Files
serverAppConfigs/tests/homepage_config.bats
T
Frank 79cca19919 observability: the LLM surfaces follow the two-endpoint split
frank-large has no /metrics to scrape any more, and scraping it would be red by
construction: the halogen engine publishes /health, /cache and /v1/* only. That
job is removed with the reason written down (the remedy is the blackbox
exporter this fleet already wants for the comfyui/services probes), and
frank-small's llama.cpp endpoint takes the slot at 192.168.0.143:7771.

Homepage: frank-large's card still described the ik runtime, and the new
endpoint had no card at all. Both fixed, with a loopback probe -- the checker
runs on Dankclaw, which is also what makes the card green-able.

Dashboard: the endpoint picker was sourced from a vLLM-only metric, so a
llama.cpp job could never be selected, and the prose named frank-large as the
llama.cpp endpoint. The picker now matches both runtimes' series and the
llama.cpp targets carry the job filter every other panel already used.

The seams assert the new contract including the ABSENCE of a 7770 target, so a
well-meaning edit cannot re-add a permanently-red probe.
2026-09-16 13:59:49 -07:00

60 lines
2.4 KiB
Bash

#!/usr/bin/env bats
# Seam: shared/homepage/services.json — the service config the checker reads
# and the pages render. It must be a JSON list; every entry carries name,
# category, and a host:port probe. category is user or admin. method, when
# present, is tcp or http.
load helpers
@test "services.json: valid schema" {
python3 - "$REPO_ROOT/shared/homepage/services.json" <<'PY'
import json, sys
path = sys.argv[1]
try:
data = json.load(open(path))
except FileNotFoundError:
sys.exit("services.json not found")
assert isinstance(data, list), "top level must be a list"
assert data, "the list must not be empty"
for svc in data:
for field in ("name", "category", "probe"):
assert field in svc, f"{svc.get('name', '?')} is missing {field}"
assert svc["category"] in ("user", "admin"), svc["category"]
if "method" in svc:
assert svc["method"] in ("tcp", "http"), svc["method"]
host, _, port = svc["probe"].rpartition(":")
assert host and port.isdigit(), f"bad probe {svc['probe']}"
PY
}
@test "services.json: every user service has an Open link, status-only backends do not" {
python3 - "$REPO_ROOT/shared/homepage/services.json" <<'PY'
import json, sys
data = json.load(open(sys.argv[1]))
for svc in data:
show = svc.get("showLink", True)
if show:
assert svc.get("url"), f"{svc['name']} shows a link but has no url"
else:
assert not svc.get("url"), f"{svc['name']} is status-only but has a url"
PY
}
@test "the LLM status cards track the fleet, not retired service names" {
# This drifted twice: the card probing Dankserver's :7770 was still named
# frank-small long after frank-medium took that endpoint, and Dankclaw's
# second endpoint now exists again as a real service on its own port. The
# probe target is what matters; the name has to follow it.
python3 - "$REPO_ROOT/shared/homepage/services.json" <<'PY'
import json, sys
services = json.load(open(sys.argv[1]))
by_probe = {s["probe"]: s["name"] for s in services}
medium = by_probe.get("192.168.0.235:7770")
assert medium == "frank-medium", f"Dankserver :7770 card is named {medium!r}"
# Dankclaw serves two endpoints on two ports: frank-large (halogen, 7770) and
# frank-small (llama.cpp on the RTX 3090, 7771).
assert by_probe.get("127.0.0.1:7770") == "frank-large", by_probe.get("127.0.0.1:7770")
assert by_probe.get("127.0.0.1:7771") == "frank-small", by_probe.get("127.0.0.1:7771")
PY
}