NA sees every campus; SSH from the admin laptop to every machine
Campuses set up from NA's install line tell NA where they are and learn nothing back (no campus ever shows another). NA alone reads each campus's key states every two seconds and keeps two pages in its Companion (added at the end, 98 and 99, since every other page is in use): CAMPUSES, a key per campus (its ALL key, purple when it stops answering), and CAMPUS, the tapped campus's status page drawn live in the same places, view only. Tried on NA with a test campus pointing at NA itself, then removed. tools/fleet.py: an Apple Remote Desktop command that turns on Remote Login, adds the laptop's key and reports each Mac to NA, and the laptop SSH shortcuts made from those reports (tried on NA Translation). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -245,3 +245,81 @@ class TestRoutes(unittest.TestCase):
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
|
||||
class TestCampusesView(unittest.TestCase):
|
||||
"""North Attleboro alone shows every campus: a copy of each status page (view only) and a CAMPUSES page."""
|
||||
|
||||
def test_the_campus_page_is_view_only_cells_with_a_way_back(self):
|
||||
from settings import campuses as cv
|
||||
import push_page
|
||||
na = json.load(open(os.path.join(ROOT, "config.json")))
|
||||
export = cv.build_view(na, 99, 98)
|
||||
ctrls = export["page"]["controls"]
|
||||
self.assertEqual(export["page"]["name"], "99\\nCampus")
|
||||
self.assertIn("CAMPUSES", json.dumps(ctrls["3"]["0"])) # where ALARMS sits on every status page
|
||||
cells = [ctl for row in ctrls.values() for ctl in row.values() if "campus view" in (ctl.get("options") or {}).get("notes", "")]
|
||||
self.assertEqual(len(cells), 28)
|
||||
self.assertTrue(all(c["steps"]["0"]["action_sets"] == {"down": [], "up": []} for c in cells)) # no press, no hold
|
||||
self.assertIn("sp_state_view", json.dumps(cells[0]["style"]))
|
||||
self.assertTrue(push_page.safe_target(export)[0]) # a rebuild may overwrite it
|
||||
|
||||
def test_a_campus_state_lands_on_its_cells(self):
|
||||
from settings import campuses as cv
|
||||
ws, _ = ac.build(BASE, small(), {"id": "ws", "name": "Woonsocket"}, "1234")
|
||||
keys = [{"id": t["id"], "pos": t["pos"]} for t in ws["tiles"] if t.get("pos")]
|
||||
out = cv.view_state({"hd1": {"x": "HD1\nREC", "b": 1}, "all": {"x": "ALL OK"}}, keys)
|
||||
hd1 = next(k for k in keys if k["id"] == "hd1")
|
||||
self.assertEqual(out[cv.cell_id(*hd1["pos"])]["x"], "HD1\nREC")
|
||||
self.assertEqual(out["c_0_1"]["x"], "ALL OK")
|
||||
self.assertEqual(out["c_2_7"]["x"], "") # nothing there: blank
|
||||
|
||||
def test_the_campuses_page_puts_this_campus_first_and_taps_to_each(self):
|
||||
from settings import campuses as cv
|
||||
na = json.load(open(os.path.join(ROOT, "config.json")))
|
||||
roster = {"na": {"name": "North Attleboro"}, "ws": {"name": "Woonsocket"}, "ab": {"name": "Apollo Beach"}}
|
||||
export = cv.build_overview(na, roster, 98, 99)
|
||||
keys = [(r, c, ctl) for r, row in export["page"]["controls"].items() for c, ctl in row.items() if "'campus " in (ctl.get("options") or {}).get("notes", "")]
|
||||
self.assertEqual([(r, c) for r, c, _ in keys], [("0", "1"), ("0", "2"), ("0", "3")])
|
||||
self.assertIn("'campus na'", keys[0][2]["options"]["notes"])
|
||||
self.assertIn("page 19", keys[0][2]["options"]["notes"])
|
||||
ws_key = next(k for _, _, k in keys if "'campus ws'" in k["options"]["notes"])
|
||||
acts = ws_key["steps"]["0"]["action_sets"]["up"]
|
||||
self.assertEqual([a["definitionId"] for a in acts], ["custom_variable_set_value", "set_page"])
|
||||
self.assertEqual((acts[0]["options"]["value"]["value"], acts[1]["options"]["page"]["value"]), ("ws", 99))
|
||||
|
||||
def test_a_campus_tells_the_hub_and_learns_nothing_back(self):
|
||||
from settings import campuses as cv
|
||||
data_dir = tempfile.mkdtemp(prefix="sp-cv-")
|
||||
cv.save(data_dir, {"home": "http://10.1.1.1:8020", "list": {"na": {"url": "x"}, "ab": {"url": "y"}}})
|
||||
|
||||
class FakeSite:
|
||||
def __init__(self):
|
||||
self.data_dir = data_dir
|
||||
|
||||
def load(self):
|
||||
return {"site": {"id": "ws", "name": "Woonsocket"}}
|
||||
sent = []
|
||||
real = cv.http_json
|
||||
cv.http_json = lambda url, body=None, timeout=3: sent.append((url, body)) or {"ok": True}
|
||||
real_url = cv.my_url
|
||||
cv.my_url = lambda cfg: "http://10.5.1.1:8020"
|
||||
try:
|
||||
m = cv.Mirror(FakeSite())
|
||||
data = m.sync_registry()
|
||||
m.poll()
|
||||
self.assertEqual(m.refresh_pages()["list"], {"ws": {"id": "ws", "name": "Woonsocket", "url": "http://10.5.1.1:8020"}})
|
||||
finally:
|
||||
cv.http_json, cv.my_url = real, real_url
|
||||
self.assertEqual(list(data["list"]), ["ws"]) # the others are forgotten
|
||||
self.assertTrue(all(u.endswith("/api/campus/hello") for u, _ in sent)) # it only ever says hello
|
||||
|
||||
|
||||
class TestCampusHello(TestRoutes):
|
||||
def test_campus_hello_is_checked(self):
|
||||
self.assertEqual(get(self.port, "/api/campus/hello", {"id": "ws", "name": "Woonsocket", "url": "http://10.5.1.1:8020"})[0], 200)
|
||||
for bad in ({"id": "WS; rm", "url": "http://10.5.1.1:8020"}, {"id": "ws", "url": "http://evil.example.com:80"},
|
||||
{"id": "ws", "url": "http://8.8.8.8:8020"}):
|
||||
self.assertEqual(get(self.port, "/api/campus/hello", bad)[0], 400, bad)
|
||||
from settings import campuses as cv
|
||||
self.assertEqual(cv.load(self.data)["list"]["ws"]["url"], "http://10.5.1.1:8020")
|
||||
|
||||
Reference in New Issue
Block a user