"""vSphere Automation API error shapes.""" from __future__ import annotations from typing import Any from fastapi import HTTPException class VsphereError(HTTPException): """HTTPException with a vSphere Automation-style JSON body.""" def __init__( self, status_code: int, *, error_type: str, messages: list[dict[str, Any]] | None = None, data: dict[str, Any] | None = None, ) -> None: detail: dict[str, Any] = { "error_type": error_type, "messages": messages or [{"default_message": error_type, "id": error_type, "args": []}], } if data is not None: detail["data"] = data super().__init__(status_code=status_code, detail=detail) def unauthenticated(message: str = "Authentication required") -> VsphereError: return VsphereError( 401, error_type="unauthenticated", messages=[ { "default_message": message, "id": "com.vmware.vapi.endpoint.unauthenticated", "args": [], } ], ) def not_found(message: str = "Not found", *, args: list[Any] | None = None) -> VsphereError: return VsphereError( 404, error_type="not_found", messages=[ { "default_message": message, "id": "com.vmware.vapi.std.errors.not_found", "args": list(args or []), } ], ) def no_such(resource: str, resource_id: str) -> VsphereError: """Native not-found with the missing id in the message (Ingress-friendly JSON).""" message = f"No such {resource} ('{resource_id}')" return VsphereError( 404, error_type="not_found", messages=[ { "default_message": message, "id": "com.vmware.vapi.std.errors.not_found", "args": [resource_id], } ], data={resource: message}, ) def already_exists(message: str = "Already exists") -> VsphereError: return VsphereError( 400, error_type="already_exists", messages=[ { "default_message": message, "id": "com.vmware.vapi.std.errors.already_exists", "args": [], } ], ) def invalid_argument(message: str = "Invalid argument") -> VsphereError: return VsphereError( 400, error_type="invalid_argument", messages=[ { "default_message": message, "id": "com.vmware.vapi.std.errors.invalid_argument", "args": [], } ], ) def unauthorized(message: str = "Unauthorized") -> VsphereError: return VsphereError( 403, error_type="unauthorized", messages=[ { "default_message": message, "id": "com.vmware.vapi.std.errors.unauthorized", "args": [], } ], ) def not_implemented(message: str = "Not implemented for active contract version") -> VsphereError: return VsphereError( 501, error_type="error", messages=[ { "default_message": message, "id": "com.vmware.vapi.std.errors.error", "args": [], } ], )