import httpx from fastapi import APIRouter, Depends, HTTPException, Request from sqlmodel import Session from clients.edge.http import HttpEdgeClient from core.database import get_session from schemas.platform import ManagedNodePayload from api.platform_node_support import ( managed_node_from_payload, normalize_node_payload, test_edge_connectivity, test_edge_native_preflight, ) from api.platform_shared import invalidate_platform_nodes_cache router = APIRouter() @router.post("/api/platform/nodes/test") def test_platform_node(payload: ManagedNodePayload, request: Request): normalized = normalize_node_payload(payload) temp_node = managed_node_from_payload(normalized) result = test_edge_connectivity( lambda _target: HttpEdgeClient( node=temp_node, http_client_factory=lambda: httpx.Client(timeout=10.0, trust_env=False), async_http_client_factory=lambda: httpx.AsyncClient(timeout=10.0, trust_env=False), ), temp_node, ) return result.model_dump() @router.post("/api/platform/nodes/native/preflight") def test_platform_node_native_preflight(payload: ManagedNodePayload, request: Request): normalized = normalize_node_payload(payload) temp_node = managed_node_from_payload(normalized) result = test_edge_native_preflight( lambda _target: HttpEdgeClient( node=temp_node, http_client_factory=lambda: httpx.Client(timeout=10.0, trust_env=False), async_http_client_factory=lambda: httpx.AsyncClient(timeout=10.0, trust_env=False), ), temp_node, native_command=str(normalized.native_command or "").strip() or None, native_workdir=str(normalized.native_workdir or "").strip() or None, ) return result.model_dump() @router.post("/api/platform/nodes/{node_id}/test") def test_saved_platform_node(node_id: str, request: Request, session: Session = Depends(get_session)): normalized_node_id = str(node_id or "").strip().lower() node_registry = getattr(request.app.state, "node_registry_service", None) if node_registry is None or not hasattr(node_registry, "get_node"): raise HTTPException(status_code=500, detail="node registry is unavailable") node = node_registry.get_node(normalized_node_id) if node is None: raise HTTPException(status_code=404, detail=f"Managed node not found: {normalized_node_id}") transport_kind = str((node.metadata or {}).get("transport_kind") or "edge").strip().lower() if transport_kind != "edge": invalidate_platform_nodes_cache() raise HTTPException(status_code=400, detail="Only edge transport is supported") result = test_edge_connectivity( lambda _target: HttpEdgeClient( node=node, http_client_factory=lambda: httpx.Client(timeout=10.0, trust_env=False), async_http_client_factory=lambda: httpx.AsyncClient(timeout=10.0, trust_env=False), ), node, ) if result.ok: node_registry.mark_node_seen( session, node_id=node.node_id, display_name=str(node.display_name or result.node_self.get("display_name") or node.node_id) if result.node_self else node.display_name, capabilities=dict(result.node_self.get("capabilities") or {}) if result.node_self else dict(node.capabilities or {}), resources=dict(result.node_self.get("resources") or {}) if result.node_self else dict(getattr(node, "resources", {}) or {}), ) invalidate_platform_nodes_cache() return result.model_dump() @router.post("/api/platform/nodes/{node_id}/native/preflight") def test_saved_platform_node_native_preflight(node_id: str, request: Request, session: Session = Depends(get_session)): normalized_node_id = str(node_id or "").strip().lower() node_registry = getattr(request.app.state, "node_registry_service", None) if node_registry is None or not hasattr(node_registry, "get_node"): raise HTTPException(status_code=500, detail="node registry is unavailable") node = node_registry.get_node(normalized_node_id) if node is None: raise HTTPException(status_code=404, detail=f"Managed node not found: {normalized_node_id}") transport_kind = str((node.metadata or {}).get("transport_kind") or "edge").strip().lower() if transport_kind != "edge": invalidate_platform_nodes_cache() raise HTTPException(status_code=400, detail="Only edge transport is supported") metadata = dict(node.metadata or {}) result = test_edge_native_preflight( lambda _target: HttpEdgeClient( node=node, http_client_factory=lambda: httpx.Client(timeout=10.0, trust_env=False), async_http_client_factory=lambda: httpx.AsyncClient(timeout=10.0, trust_env=False), ), node, native_command=str(metadata.get("native_command") or "").strip() or None, native_workdir=str(metadata.get("native_workdir") or "").strip() or None, ) if result.status == "online" and result.node_self: node_registry.mark_node_seen( session, node_id=node.node_id, display_name=str(node.display_name or result.node_self.get("display_name") or node.node_id), capabilities=dict(result.node_self.get("capabilities") or {}), resources=dict(result.node_self.get("resources") or {}), ) invalidate_platform_nodes_cache() return result.model_dump()