6033967e6a
Ship Keystone auth, multi-service handlers (Yoga→Dalmatian), Compose/Helm packaging, API contract packs, and pytest/Pulumi coverage labs.
135 lines
5.3 KiB
Python
135 lines
5.3 KiB
Python
"""Resource pool semantic handlers."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import uuid
|
|
from typing import Any
|
|
|
|
from fastapi import Request
|
|
|
|
from app.api.errors import ApiError
|
|
from app.api.registry import HandlerRegistry
|
|
from app.handlers.common import database, state, values
|
|
from app.simulation.seed import CLUSTER_ID, stable_id
|
|
|
|
|
|
async def _pool_members(request: Request, pool_id: uuid.UUID) -> list[str]:
|
|
rows = await database(request).pool.fetch(
|
|
"""SELECT r.external_id FROM pool_members pm
|
|
JOIN resources r ON r.id = pm.resource_id
|
|
WHERE pm.pool_id=$1 ORDER BY r.external_id::integer""",
|
|
pool_id,
|
|
)
|
|
return [str(row["external_id"]) for row in rows]
|
|
|
|
|
|
def register_pool_handlers(registry: HandlerRegistry) -> None:
|
|
async def pool_list(request: Request, inputs: dict[str, Any]) -> list[dict[str, Any]]:
|
|
payload = values(inputs)
|
|
filter_poolid = payload.get("poolid")
|
|
rows = await database(request).pool.fetch(
|
|
"""SELECT id, pool_id, comment, metadata FROM pools
|
|
WHERE ($1::text IS NULL OR pool_id=$1)
|
|
ORDER BY pool_id""",
|
|
str(filter_poolid) if filter_poolid is not None else None,
|
|
)
|
|
result: list[dict[str, Any]] = []
|
|
for row in rows:
|
|
metadata = state(row["metadata"])
|
|
members = await _pool_members(request, row["id"])
|
|
if not members and isinstance(metadata.get("members"), list):
|
|
members = [str(item) for item in metadata["members"]]
|
|
item: dict[str, Any] = {
|
|
"poolid": str(row["pool_id"]),
|
|
"members": members,
|
|
}
|
|
if row["comment"] is not None:
|
|
item["comment"] = str(row["comment"])
|
|
elif metadata.get("comment"):
|
|
item["comment"] = str(metadata["comment"])
|
|
result.append(item)
|
|
return result
|
|
|
|
async def pool_get(request: Request, inputs: dict[str, Any]) -> dict[str, Any]:
|
|
items = await pool_list(request, inputs)
|
|
if not items:
|
|
raise ApiError(404, "pool does not exist")
|
|
return items[0]
|
|
|
|
async def pool_create(request: Request, inputs: dict[str, Any]) -> None:
|
|
payload = values(inputs)
|
|
poolid = str(payload["poolid"])
|
|
exists = await database(request).pool.fetchval(
|
|
"SELECT EXISTS(SELECT 1 FROM pools WHERE pool_id=$1)",
|
|
poolid,
|
|
)
|
|
if exists:
|
|
raise ApiError(409, "pool already exists")
|
|
await database(request).pool.execute(
|
|
"""INSERT INTO pools(id, cluster_id, pool_id, comment, metadata)
|
|
VALUES($1, $2, $3, $4, $5::jsonb)""",
|
|
stable_id(f"pool:{poolid}"),
|
|
CLUSTER_ID,
|
|
poolid,
|
|
payload.get("comment"),
|
|
json.dumps({"members": []}, sort_keys=True),
|
|
)
|
|
|
|
async def pool_update(request: Request, inputs: dict[str, Any]) -> None:
|
|
payload = values(inputs)
|
|
poolid = str(payload["poolid"])
|
|
pool_row = await database(request).pool.fetchrow(
|
|
"SELECT id FROM pools WHERE pool_id=$1",
|
|
poolid,
|
|
)
|
|
if pool_row is None:
|
|
raise ApiError(404, "pool does not exist")
|
|
if payload.get("comment") is not None:
|
|
await database(request).pool.execute(
|
|
"UPDATE pools SET comment=$2 WHERE pool_id=$1",
|
|
poolid,
|
|
payload.get("comment"),
|
|
)
|
|
if "vms" in payload:
|
|
vmids = [item.strip() for item in str(payload["vms"]).split(",") if item.strip()]
|
|
for vmid in vmids:
|
|
resource = await database(request).pool.fetchrow(
|
|
"""SELECT id FROM resources
|
|
WHERE kind IN ('qemu', 'lxc') AND external_id=$1""",
|
|
vmid,
|
|
)
|
|
if resource is None:
|
|
continue
|
|
await database(request).pool.execute(
|
|
"""INSERT INTO pool_members(pool_id, resource_id)
|
|
VALUES($1, $2) ON CONFLICT DO NOTHING""",
|
|
pool_row["id"],
|
|
resource["id"],
|
|
)
|
|
if "delete" in payload:
|
|
vmids = [item.strip() for item in str(payload["delete"]).split(",") if item.strip()]
|
|
await database(request).pool.execute(
|
|
"""DELETE FROM pool_members pm USING resources r
|
|
WHERE pm.pool_id=$1 AND pm.resource_id=r.id AND r.external_id = ANY($2::text[])""",
|
|
pool_row["id"],
|
|
vmids,
|
|
)
|
|
|
|
async def pool_delete(request: Request, inputs: dict[str, Any]) -> None:
|
|
poolid = str(values(inputs)["poolid"])
|
|
status = await database(request).pool.execute(
|
|
"DELETE FROM pools WHERE pool_id=$1",
|
|
poolid,
|
|
)
|
|
if status != "DELETE 1":
|
|
raise ApiError(404, "pool does not exist")
|
|
|
|
registry.register("/pools", "GET", pool_list)
|
|
registry.register("/pools", "POST", pool_create)
|
|
registry.register("/pools", "PUT", pool_update)
|
|
registry.register("/pools", "DELETE", pool_delete)
|
|
registry.register("/pools/{poolid}", "GET", pool_get)
|
|
registry.register("/pools/{poolid}", "PUT", pool_update)
|
|
registry.register("/pools/{poolid}", "DELETE", pool_delete)
|