""" GUARDiA 클라우드 네이티브 인프라 — Gen6 eBPF 계측·Wasm 엣지·서비스 메시·이벤트 소싱·시크릿 관리·멀티런타임 """ 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/infra", tags=["Cloud Native Infra"]) _ebpf_probes: Dict[str, Dict] = {} _wasm_modules: Dict[str, Dict] = {} _mesh_services: Dict[str, Dict] = {} _events: List[Dict] = [] _secrets: Dict[str, Dict] = {} _runtimes: Dict[str, Dict] = {} class EBPFProbe(BaseModel): name: str; program_type: str = "kprobe" # kprobe|tracepoint|xdp|tc target: str; filter_expr: str = ""; owner: str = "platform" class WasmModule(BaseModel): name: str; wasm_binary_url: str = "" runtime: str = "wasmtime"; memory_mb: int = 64 env: Dict[str, str] = {} class MeshService(BaseModel): service: str; version: str = "v1" protocol: str = "http2"; mtls: bool = True circuit_breaker: bool = True; retries: int = 3 class EventCreate(BaseModel): aggregate_id: str; aggregate_type: str event_type: str; payload: Dict[str, Any] = {} correlation_id: Optional[str] = None class SecretCreate(BaseModel): name: str; value: str; engine: str = "vault" # vault|k8s|env rotate_days: int = 90; owner: str = "" class RuntimeCreate(BaseModel): name: str; runtime_type: str = "wasmtime" # wasmtime|spin|containerd|gvisor config: Dict[str, Any] = {} # ── eBPF 계측 ───────────────────────────────────────────────────────────── @router.post("/ebpf/probes") async def create_ebpf_probe(probe: EBPFProbe): pid = f"EBPF-{uuid.uuid4().hex[:8].upper()}" _ebpf_probes[pid] = {**probe.model_dump(), "id": pid, "status": "attached", "created_at": datetime.utcnow().isoformat(), "events_captured": 0} return _ebpf_probes[pid] @router.get("/ebpf/probes") async def list_ebpf_probes(): probes = list(_ebpf_probes.values()) or [ {"id": "EBPF-SYS001", "name": "syscall_monitor", "type": "kprobe", "status": "attached"}, {"id": "EBPF-NET001", "name": "network_flow", "type": "xdp", "status": "attached"}, ] return {"probes": probes, "total": len(probes)} @router.get("/ebpf/probes/{pid}/metrics") async def ebpf_probe_metrics(pid: str): return {"probe_id": pid, "events_per_sec": 1240, "latency_p99_us": 45, "cpu_overhead_pct": 0.3, "ts": datetime.utcnow().isoformat()} @router.delete("/ebpf/probes/{pid}") async def detach_ebpf_probe(pid: str): _ebpf_probes.pop(pid, None); return {"detached": pid} @router.get("/ebpf/trace") async def live_trace(program: str = "syscall", duration_sec: int = 5): return {"program": program, "duration_sec": duration_sec, "trace": [ {"ts": datetime.utcnow().isoformat(), "pid": 1234, "comm": "guardia-api", "event": "tcp_connect", "latency_ns": 4500}, {"ts": datetime.utcnow().isoformat(), "pid": 1234, "comm": "guardia-api", "event": "sys_read", "latency_ns": 120}, ]} @router.get("/ebpf/topology") async def network_topology(): return {"nodes": [ {"id": "guardia-itsm", "type": "service", "ip": "10.0.1.10"}, {"id": "guardia-manager", "type": "service", "ip": "10.0.1.11"}, {"id": "postgres", "type": "database", "ip": "10.0.1.20"}, ], "edges": [ {"from": "guardia-itsm", "to": "postgres", "protocol": "tcp", "port": 5432}, {"from": "guardia-manager", "to": "guardia-itsm", "protocol": "tcp", "port": 8001}, ], "captured_by": "eBPF XDP"} # ── Wasm 엣지 모듈 ─────────────────────────────────────────────────────── @router.post("/wasm/modules") async def deploy_wasm(module: WasmModule): mid = f"WASM-{uuid.uuid4().hex[:8].upper()}" _wasm_modules[mid] = {**module.model_dump(), "id": mid, "status": "running", "deployed_at": datetime.utcnow().isoformat()} return _wasm_modules[mid] @router.get("/wasm/modules") async def list_wasm(): modules = list(_wasm_modules.values()) or [ {"id": "WASM-EDGE01", "name": "request-validator", "runtime": "wasmtime", "status": "running"}, ] return {"modules": modules, "total": len(modules)} @router.get("/wasm/modules/{mid}/logs") async def wasm_logs(mid: str, lines: int = 50): return {"module_id": mid, "logs": [ f"[2026-06-06T00:00:00Z] Module {mid} started", f"[2026-06-06T00:00:01Z] Processed 1240 requests", ][-lines:]} @router.post("/wasm/modules/{mid}/invoke") async def invoke_wasm(mid: str, input: Dict[str, Any] = {}): m = _wasm_modules.get(mid) if not m: raise HTTPException(404) return {"module_id": mid, "input": input, "output": {"result": "ok", "processed": True}, "exec_time_ms": 1.2, "ts": datetime.utcnow().isoformat()} # ── 서비스 메시 ──────────────────────────────────────────────────────────── @router.post("/mesh/services") async def register_mesh_service(svc: MeshService): sid = f"MESH-{uuid.uuid4().hex[:8].upper()}" _mesh_services[sid] = {**svc.model_dump(), "id": sid, "status": "enrolled", "enrolled_at": datetime.utcnow().isoformat()} return _mesh_services[sid] @router.get("/mesh/services") async def list_mesh_services(): svcs = list(_mesh_services.values()) or [ {"service": "guardia-itsm", "mtls": True, "status": "enrolled"}, {"service": "guardia-manager", "mtls": True, "status": "enrolled"}, ] return {"services": svcs, "total": len(svcs)} @router.get("/mesh/traffic") async def mesh_traffic(): return {"services": [ {"from": "guardia-manager", "to": "guardia-itsm", "rps": 142, "error_rate": 0.1, "p99_ms": 45}, {"from": "guardia-itsm", "to": "postgres", "rps": 520, "error_rate": 0.0, "p99_ms": 12}, ]} @router.get("/mesh/policies") async def mesh_policies(): return {"policies": [ {"type": "circuit_breaker", "service": "guardia-itsm", "threshold": 50, "window_sec": 10}, {"type": "retry", "service": "guardia-manager", "max_attempts": 3, "backoff_ms": 100}, ]} @router.post("/mesh/policies") async def create_mesh_policy(service: str, policy_type: str, rules: Dict[str, Any] = {}): return {"id": f"POL-{uuid.uuid4().hex[:8].upper()}", "service": service, "type": policy_type, "rules": rules, "applied": True, "ts": datetime.utcnow().isoformat()} # ── 이벤트 소싱 ──────────────────────────────────────────────────────────── @router.post("/events/publish") async def publish_event(event: EventCreate): eid = f"EVT-{uuid.uuid4().hex[:8].upper()}" record = {**event.model_dump(), "id": eid, "sequence": len(_events) + 1, "published_at": datetime.utcnow().isoformat()} _events.append(record) return record @router.get("/events/stream") async def get_event_stream(aggregate_id: Optional[str] = None, event_type: Optional[str] = None, limit: int = 100): evts = _events if aggregate_id: evts = [e for e in evts if e["aggregate_id"] == aggregate_id] if event_type: evts = [e for e in evts if e["event_type"] == event_type] return {"events": evts[-limit:], "total": len(evts)} @router.get("/events/replay/{aggregate_id}") async def replay_events(aggregate_id: str, from_sequence: int = 0): evts = [e for e in _events if e["aggregate_id"] == aggregate_id and e.get("sequence", 0) >= from_sequence] return {"aggregate_id": aggregate_id, "events": evts, "replayed": len(evts)} @router.get("/events/projections") async def list_projections(): return {"projections": [ {"name": "sr-read-model", "last_event": len(_events), "status": "up-to-date"}, {"name": "server-state", "last_event": len(_events), "status": "up-to-date"}, ]} # ── 시크릿 관리 ──────────────────────────────────────────────────────────── @router.post("/secrets") async def create_secret(secret: SecretCreate): sid = f"SEC-{uuid.uuid4().hex[:8].upper()}" _secrets[sid] = {"id": sid, "name": secret.name, "engine": secret.engine, "rotate_days": secret.rotate_days, "owner": secret.owner, "value": "***ENCRYPTED***", "created_at": datetime.utcnow().isoformat()} return {k: v for k, v in _secrets[sid].items() if k != "value"} @router.get("/secrets") async def list_secrets(): return {"secrets": [{k: v for k, v in s.items() if k != "value"} for s in _secrets.values()]} @router.post("/secrets/{name}/rotate") async def rotate_secret(name: str): return {"name": name, "rotated": True, "new_version": f"v{uuid.uuid4().hex[:4]}", "ts": datetime.utcnow().isoformat()} @router.get("/secrets/{name}/audit") async def secret_audit(name: str): return {"name": name, "access_log": [ {"user": "guardia-itsm", "action": "read", "ts": datetime.utcnow().isoformat()}, ], "rotation_history": [{"version": "v1", "ts": datetime.utcnow().isoformat()}]} # ── 멀티 런타임 관리 ────────────────────────────────────────────────────── @router.post("/runtimes") async def create_runtime(rt: RuntimeCreate): rid = f"RT-{uuid.uuid4().hex[:8].upper()}" _runtimes[rid] = {**rt.model_dump(), "id": rid, "status": "ready", "created_at": datetime.utcnow().isoformat()} return _runtimes[rid] @router.get("/runtimes") async def list_runtimes(): rts = list(_runtimes.values()) or [ {"id": "RT-WASM01", "name": "wasmtime-edge", "type": "wasmtime", "status": "ready"}, {"id": "RT-CONT01", "name": "containerd-shim", "type": "containerd", "status": "ready"}, ] return {"runtimes": rts, "total": len(rts)} @router.get("/runtimes/{rid}/stats") async def runtime_stats(rid: str): return {"runtime_id": rid, "cpu_cores": 4, "memory_used_mb": 512, "modules_running": len(_wasm_modules), "uptime_sec": 86400, "ts": datetime.utcnow().isoformat()} # ── 클라우드 네이티브 상태 ──────────────────────────────────────────────── @router.get("/native/health") async def native_health(): return {"status": "healthy", "ebpf_probes": len(_ebpf_probes), "wasm_modules": len(_wasm_modules), "mesh_services": len(_mesh_services), "events_stored": len(_events), "secrets": len(_secrets), "runtimes": len(_runtimes)} @router.get("/native/overview") async def native_overview(): return {"gen": 6, "capabilities": ["eBPF", "Wasm Edge", "Service Mesh", "Event Sourcing", "Secret Manager", "Multi-Runtime"], "maturity": "production", "last_updated": datetime.utcnow().isoformat()}