guardia-manager/backend/routers/platform_mgmt.py
2026-06-07 08:13:48 +09:00

120 lines
5.7 KiB
Python

"""Manager Gen6 — 플랫폼 관리: 멀티클러스터·GitOps·배포맵·서비스카탈로그"""
import uuid
from datetime import datetime
from typing import Any, Dict, List, Optional
from fastapi import APIRouter, HTTPException, Query
from pydantic import BaseModel
router = APIRouter(prefix="/api/platform-mgmt", tags=["Platform Management"])
_clusters: Dict[str, Dict] = {}
_gitops: Dict[str, Dict] = {}
_service_map: Dict[str, Dict] = {}
class ClusterCreate(BaseModel):
name: str; type: str = "kubernetes" # kubernetes|docker-swarm|bare-metal
endpoint: str; region: str = "kr-1"; tags: List[str] = []
class GitOpsCreate(BaseModel):
name: str; repo_url: str; branch: str = "main"
target_cluster: str; auto_sync: bool = True
class ServiceMapEntry(BaseModel):
service: str; version: str; cluster: str
replicas: int = 1; expose: bool = True
# ── 멀티 클러스터 ─────────────────────────────────────────────────────────
@router.post("/clusters")
async def register_cluster(cluster: ClusterCreate):
cid = f"CLU-{uuid.uuid4().hex[:8].upper()}"
_clusters[cid] = {**cluster.model_dump(), "id": cid, "status": "connected",
"node_count": 3, "registered_at": datetime.utcnow().isoformat()}
return _clusters[cid]
@router.get("/clusters")
async def list_clusters():
clusters = list(_clusters.values()) or [
{"id": "CLU-PROD01", "name": "production", "type": "kubernetes", "node_count": 5, "status": "healthy"},
{"id": "CLU-DEV01", "name": "development", "type": "kubernetes", "node_count": 2, "status": "healthy"},
]
return {"clusters": clusters, "total": len(clusters)}
@router.get("/clusters/{cid}/nodes")
async def cluster_nodes(cid: str):
return {"cluster_id": cid, "nodes": [
{"name": "node-01", "status": "ready", "cpu_usage": 42.1, "mem_usage": 67.8, "pods": 12},
{"name": "node-02", "status": "ready", "cpu_usage": 38.4, "mem_usage": 55.2, "pods": 9},
{"name": "node-03", "status": "ready", "cpu_usage": 51.0, "mem_usage": 71.3, "pods": 14},
]}
@router.get("/clusters/{cid}/workloads")
async def cluster_workloads(cid: str):
return {"cluster_id": cid, "workloads": [
{"name": "guardia-itsm", "namespace": "default", "replicas": "2/2", "status": "running"},
{"name": "guardia-manager", "namespace": "default", "replicas": "1/1", "status": "running"},
{"name": "postgres", "namespace": "data", "replicas": "1/1", "status": "running"},
]}
# ── GitOps ────────────────────────────────────────────────────────────────
@router.post("/gitops")
async def create_gitops(gitops: GitOpsCreate):
gid = f"GIT-{uuid.uuid4().hex[:8].upper()}"
_gitops[gid] = {**gitops.model_dump(), "id": gid, "status": "synced",
"last_sync": datetime.utcnow().isoformat(), "drift": False}
return _gitops[gid]
@router.get("/gitops")
async def list_gitops():
items = list(_gitops.values()) or [
{"id": "GIT-001", "name": "guardia-itsm-deploy", "branch": "main", "status": "synced", "drift": False},
]
return {"gitops": items, "total": len(items)}
@router.post("/gitops/{gid}/sync")
async def sync_gitops(gid: str):
g = _gitops.get(gid)
if not g: raise HTTPException(404)
g["last_sync"] = datetime.utcnow().isoformat(); g["drift"] = False
return {"synced": True, **g}
@router.get("/gitops/{gid}/diff")
async def gitops_diff(gid: str):
return {"gitops_id": gid, "diff": [
{"resource": "Deployment/guardia-itsm", "type": "modified", "fields": ["image.tag"]},
], "drift_detected": False}
# ── 서비스 맵 (배포 위상도) ────────────────────────────────────────────────
@router.post("/service-map")
async def register_service(entry: ServiceMapEntry):
eid = f"SVC-{uuid.uuid4().hex[:8].upper()}"
_service_map[eid] = {**entry.model_dump(), "id": eid, "health": "healthy",
"registered_at": datetime.utcnow().isoformat()}
return _service_map[eid]
@router.get("/service-map")
async def get_service_map():
svcs = list(_service_map.values()) or [
{"service": "guardia-itsm", "cluster": "production", "version": "2.1.0", "health": "healthy"},
{"service": "guardia-manager", "cluster": "production", "version": "1.5.0", "health": "healthy"},
{"service": "guardia-messenger", "cluster": "N/A", "version": "1.0.0", "health": "healthy"},
]
return {"services": svcs, "edges": [
{"from": "guardia-manager", "to": "guardia-itsm", "type": "api"},
]}
# ── 배포 파이프라인 관제 ────────────────────────────────────────────────────
@router.get("/pipelines")
async def list_pipelines():
return {"pipelines": [
{"id": "PIPE-001", "name": "guardia-itsm-ci", "status": "success", "last_run": datetime.utcnow().isoformat(), "duration_sec": 124},
{"id": "PIPE-002", "name": "guardia-manager-ci", "status": "success", "last_run": datetime.utcnow().isoformat(), "duration_sec": 87},
]}
@router.post("/pipelines/{pid}/trigger")
async def trigger_pipeline(pid: str, branch: str = "main"):
return {"pipeline_id": pid, "branch": branch, "triggered": True, "run_id": str(uuid.uuid4()),
"ts": datetime.utcnow().isoformat()}
@router.get("/health")
async def health(): return {"status": "ok", "clusters": len(_clusters), "gitops": len(_gitops)}