159 lines
4.4 KiB
Python
159 lines
4.4 KiB
Python
"""Env management endpoints for creating ENV_INSPECT and ENV_UPDATE tasks."""
|
|
|
|
import uuid
|
|
|
|
from fastapi import APIRouter, HTTPException, status
|
|
from sqlalchemy import select
|
|
|
|
from app.db import AsyncSessionDep
|
|
from app.models.agent import Agent
|
|
from app.models.task import Task, TaskStatus
|
|
from app.models.tenant import Tenant
|
|
from app.schemas.env import EnvInspectRequest, EnvUpdateRequest
|
|
from app.schemas.task import TaskResponse
|
|
|
|
router = APIRouter(prefix="/agents/{agent_id}/env", tags=["Env Management"])
|
|
|
|
|
|
# --- Helper functions ---
|
|
|
|
|
|
async def get_tenant_by_id(db: AsyncSessionDep, tenant_id: uuid.UUID) -> Tenant | None:
|
|
"""Retrieve a tenant by ID."""
|
|
result = await db.execute(select(Tenant).where(Tenant.id == tenant_id))
|
|
return result.scalar_one_or_none()
|
|
|
|
|
|
async def get_agent_by_id(db: AsyncSessionDep, agent_id: uuid.UUID) -> Agent | None:
|
|
"""Retrieve an agent by ID."""
|
|
result = await db.execute(select(Agent).where(Agent.id == agent_id))
|
|
return result.scalar_one_or_none()
|
|
|
|
|
|
# --- Route handlers ---
|
|
|
|
|
|
@router.post(
|
|
"/inspect",
|
|
response_model=TaskResponse,
|
|
status_code=status.HTTP_201_CREATED,
|
|
)
|
|
async def inspect_env(
|
|
agent_id: uuid.UUID,
|
|
request: EnvInspectRequest,
|
|
db: AsyncSessionDep,
|
|
) -> Task:
|
|
"""
|
|
Create an ENV_INSPECT task to read env file contents.
|
|
|
|
The SysAdmin Agent will execute this task and return the env file
|
|
key-value pairs in the task result.
|
|
|
|
## Request Body
|
|
- **tenant_id**: UUID of the tenant
|
|
- **path**: Path to the env file (e.g., `/opt/letsbe/env/chatwoot.env`)
|
|
- **keys**: Optional list of specific keys to inspect (returns all if omitted)
|
|
|
|
## Response
|
|
Returns the created Task with type="ENV_INSPECT" and status="pending".
|
|
"""
|
|
# Validate tenant exists
|
|
tenant = await get_tenant_by_id(db, request.tenant_id)
|
|
if tenant is None:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail=f"Tenant {request.tenant_id} not found",
|
|
)
|
|
|
|
# Validate agent exists
|
|
agent = await get_agent_by_id(db, agent_id)
|
|
if agent is None:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail=f"Agent {agent_id} not found",
|
|
)
|
|
|
|
# Build payload
|
|
payload: dict = {"path": request.path}
|
|
if request.keys is not None:
|
|
payload["keys"] = request.keys
|
|
|
|
# Create the task
|
|
task = Task(
|
|
tenant_id=request.tenant_id,
|
|
agent_id=agent_id,
|
|
type="ENV_INSPECT",
|
|
payload=payload,
|
|
status=TaskStatus.PENDING.value,
|
|
)
|
|
|
|
db.add(task)
|
|
await db.commit()
|
|
await db.refresh(task)
|
|
|
|
return task
|
|
|
|
|
|
@router.post(
|
|
"/update",
|
|
response_model=TaskResponse,
|
|
status_code=status.HTTP_201_CREATED,
|
|
)
|
|
async def update_env(
|
|
agent_id: uuid.UUID,
|
|
request: EnvUpdateRequest,
|
|
db: AsyncSessionDep,
|
|
) -> Task:
|
|
"""
|
|
Create an ENV_UPDATE task to modify env file contents.
|
|
|
|
The SysAdmin Agent will execute this task to update or remove
|
|
key-value pairs in the specified env file.
|
|
|
|
## Request Body
|
|
- **tenant_id**: UUID of the tenant
|
|
- **path**: Path to the env file (e.g., `/opt/letsbe/env/chatwoot.env`)
|
|
- **updates**: Optional dict of key-value pairs to set or update
|
|
- **remove_keys**: Optional list of keys to remove from the env file
|
|
|
|
## Response
|
|
Returns the created Task with type="ENV_UPDATE" and status="pending".
|
|
"""
|
|
# Validate tenant exists
|
|
tenant = await get_tenant_by_id(db, request.tenant_id)
|
|
if tenant is None:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail=f"Tenant {request.tenant_id} not found",
|
|
)
|
|
|
|
# Validate agent exists
|
|
agent = await get_agent_by_id(db, agent_id)
|
|
if agent is None:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail=f"Agent {agent_id} not found",
|
|
)
|
|
|
|
# Build payload
|
|
payload: dict = {"path": request.path}
|
|
if request.updates is not None:
|
|
payload["updates"] = request.updates
|
|
if request.remove_keys is not None:
|
|
payload["remove_keys"] = request.remove_keys
|
|
|
|
# Create the task
|
|
task = Task(
|
|
tenant_id=request.tenant_id,
|
|
agent_id=agent_id,
|
|
type="ENV_UPDATE",
|
|
payload=payload,
|
|
status=TaskStatus.PENDING.value,
|
|
)
|
|
|
|
db.add(task)
|
|
await db.commit()
|
|
await db.refresh(task)
|
|
|
|
return task
|