sections.py•7.77 kB
"""
API routes for section management.
"""
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession
from typing import Dict, Any, List, Optional
from src.database.database import get_db
from src.database import crud
from src.config.models import SectionCreate, SectionUpdate, SectionAction
router = APIRouter(
prefix="/sections",
tags=["sections"],
)
@router.get("/", response_model=List[Dict[str, Any]])
async def get_sections(db: AsyncSession = Depends(get_db)):
"""Get all sections."""
sections = await crud.get_sections(db)
return [
{
"id": section.id,
"name": section.name,
"description": section.description,
"settings": section.settings,
"created_at": section.created_at,
"updated_at": section.updated_at
}
for section in sections
]
@router.get("/{section_id}", response_model=Dict[str, Any])
async def get_section(section_id: int, db: AsyncSession = Depends(get_db)):
"""Get a section by ID."""
section = await crud.get_section_by_id(db, section_id)
if not section:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Section with ID {section_id} not found"
)
# Get servers in this section
servers = await crud.get_servers(db, section_id)
return {
"id": section.id,
"name": section.name,
"description": section.description,
"settings": section.settings,
"created_at": section.created_at,
"updated_at": section.updated_at,
"servers": [
{
"id": server.id,
"name": server.name,
"description": server.description,
"status": server.status
}
for server in servers
]
}
@router.post("/", response_model=Dict[str, Any], status_code=status.HTTP_201_CREATED)
async def create_section(section_data: SectionCreate, db: AsyncSession = Depends(get_db)):
"""Create a new section."""
# Check if section with this name already exists
existing_section = await crud.get_section_by_name(db, section_data.name)
if existing_section:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT,
detail=f"Section with name '{section_data.name}' already exists"
)
try:
section = await crud.create_section(db, section_data.dict())
return {
"id": section.id,
"name": section.name,
"description": section.description,
"settings": section.settings,
"created_at": section.created_at,
"updated_at": section.updated_at
}
except Exception as e:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Failed to create section: {str(e)}"
)
@router.put("/{section_id}", response_model=Dict[str, Any])
async def update_section(
section_id: int,
section_data: SectionUpdate,
db: AsyncSession = Depends(get_db)
):
"""Update a section."""
# Check if section exists
section = await crud.get_section_by_id(db, section_id)
if not section:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Section with ID {section_id} not found"
)
# If name is being updated, check if it conflicts with existing section
if section_data.name and section_data.name != section.name:
existing_section = await crud.get_section_by_name(db, section_data.name)
if existing_section and existing_section.id != section_id:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT,
detail=f"Section with name '{section_data.name}' already exists"
)
try:
updated_section = await crud.update_section(db, section_id, section_data.dict(exclude_unset=True))
if not updated_section:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Section with ID {section_id} not found"
)
return {
"id": updated_section.id,
"name": updated_section.name,
"description": updated_section.description,
"settings": updated_section.settings,
"created_at": updated_section.created_at,
"updated_at": updated_section.updated_at
}
except HTTPException:
raise
except Exception as e:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Failed to update section: {str(e)}"
)
@router.delete("/{section_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_section(section_id: int, db: AsyncSession = Depends(get_db)):
"""Delete a section."""
# Check if section exists
section = await crud.get_section_by_id(db, section_id)
if not section:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Section with ID {section_id} not found"
)
# Check if section has servers
servers = await crud.get_servers(db, section_id)
if servers:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT,
detail=f"Cannot delete section with ID {section_id} because it contains servers"
)
success = await crud.delete_section(db, section_id)
if not success:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Failed to delete section with ID {section_id}"
)
@router.post("/{section_id}/{action}", response_model=Dict[str, Any])
async def section_action(
section_id: int,
action: str,
action_data: Optional[SectionAction] = None,
db: AsyncSession = Depends(get_db)
):
"""Perform an action on a section (start, stop, restart)."""
# Check if section exists
section = await crud.get_section_by_id(db, section_id)
if not section:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Section with ID {section_id} not found"
)
# Initialize orchestration engine
from src.orchestration.orchestration_engine import OrchestrationEngine
from src.config.config_manager import ConfigManager
from src.runtime.runtime_engine import RuntimeEngine
config_manager = ConfigManager()
runtime_engine = RuntimeEngine()
orchestration_engine = OrchestrationEngine(config_manager, runtime_engine)
# Set default values if action_data is not provided
concurrency = 5
force = False
timeout = 30
if action_data:
concurrency = action_data.concurrency or concurrency
force = action_data.force or force
timeout = action_data.timeout or timeout
# Perform the action
if action == "start":
task_id = await orchestration_engine.start_section(db, section_id, concurrency)
elif action == "stop":
task_id = await orchestration_engine.stop_section(db, section_id, concurrency, force, timeout)
elif action == "restart":
task_id = await orchestration_engine.restart_section(db, section_id, concurrency, force, timeout)
else:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Invalid action: {action}. Must be one of: start, stop, restart"
)
return {
"task_id": task_id,
"section_id": section_id,
"section_name": section.name,
"action": action,
"status": "accepted"
}