mirror of
https://github.com/saphid/frame-control.git
synced 2026-10-06 01:00:18 +02:00
Devices: fixes from review round 18
- A set-up headset whose alias goes through a jump host (ProxyJump or ProxyCommand in ~/.ssh/config) is reached through it, address by address, still pinned per headset. - A refused switch puts the header's switcher back on the headset in use. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
90fd2684ba
commit
c3e3f2629c
3 files changed
+39
-1
No files matched your search
@@ -344,6 +344,15 @@ class Connecting(unittest.TestCase):
|
||||
self.assertEqual(self.link.snapshot()["phase"], "connected")
|
||||
self.assertEqual(self.link.named_route(), ("frame-bare", pinned)) # terminals go there too
|
||||
|
||||
def test_a_set_up_headset_behind_a_jump_host_is_left_to_ssh(self):
|
||||
d = self.device("10.99.99.98", "10.99.99.99") # neither answers directly
|
||||
self.hosts({"10.99.99.98": "wrong", "10.99.99.99": "ok"})
|
||||
with mock.patch.object(fl, "ssh_g", return_value=("frame-t", 22, "steamos", True)):
|
||||
self.link.connect(["start"])
|
||||
s = self.link.snapshot()
|
||||
self.assertEqual((s["phase"], s["via"]["host"]), ("connected", "10.99.99.99"), s["error"])
|
||||
self.assertIn(f"HostKeyAlias=frame-control-{d['id']}", self.routes[-1][1]) # still pinned per headset
|
||||
|
||||
def test_a_bare_alias_behind_a_jump_host_is_left_to_ssh(self):
|
||||
self.link.override = "frame-jump"
|
||||
self.hosts({"10.99.99.99": "ok"}) # ssh's ProxyJump would get there
|
||||
|
||||
@@ -584,6 +584,31 @@ class Link:
|
||||
ranked = [(a, "from ~/.ssh/config")]
|
||||
else:
|
||||
ranked = frame_devices.order_addresses(device["addresses"], net.get("id"), bool(ts.get("up")))
|
||||
if ssh_g(device["alias"])[3]:
|
||||
# ~/.ssh/config sends this alias through a jump host: a direct probe says
|
||||
# nothing, so let ssh (through the jump host) try each address in turn.
|
||||
with self.cond:
|
||||
self.state["probes"] = [dict(a, why=why, state="waiting", detail="Through a jump host", ip=None,
|
||||
rtt_ms=None, label=a.get("label") or "") for a, why in ranked]
|
||||
self.stage("find", "done", f"{device['alias']} goes through a jump host; ssh finds it")
|
||||
for i, (a, why) in enumerate(ranked):
|
||||
if i:
|
||||
for sid in ("ssh", "identity", "login"):
|
||||
self.stage(sid, "pending", "")
|
||||
outcome = self.handshake(device, a, {"ip": None, "rtt_ms": None}, device.get("user"))
|
||||
if outcome == "ok":
|
||||
self.probe_update(i, state="answered", detail="Reached through the jump host")
|
||||
self.publish(via={"host": a["host"], "kind": a["kind"], "ip": None, "rtt_ms": None,
|
||||
"why": "through a jump host", "network": net.get("id"),
|
||||
"network_name": net["name"]})
|
||||
self.learn(device, a["host"], net, None)
|
||||
return True
|
||||
with self.cond:
|
||||
why_not = (self.state["error"] or {}).get("message") or "SSH failed"
|
||||
self.probe_update(i, state="sshfailed", detail=why_not)
|
||||
if outcome != "next":
|
||||
return False
|
||||
return False
|
||||
with self.cond:
|
||||
self.state["probes"] = [{"host": a["host"], "kind": a["kind"], "label": a.get("label") or "",
|
||||
"why": why, "state": "waiting", "detail": "Waiting", "ip": None,
|
||||
|
||||
+5
-1
@@ -2677,7 +2677,11 @@ async function useDevice(id) {
|
||||
const d = dv.list.find(x => x.id === id);
|
||||
if (!d || d.active) return;
|
||||
devGen++; // from here on, answers about the last headset are dropped
|
||||
await act(`Switch to ${d.name}`, () => api("/api/devices", { action: "use", id }));
|
||||
const res = await act(`Switch to ${d.name}`, () => api("/api/devices", { action: "use", id }));
|
||||
if (!res) { // refused (an install is running): show the headset still in use
|
||||
const current = dv.list.find(x => x.active);
|
||||
if (current) $("devSel").value = current.id;
|
||||
}
|
||||
}
|
||||
async function devAction(label, body, btn) {
|
||||
const res = await act(label, () => api("/api/devices", body), btn);
|
||||
|
||||
Reference in new issue
Block a user