mirror of
https://github.com/saphid/frame-control.git
synced 2026-10-06 04:04:21 +02:00
Devices: fixes from review round 24
- While the connector is taking a queued reconnect off its list, the old connection no longer counts as live, so no install starts on it. - Importing a block without a Port takes the port ssh would really use (ssh -F <config> -G), e.g. one a later Host * sets. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
22863f2f87
commit
49378b2c80
4 files changed
+37
-5
No files matched your search
+22
-3
@@ -157,7 +157,8 @@ def parse_blocks(text):
|
||||
for line in text.splitlines():
|
||||
m = BLOCK_RE.fullmatch(line.strip())
|
||||
if m:
|
||||
cur = {"alias": m.group(1), "hostname": None, "user": None, "port": 22, "identity_files": []}
|
||||
cur = {"alias": m.group(1), "hostname": None, "user": None, "port": 22, "port_set": False,
|
||||
"identity_files": []}
|
||||
continue
|
||||
if cur is None:
|
||||
continue
|
||||
@@ -174,7 +175,7 @@ def parse_blocks(text):
|
||||
elif key == "user" and cur["user"] is None:
|
||||
cur["user"] = value
|
||||
elif key == "port" and value.isdigit():
|
||||
cur["port"] = int(value)
|
||||
cur["port"], cur["port_set"] = int(value), True
|
||||
elif key == "identityfile":
|
||||
cur["identity_files"].append(value)
|
||||
return blocks
|
||||
@@ -278,7 +279,9 @@ def rewrite_block(alias, path=None, hostname=None, user=None, port=None, expect=
|
||||
def change(lines):
|
||||
if expect:
|
||||
block = next((b for b in parse_blocks("\n".join(lines)) if b["alias"] == alias), None)
|
||||
if not block or any(v is not None and block[k] != v for k, v in expect.items()):
|
||||
# A port the block doesn't set is inherited from elsewhere in the file: not compared.
|
||||
if not block or any(v is not None and block[k] != v and (k != "port" or block["port_set"])
|
||||
for k, v in expect.items()):
|
||||
return None
|
||||
return _rewritten(lines, alias, hostname, user, port)
|
||||
return _edit_config(Path(path or ssh_config()), change)
|
||||
@@ -321,6 +324,18 @@ def remove_block(alias, path=None):
|
||||
return _edit_config(Path(path or ssh_config()), change)
|
||||
|
||||
|
||||
def effective_port(alias, config):
|
||||
"""The port ssh uses for ALIAS with this config file (`ssh -F FILE -G ALIAS`), else 22."""
|
||||
try:
|
||||
out = subprocess.run(["ssh", "-F", str(config), "-G", alias], capture_output=True, text=True,
|
||||
stdin=subprocess.DEVNULL, timeout=10).stdout
|
||||
except (OSError, subprocess.TimeoutExpired):
|
||||
return 22
|
||||
m = re.search(r"^port (\d+)$", out, re.M)
|
||||
port = int(m.group(1)) if m else 22
|
||||
return port if 1 <= port <= 65535 else 22
|
||||
|
||||
|
||||
# ---- pinned host keys -------------------------------------------------------------
|
||||
|
||||
def _keygen(*args):
|
||||
@@ -670,6 +685,10 @@ class Registry:
|
||||
"""Import managed blocks we don't know yet, and pick up a HostName that Set Up
|
||||
Connection changed since we last looked. -> True if anything changed."""
|
||||
blocks = parse_blocks(read_config(self.config))
|
||||
for b in blocks:
|
||||
if not b["port_set"]:
|
||||
# No Port in the block: another Host entry may give one (ssh uses the first).
|
||||
b["port"] = effective_port(b["alias"], self.config or ssh_config())
|
||||
changed = False
|
||||
with self.lock:
|
||||
first = not self.data["devices"] and not self.data.get("active")
|
||||
|
||||
+2
-2
@@ -259,8 +259,8 @@ class Link:
|
||||
self.close_master()
|
||||
|
||||
def alive(self):
|
||||
if self.state["phase"] != "connected" or self.kicks:
|
||||
return False
|
||||
if self.state["phase"] != "connected" or self.kicks or self.busy:
|
||||
return False # a reconnect is queued or starting: don't begin anything on this connection
|
||||
if not self.control:
|
||||
return True
|
||||
return self.master is None or self.master.poll() is None
|
||||
|
||||
Reference in new issue
Block a user