Files
computer-playbook/cli/contributing/network/diagnose/format.py
T
kevinveenbirkenbachandClaude Opus 4.7 e4e861c261 refactor(cli): move ports/networks suggesters under cli/contributing/network and add diagnose subcommand
Relocates `cli/meta/{ports,networks/suggest}` to
`cli/contributing/network/{ports,address/suggest}` so port and subnet
allocators live alongside the rest of the contributor-side tooling
(mirror, update, changelog) instead of `meta`. Mirrors the tests
into `tests/unit/cli/contributing/network/` and renames the contract
docs to `docs/contributing/tools/network/{port,address}.md`. Prog
names update from `cli meta ports suggest` / `cli meta networks
suggest` to `cli contributing network ports suggest` / `cli
contributing network address suggest`; the corresponding lint
references and `utils.meta.scan` docstring follow.

Adds a third subcommand: `cli contributing network diagnose`
(stdlib-only DNS / TCP / TLS / PMTU probe against the standard
infrastructure hosts plus interface MTU, `/etc/resolv.conf`,
`/etc/hosts`, proxy env, CA-bundle summaries). Split across `cli.py`
(orchestration), `config.py` (SPOT for hosts / per-distro install
commands), `format.py` (output + subprocess helpers), `tools.py`
(distro-aware auto-install of `iputils-ping` + `iproute2`),
`report.py` (system-info dumps + IPv6-default-route detection), and
`probes.py` (per-host probes). Exposed as `make debug-network`.

Companion `docs/contributing/actions/debugging/network.md` absorbs
the diagnose-tool walkthrough (incl. how to read MTU-induced TLS
handshake timeouts) so the merged page covers DNS / MTU / IPv6 /
connectivity end-to-end.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 14:55:10 +02:00

40 lines
1.1 KiB
Python

"""Output and subprocess helpers."""
from __future__ import annotations
import subprocess
import sys
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from collections.abc import Sequence
def section(title: str, *, file=None) -> None:
print(f"\n=== {title} ===", flush=True, file=file or sys.stdout)
def line(label: str, value: str, *, file=None) -> None:
print(f" {label}: {value}", flush=True, file=file or sys.stdout)
def cmd_capture(argv: Sequence[str], timeout: float = 5.0) -> tuple[int, str]:
"""Run argv and return (returncode, combined stdout+stderr).
Returns (-1, "command not found: …") when the binary is missing.
Returns (-2, "timeout after …") when the call exceeds ``timeout``.
"""
try:
p = subprocess.run(
list(argv),
capture_output=True,
text=True,
timeout=timeout,
check=False,
)
return p.returncode, (p.stdout or "") + (p.stderr or "")
except FileNotFoundError:
return -1, f"command not found: {argv[0]}"
except subprocess.TimeoutExpired:
return -2, f"timeout after {timeout}s: {' '.join(argv)}"