120 lines
5.7 KiB
Python
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)}
|