Fix Nova/Cinder stateful CRUD so the full surface and Pulumi matrix pass clean.

Persist aggregates and server security groups in domain tables, add Cinder quota
show from DB-backed defaults, align unit tests with OpenStack series, auto-pick
Keystone :5000/:15000 for smoke, and document test locations plus 6514/6514 results.
This commit is contained in:
2026-07-18 09:38:45 +03:00
parent 6cffb6a95f
commit 147f04c9a2
29 changed files with 843 additions and 346 deletions
+25 -53
View File
@@ -1,23 +1,16 @@
"""Web console route tests."""
from pathlib import Path
from httpx import ASGITransport, AsyncClient
from app.config import Settings
from app.main import create_app
from tests.unit.test_health import FakeDatabase
_BUNDLED = Path(
"contracts/e61a893e996d05d376579226e7dfbedbcfce8b71787adacffbc557e6e35901c1/snapshot.json"
)
async def test_root_console_is_served() -> None:
app = create_app(database_factory=lambda _settings: FakeDatabase(True), worker_factories=())
async with app.router.lifespan_context(app):
async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client:
response = await client.get("/")
response = await client.get("/console")
assert response.status_code == 200
assert "OpenStack API Emulator" in response.text
assert "openstack" in response.text
@@ -35,60 +28,36 @@ async def test_root_console_is_served() -> None:
assert "Request body" in response.text
async def test_ui_method_nodes_is_implemented() -> None:
settings = Settings(contract_snapshot=_BUNDLED)
app = create_app(
settings=settings,
database_factory=lambda _settings: FakeDatabase(True),
worker_factories=(),
)
async def test_ui_method_server_list_is_implemented() -> None:
app = create_app(database_factory=lambda _settings: FakeDatabase(True), worker_factories=())
async with app.router.lifespan_context(app):
async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client:
method = await client.get(
"/ui/api/method",
params={"major": 7, "path": "/nodes", "verb": "GET"},
)
assert method.status_code == 200
assert method.json()["implemented"] is True
async def test_ui_method_read_group_is_implemented() -> None:
settings = Settings(contract_snapshot=_BUNDLED)
app = create_app(
settings=settings,
database_factory=lambda _settings: FakeDatabase(True),
worker_factories=(),
)
async with app.router.lifespan_context(app):
async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client:
method = await client.get(
"/ui/api/method",
params={"major": 9, "path": "/access/groups/{groupid}", "verb": "GET"},
params={"major": 9, "path": "/v2.1/servers", "verb": "GET"},
)
assert method.status_code == 200
payload = method.json()
assert payload["name"] == "read_group"
assert payload["implemented"] is True
assert payload["name"] == "server_list"
assert payload["service"] == "nova"
async def test_ui_catalog_read_group_is_implemented() -> None:
settings = Settings(contract_snapshot=_BUNDLED)
app = create_app(
settings=settings,
database_factory=lambda _settings: FakeDatabase(True),
worker_factories=(),
)
async def test_ui_catalog_server_list_is_implemented() -> None:
app = create_app(database_factory=lambda _settings: FakeDatabase(True), worker_factories=())
async with app.router.lifespan_context(app):
async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client:
catalog = await client.get("/ui/api/catalog", params={"major": 9})
assert catalog.status_code == 200
body = catalog.json()
assert body["source_version"] == "openstack-dalmatian"
methods = {
(path["path"], method["name"]): method["implemented"]
for category in catalog.json()["categories"]
for category in body["categories"]
for path in category["paths"]
for method in path["methods"]
}
assert methods[("/access/groups/{groupid}", "read_group")] is True
assert methods[("/v2.1/servers", "server_list")] is True
async def test_demo_api_requires_database() -> None:
@@ -102,23 +71,26 @@ async def test_demo_api_requires_database() -> None:
async def test_ui_versions_and_catalog_endpoints() -> None:
settings = Settings(contract_snapshot=_BUNDLED)
app = create_app(
settings=settings,
database_factory=lambda _settings: FakeDatabase(True),
worker_factories=(),
)
app = create_app(database_factory=lambda _settings: FakeDatabase(True), worker_factories=())
async with app.router.lifespan_context(app):
async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client:
versions = await client.get("/ui/api/versions")
assert versions.status_code == 200
assert {item["major"] for item in versions.json()["majors"]} == {6, 7, 8, 9}
majors = versions.json()["majors"]
assert {item["major"] for item in majors} == {6, 7, 8, 9}
assert {item["latest_version"] for item in majors} == {
"yoga",
"antelope",
"caracal",
"dalmatian",
}
catalog = await client.get("/ui/api/catalog", params={"major": 9})
assert catalog.status_code == 200
assert catalog.json()["source_version"] == "9.2.3"
assert catalog.json()["source_version"] == "openstack-dalmatian"
method = await client.get(
"/ui/api/method",
params={"major": 9, "path": "/version", "verb": "GET"},
params={"major": 9, "path": "/v2.1/servers", "verb": "GET"},
)
assert method.status_code == 200
assert method.json()["path"] == "/version"
assert method.json()["path"] == "/v2.1/servers"
assert method.json()["name"] == "server_list"