138 lines
3.9 KiB
Python
138 lines
3.9 KiB
Python
from uuid import UUID
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, status
|
|
|
|
from adapter.di.container import AppContainer
|
|
from adapter.http.fastapi.dependencies import (
|
|
get_container,
|
|
get_create_sandbox,
|
|
get_delete_sandbox,
|
|
)
|
|
from adapter.http.fastapi.schemas import (
|
|
CreateSandboxRequest,
|
|
DeleteSandboxResponse,
|
|
ErrorResponse,
|
|
HealthResponse,
|
|
SandboxEndpointResponse,
|
|
SandboxSessionResponse,
|
|
)
|
|
from domain.error import SandboxConflictError, SandboxError, SandboxStartError
|
|
from domain.sandbox import SandboxSession
|
|
from usecase.sandbox import (
|
|
CreateSandbox,
|
|
CreateSandboxCommand,
|
|
DeleteSandbox,
|
|
DeleteSandboxCommand,
|
|
DeleteSandboxResult,
|
|
)
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.get(
|
|
'/health',
|
|
response_model=HealthResponse,
|
|
status_code=status.HTTP_200_OK,
|
|
)
|
|
def health(container: AppContainer = Depends(get_container)) -> HealthResponse:
|
|
return HealthResponse(
|
|
status='ok',
|
|
app=container.config.app.name,
|
|
env=container.config.app.env,
|
|
)
|
|
|
|
|
|
@router.post(
|
|
'/create',
|
|
response_model=SandboxSessionResponse,
|
|
responses={
|
|
status.HTTP_409_CONFLICT: {'model': ErrorResponse},
|
|
status.HTTP_503_SERVICE_UNAVAILABLE: {'model': ErrorResponse},
|
|
status.HTTP_500_INTERNAL_SERVER_ERROR: {'model': ErrorResponse},
|
|
},
|
|
status_code=status.HTTP_200_OK,
|
|
)
|
|
def create_sandbox(
|
|
request: CreateSandboxRequest,
|
|
usecase: CreateSandbox = Depends(get_create_sandbox),
|
|
) -> SandboxSessionResponse:
|
|
try:
|
|
session = usecase.execute(
|
|
CreateSandboxCommand(
|
|
chat_id=request.chat_id,
|
|
agent_id=request.agent_id,
|
|
volume_host_path=request.volume_host_path,
|
|
)
|
|
)
|
|
except SandboxConflictError as exc:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_409_CONFLICT,
|
|
detail=str(exc),
|
|
) from exc
|
|
except SandboxStartError as exc:
|
|
detail = f'{exc}: {exc.reason}' if exc.reason else str(exc)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
|
detail=detail,
|
|
) from exc
|
|
except SandboxError as exc:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail=str(exc),
|
|
) from exc
|
|
|
|
return _to_sandbox_session_response(session)
|
|
|
|
|
|
@router.delete(
|
|
'/sandboxes/{chat_id}',
|
|
response_model=DeleteSandboxResponse,
|
|
responses={
|
|
status.HTTP_500_INTERNAL_SERVER_ERROR: {'model': ErrorResponse},
|
|
},
|
|
status_code=status.HTTP_200_OK,
|
|
)
|
|
def delete_sandbox(
|
|
chat_id: UUID,
|
|
usecase: DeleteSandbox = Depends(get_delete_sandbox),
|
|
) -> DeleteSandboxResponse:
|
|
try:
|
|
result = usecase.execute(DeleteSandboxCommand(chat_id=chat_id))
|
|
except SandboxError as exc:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail=str(exc),
|
|
) from exc
|
|
|
|
return _to_delete_sandbox_response(result)
|
|
|
|
|
|
def _to_sandbox_session_response(session: SandboxSession) -> SandboxSessionResponse:
|
|
if session.endpoint is None:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail='sandbox_endpoint_unavailable',
|
|
)
|
|
|
|
return SandboxSessionResponse(
|
|
session_id=session.session_id,
|
|
chat_id=session.chat_id,
|
|
agent_id=session.agent_id,
|
|
volume_host_path=session.volume_host_path,
|
|
container_id=session.container_id,
|
|
endpoint=SandboxEndpointResponse(
|
|
ip=session.endpoint.ip,
|
|
port=session.endpoint.port,
|
|
),
|
|
status=session.status.value,
|
|
expires_at=session.expires_at,
|
|
)
|
|
|
|
|
|
def _to_delete_sandbox_response(result: DeleteSandboxResult) -> DeleteSandboxResponse:
|
|
return DeleteSandboxResponse(
|
|
chat_id=result.chat_id,
|
|
result=result.result,
|
|
session_id=result.session_id,
|
|
container_id=result.container_id,
|
|
)
|