175 lines
5.7 KiB
Python
175 lines
5.7 KiB
Python
"""
|
|
Routes API pour les builtin playbooks (collecte métriques).
|
|
"""
|
|
|
|
import asyncio
|
|
from typing import Optional
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, BackgroundTasks
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.core.config import settings
|
|
from app.core.dependencies import get_db, verify_api_key
|
|
from app.crud.host import HostRepository
|
|
from app.crud.host_metrics import HostMetricsRepository
|
|
from app.services import ansible_service, ws_manager
|
|
from app.services.builtin_playbooks import (
|
|
BuiltinPlaybookService,
|
|
BUILTIN_PLAYBOOKS,
|
|
get_builtin_playbook_service,
|
|
init_builtin_playbook_service,
|
|
)
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
def _get_service() -> BuiltinPlaybookService:
|
|
"""Récupère ou initialise le service builtin playbooks."""
|
|
try:
|
|
return get_builtin_playbook_service()
|
|
except RuntimeError:
|
|
return init_builtin_playbook_service(settings.ansible_dir, ansible_service)
|
|
|
|
|
|
@router.get("")
|
|
async def list_builtin_playbooks(api_key_valid: bool = Depends(verify_api_key)):
|
|
"""Liste tous les builtin playbooks disponibles."""
|
|
return [pb.model_dump() for pb in BUILTIN_PLAYBOOKS.values()]
|
|
|
|
|
|
@router.get("/{builtin_id}")
|
|
async def get_builtin_playbook(
|
|
builtin_id: str,
|
|
api_key_valid: bool = Depends(verify_api_key)
|
|
):
|
|
"""Récupère les détails d'un builtin playbook."""
|
|
if builtin_id not in BUILTIN_PLAYBOOKS:
|
|
raise HTTPException(status_code=404, detail=f"Builtin playbook '{builtin_id}' non trouvé")
|
|
return BUILTIN_PLAYBOOKS[builtin_id].model_dump()
|
|
|
|
|
|
@router.post("/execute")
|
|
async def execute_builtin_playbook(
|
|
builtin_id: str,
|
|
target: str,
|
|
api_key_valid: bool = Depends(verify_api_key),
|
|
db_session: AsyncSession = Depends(get_db)
|
|
):
|
|
"""Exécute un builtin playbook sur une cible."""
|
|
if builtin_id not in BUILTIN_PLAYBOOKS:
|
|
raise HTTPException(status_code=404, detail=f"Builtin playbook '{builtin_id}' non trouvé")
|
|
|
|
service = _get_service()
|
|
result = await service.execute_builtin(builtin_id, target)
|
|
|
|
# Si collecte de métriques, sauvegarder en BD
|
|
if BUILTIN_PLAYBOOKS[builtin_id].collect_metrics and result.get("success"):
|
|
metrics_repo = HostMetricsRepository(db_session)
|
|
host_repo = HostRepository(db_session)
|
|
|
|
for hostname, metrics_data in result.get("parsed_metrics", {}).items():
|
|
# Trouver l'host_id
|
|
host = await host_repo.get_by_name(hostname)
|
|
if host:
|
|
metrics_create = service.create_metrics_from_parsed(
|
|
host_id=host.id,
|
|
parsed_data=metrics_data,
|
|
builtin_id=builtin_id,
|
|
execution_time_ms=result.get("execution_time_ms", 0)
|
|
)
|
|
await metrics_repo.create(**metrics_create.model_dump())
|
|
|
|
await db_session.commit()
|
|
|
|
await ws_manager.broadcast({
|
|
"type": "builtin_executed",
|
|
"data": {
|
|
"builtin_id": builtin_id,
|
|
"target": target,
|
|
"success": result.get("success", False)
|
|
}
|
|
})
|
|
|
|
return result
|
|
|
|
|
|
@router.post("/execute-background")
|
|
async def execute_builtin_playbook_background(
|
|
builtin_id: str,
|
|
target: str,
|
|
background_tasks: BackgroundTasks,
|
|
api_key_valid: bool = Depends(verify_api_key)
|
|
):
|
|
"""Exécute un builtin playbook en arrière-plan."""
|
|
if builtin_id not in BUILTIN_PLAYBOOKS:
|
|
raise HTTPException(status_code=404, detail=f"Builtin playbook '{builtin_id}' non trouvé")
|
|
|
|
async def run_in_background():
|
|
service = _get_service()
|
|
result = await service.execute_builtin(builtin_id, target)
|
|
await ws_manager.broadcast({
|
|
"type": "builtin_executed",
|
|
"data": {
|
|
"builtin_id": builtin_id,
|
|
"target": target,
|
|
"success": result.get("success", False)
|
|
}
|
|
})
|
|
|
|
# Planifier l'exécution en arrière-plan
|
|
background_tasks.add_task(asyncio.create_task, run_in_background())
|
|
|
|
return {
|
|
"message": f"Builtin playbook '{builtin_id}' planifié pour exécution sur {target}",
|
|
"builtin_id": builtin_id,
|
|
"target": target
|
|
}
|
|
|
|
|
|
@router.post("/collect-all")
|
|
async def collect_all_metrics(
|
|
background_tasks: BackgroundTasks,
|
|
api_key_valid: bool = Depends(verify_api_key),
|
|
db_session: AsyncSession = Depends(get_db)
|
|
):
|
|
"""Collecte les métriques de tous les hôtes."""
|
|
host_repo = HostRepository(db_session)
|
|
hosts = await host_repo.list(limit=1000)
|
|
|
|
if not hosts:
|
|
return {"message": "Aucun hôte trouvé", "hosts_count": 0}
|
|
|
|
async def collect_for_all():
|
|
service = _get_service()
|
|
results = []
|
|
|
|
for host in hosts:
|
|
try:
|
|
result = await service.execute_builtin("collect_system_info", host.name)
|
|
results.append({
|
|
"host": host.name,
|
|
"success": result.get("success", False)
|
|
})
|
|
except Exception as e:
|
|
results.append({
|
|
"host": host.name,
|
|
"success": False,
|
|
"error": str(e)
|
|
})
|
|
|
|
await ws_manager.broadcast({
|
|
"type": "metrics_collection_complete",
|
|
"data": {
|
|
"total": len(hosts),
|
|
"success": sum(1 for r in results if r.get("success")),
|
|
"failed": sum(1 for r in results if not r.get("success"))
|
|
}
|
|
})
|
|
|
|
background_tasks.add_task(asyncio.create_task, collect_for_all())
|
|
|
|
return {
|
|
"message": f"Collecte des métriques lancée pour {len(hosts)} hôte(s)",
|
|
"hosts_count": len(hosts)
|
|
}
|