"""Pydantic request and response models for the UVM HTTP API.""" from __future__ import annotations from ipaddress import IPv4Address from typing import Literal from pydantic import BaseModel, ConfigDict, Field, SecretStr from .domain import VmRecord class HealthResponse(BaseModel): status: str = "ok" class InstallRequest(BaseModel): model_config = ConfigDict(extra="forbid") force: bool = False class InstallResponse(BaseModel): firecracker: str kernel: str rootfs: str class PortRuleModel(BaseModel): """A private guest TCP port; HTTP and HTTPS are descriptive labels only.""" model_config = ConfigDict(extra="forbid") port: int = Field(strict=True, ge=1, le=65535) protocol: Literal["TCP", "HTTP", "HTTPS"] = "TCP" class VmCreateRequest(BaseModel): model_config = ConfigDict(extra="forbid") cpu: float = Field(default=1, gt=0) ram: str | int | float = "512" guest_ip: IPv4Address | None = None username: str = "root" password: SecretStr = SecretStr("root") name: str | None = None ports: list[PortRuleModel] | None = None no_default_ports: bool = Field(default=False, strict=True) class VmResponse(BaseModel): id: str name: str | None cpu: float ram_mib: int guest_ip: str gateway: str mac: str username: str status: str observed_status: str ports: list[PortRuleModel] | None policy_status: str operation: str | None pid: int | None created_at: int updated_at: int last_error: str | None class DestroyResponse(BaseModel): id: str status: str = "terminated" def vm_response( vm: VmRecord, *, observed_status: str | None = None, policy_status: str = "unknown", ) -> VmResponse: return VmResponse( id=vm.id, name=vm.name, cpu=vm.cpu, ram_mib=vm.ram_mib, guest_ip=vm.guest_ip, gateway=vm.gateway, mac=vm.mac, username=vm.username, status=vm.status, observed_status=observed_status if observed_status is not None else vm.status, ports=( [PortRuleModel(port=rule.port, protocol=rule.protocol) for rule in vm.ports] if vm.ports is not None else None ), policy_status=policy_status, operation=vm.operation, pid=vm.pid, created_at=vm.created_at, updated_at=vm.updated_at, last_error=vm.last_error, )