Repo-side rename only (Phases 1-3 of the migration plan); the live box (~/.castle, systemd units, /data/castle, domains) is a separate cutover. - Slug `castle` -> `wildpc`: CLI command, module names (wildpc_core/cli/api), dist names, entry point `wildpc = wildpc_cli.main:main`. - Identifiers: CastleConfig/NATSClient/DirError/MDNS -> Wildpc*. - Env/constants: CASTLE_* -> WILDPC_*; ~/.castle -> ~/.wildpc, castle.yaml -> wildpc.yaml, /data/castle -> /data/wildpc. - Systemd UNIT_PREFIX castle- -> wildpc-; own programs castle-api/gateway/etc. - Display prose "Castle" -> "Wild PC" in docs, agent-guide files, README, frontend. - Package dirs and bootstrap yaml renamed via git mv; lockfiles regenerated; redundant nested uv.lock files dropped (workspace root lock is authoritative). Tests: core 273, cli 47, wildpc-api 120 all pass. Frontend type-checks + builds. Fixed a stale test fixture (secret_env_path kind arg) broken pre-rename.
95 lines
3.3 KiB
Python
95 lines
3.3 KiB
Python
"""Tests for nodes endpoints."""
|
|
|
|
from pathlib import Path
|
|
|
|
from fastapi.testclient import TestClient
|
|
|
|
from wildpc_core.registry import Deployment, NodeConfig, NodeRegistry
|
|
|
|
from wildpc_api.mesh import MeshStateManager
|
|
|
|
|
|
class TestNodesList:
|
|
"""GET /nodes endpoint tests."""
|
|
|
|
def test_returns_local_node(self, client: TestClient) -> None:
|
|
"""Always returns the local node."""
|
|
response = client.get("/nodes")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert len(data) >= 1
|
|
local = data[0]
|
|
assert local["hostname"] == "test-node"
|
|
assert local["is_local"] is True
|
|
assert local["online"] is True
|
|
|
|
def test_local_node_counts(self, client: TestClient) -> None:
|
|
"""Local node has correct deployment counts."""
|
|
response = client.get("/nodes")
|
|
data = response.json()
|
|
local = data[0]
|
|
assert local["deployed_count"] == 2 # test-svc + test-tool
|
|
assert local["service_count"] == 1 # only test-svc is a service
|
|
|
|
def test_includes_remote_nodes(
|
|
self, client: TestClient, registry_path: Path
|
|
) -> None:
|
|
"""Remote nodes from mesh state are included."""
|
|
import wildpc_api.mesh as mesh_mod
|
|
|
|
original = mesh_mod.mesh_state
|
|
try:
|
|
mgr = MeshStateManager()
|
|
remote_reg = NodeRegistry(
|
|
node=NodeConfig(hostname="devbox", gateway_port=9000),
|
|
deployed={
|
|
"remote-svc": Deployment(
|
|
manager="systemd",
|
|
launcher="python",
|
|
run_cmd=["svc"],
|
|
port=9050,
|
|
kind="service",
|
|
),
|
|
},
|
|
)
|
|
mgr.update_node("devbox", remote_reg)
|
|
mesh_mod.mesh_state = mgr
|
|
|
|
# Also patch the reference in the nodes module
|
|
import wildpc_api.nodes as nodes_mod
|
|
|
|
nodes_mod.mesh_state = mgr
|
|
|
|
response = client.get("/nodes")
|
|
data = response.json()
|
|
hostnames = [n["hostname"] for n in data]
|
|
assert "devbox" in hostnames
|
|
devbox = next(n for n in data if n["hostname"] == "devbox")
|
|
assert devbox["is_local"] is False
|
|
assert devbox["deployed_count"] == 1
|
|
finally:
|
|
mesh_mod.mesh_state = original
|
|
import wildpc_api.nodes as nodes_mod2
|
|
|
|
nodes_mod2.mesh_state = original
|
|
|
|
|
|
class TestNodeDetail:
|
|
"""GET /nodes/{hostname} endpoint tests."""
|
|
|
|
def test_local_node_detail(self, client: TestClient) -> None:
|
|
"""Returns local node detail with deployed components."""
|
|
response = client.get("/nodes/test-node")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["hostname"] == "test-node"
|
|
assert data["is_local"] is True
|
|
assert len(data["deployed"]) == 2 # test-svc + test-tool
|
|
svc = next(d for d in data["deployed"] if d["id"] == "test-svc")
|
|
assert svc["node"] == "test-node"
|
|
|
|
def test_unknown_node_returns_404(self, client: TestClient) -> None:
|
|
"""Returns 404 for unknown hostname."""
|
|
response = client.get("/nodes/nonexistent")
|
|
assert response.status_code == 404
|