feat: apt proxy check+fix as device warning

- get_device_warnings(): checks /etc/apt/apt.conf.d/00proxy on apt systems
  (only when apt_proxy_url is set via optional_args from NetOrk settings)
- _action_fix_apt_proxy(): writes the proxy config via sudo, uses base64 to
  avoid quoting issues
- run_device_action(): routes 'fix_apt_proxy' to the new method

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Christian Manivong
2026-06-07 22:34:31 +02:00
co-authored by Claude Sonnet 4.6
parent c46732946d
commit 499d48c379
+41
View File
@@ -80,6 +80,9 @@ class LinuxDriver(OSDriver):
self._secret: str = optional_args.get("secret", password)
# Optional sudo password for privilege escalation (e.g. apt-get update)
self._sudo_password: Optional[str] = optional_args.get("sudo_password")
# Expected apt proxy URL — checked as a device warning on apt systems.
# Only set when apt_proxy_enabled=true in NetOrk settings; empty string disables the check.
self._apt_proxy_url: str = optional_args.get("apt_proxy_url", "")
if optional_args.get("debugging"):
logger.setLevel(logging.DEBUG)
@@ -788,6 +791,7 @@ class LinuxDriver(OSDriver):
Currently detects:
- package updates available (uses local package cache)
- apt proxy not configured (apt systems only)
"""
warnings: List[Dict[str, Any]] = []
try:
@@ -805,6 +809,18 @@ class LinuxDriver(OSDriver):
"packages": [u.get("name", "") for u in updates],
},
})
if self._pkg_manager == "apt" and self._apt_proxy_url:
try:
current = self._send("cat /etc/apt/apt.conf.d/00proxy 2>/dev/null || true").strip()
if self._apt_proxy_url not in current:
warnings.append({
"code": "apt_proxy_missing",
"severity": "warning",
"action": "fix_apt_proxy",
"meta": {"expected_url": self._apt_proxy_url},
})
except Exception as exc:
logger.warning("get_device_warnings: apt proxy check failed: %s", exc)
return warnings
def _get_updates_apt(self) -> List[UpdateDict]:
@@ -1616,6 +1632,8 @@ class LinuxDriver(OSDriver):
return self._action_fix_docker_permissions()
if action == "fix_snmp":
return self._action_fix_snmp()
if action == "fix_apt_proxy":
return self._action_fix_apt_proxy()
raise NotImplementedError(f"Unknown action: {action!r}")
def _action_fix_snmp(self) -> DeviceActionResultDict:
@@ -1750,6 +1768,29 @@ class LinuxDriver(OSDriver):
out = f"Added {user!r} to the docker group. Reconnect or run a new poll to verify."
return {"success": success, "output": out}
def _action_fix_apt_proxy(self) -> DeviceActionResultDict:
"""Write /etc/apt/apt.conf.d/00proxy with the configured proxy URL."""
import base64 as _b64
proxy_url = self._apt_proxy_url
if not proxy_url:
return {"success": False, "output": "No apt_proxy_url configured."}
if self._pkg_manager != "apt":
return {"success": False, "output": f"Package manager is {self._pkg_manager!r}, not apt — skipping."}
content = f'Acquire::http::Proxy "{proxy_url}";\n'
content_b64 = _b64.b64encode(content.encode()).decode()
self._send(f"echo {content_b64} | base64 -d > /tmp/netork_00proxy")
self._sudo(
"mv /tmp/netork_00proxy /etc/apt/apt.conf.d/00proxy && "
"chown root:root /etc/apt/apt.conf.d/00proxy && "
"chmod 644 /etc/apt/apt.conf.d/00proxy"
)
verify = self._send("cat /etc/apt/apt.conf.d/00proxy 2>/dev/null").strip()
success = proxy_url in verify
if success:
return {"success": True, "output": f"Wrote /etc/apt/apt.conf.d/00proxy — proxy: {proxy_url}"}
return {"success": False, "output": f"Write may have failed. File content: {verify[:200]}"}
def get_vpn_tunnels(self) -> Dict[str, Any]:
"""Return WireGuard status via ``wg show all dump`` (requires root/sudo).