100 lines
2.9 KiB
Python
100 lines
2.9 KiB
Python
"""Playbook endpoints for triggering infrastructure automation."""
|
|
|
|
import uuid
|
|
|
|
from fastapi import APIRouter, HTTPException, status
|
|
from pydantic import BaseModel, Field
|
|
from sqlalchemy import select
|
|
|
|
from app.db import AsyncSessionDep
|
|
from app.models.agent import Agent
|
|
from app.models.task import Task
|
|
from app.models.tenant import Tenant
|
|
from app.playbooks.chatwoot import create_chatwoot_setup_task
|
|
from app.schemas.task import TaskResponse
|
|
|
|
router = APIRouter(prefix="/tenants/{tenant_id}", tags=["Playbooks"])
|
|
|
|
|
|
class ChatwootSetupRequest(BaseModel):
|
|
"""Request body for Chatwoot setup playbook."""
|
|
|
|
agent_id: uuid.UUID | None = Field(
|
|
None, description="Optional agent UUID to assign the task to"
|
|
)
|
|
domain: str = Field(
|
|
..., min_length=1, description="Domain for Chatwoot (e.g., support.example.com)"
|
|
)
|
|
|
|
|
|
# --- 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(
|
|
"/chatwoot/setup",
|
|
response_model=TaskResponse,
|
|
status_code=status.HTTP_201_CREATED,
|
|
)
|
|
async def setup_chatwoot(
|
|
tenant_id: uuid.UUID,
|
|
request: ChatwootSetupRequest,
|
|
db: AsyncSessionDep,
|
|
) -> Task:
|
|
"""
|
|
Trigger Chatwoot setup playbook for a tenant.
|
|
|
|
Creates a COMPOSITE task with the following steps:
|
|
1. **ENV_UPDATE**: Set FRONTEND_URL and BACKEND_URL in chatwoot.env
|
|
2. **DOCKER_RELOAD**: Restart the Chatwoot stack with pull=True
|
|
|
|
## Request Body
|
|
- **agent_id**: Optional agent UUID to assign the task to immediately
|
|
- **domain**: The domain for Chatwoot (e.g., "support.example.com")
|
|
|
|
## Response
|
|
Returns the created Task with type="COMPOSITE" and status="pending".
|
|
|
|
The SysAdmin Agent will pick up this task and execute the steps in sequence.
|
|
"""
|
|
# Validate tenant exists
|
|
tenant = await get_tenant_by_id(db, tenant_id)
|
|
if tenant is None:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail=f"Tenant {tenant_id} not found",
|
|
)
|
|
|
|
# Validate agent exists if provided
|
|
if request.agent_id is not None:
|
|
agent = await get_agent_by_id(db, request.agent_id)
|
|
if agent is None:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail=f"Agent {request.agent_id} not found",
|
|
)
|
|
|
|
# Create the COMPOSITE task
|
|
task = await create_chatwoot_setup_task(
|
|
db=db,
|
|
tenant_id=tenant_id,
|
|
agent_id=request.agent_id,
|
|
domain=request.domain,
|
|
)
|
|
|
|
return task
|