"""Authenticated tool catalog, installation jobs, and guest inventory.""" from __future__ import annotations from fastapi import APIRouter, Depends, status from ..api_models import ToolCatalogResponse, ToolInstallRequest, ToolJobResponse, VmToolsResponse from ..app import Application from ..errors import UvmError from ..tool_catalog import CATALOG, normalize_tools from .dependencies import get_authorized_application router = APIRouter(tags=["tools"]) def tool_service(application): service = getattr(application, "tools", None) if service is None: raise UvmError("guest tool installation is unavailable in this application") return service @router.get("/tools", response_model=list[ToolCatalogResponse]) def catalog(application: Application = Depends(get_authorized_application)): return list(CATALOG) @router.get("/vms/{vm_id}/tools", response_model=VmToolsResponse) def vm_tools(vm_id: str, refresh: bool = False, application: Application = Depends(get_authorized_application)): """Return cached observations; refresh=true probes the running guest without installing.""" return tool_service(application).snapshot(vm_id, refresh=refresh) @router.post("/vms/{vm_id}/tools/install", response_model=ToolJobResponse, status_code=status.HTTP_202_ACCEPTED) def install_tools(vm_id: str, request: ToolInstallRequest, application: Application = Depends(get_authorized_application)): return tool_service(application).submit( vm_id, normalize_tools([item.model_dump() for item in request.tools]), start_if_stopped=request.start_if_stopped, restart=request.restart, request_id=request.request_id, ) @router.get("/vms/{vm_id}/tools/jobs/{job_id}", response_model=ToolJobResponse) def tool_job(vm_id: str, job_id: str, application: Application = Depends(get_authorized_application)): return tool_service(application).store.get_job(vm_id, job_id)