fix/docker-restart-pending
`docker ps` reports a bare image ID instead of the tag as soon as that tag points at a newer image — which is exactly what a pull without a recreate does. That ID went straight into `docker buildx imagetools inspect`, which cannot resolve an image ID, so the lookup failed and the image was silently dropped from the outdated list. The check was blind in precisely the state that means an update is waiting. get_docker_info() now also reads `.Config.Image`, the reference the container was created from, which never degrades. It compares each running container's image ID against the ID its own tag currently resolves to, and reports `image_ref`, `running_image_id`, `restart_pending` and `pending_version`. get_docker_outdated() prefers `image_ref`, skips bare IDs with a log line instead of asking the registry about them, and no longer swallows a failed registry lookup — silence there was indistinguishable from "up to date". Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
napalm-linux
NAPALM driver for generic Linux systems — Debian, Ubuntu, RHEL, Rocky, Alpine, Arch and any other distribution reachable via SSH.
Connects over SSH using Netmiko (linux device type) and
automatically detects the installed package manager (apt, dnf, yum, apk, pacman).
Requirements
| Dependency | Minimum version |
|---|---|
| Python | 3.9 |
| NAPALM | 4.0 |
| Netmiko | 4.0 |
| napalm-device-types | 0.2.0 |
Installation
pip install napalm napalm-linux
Or from source:
git clone https://github.com/chrismanivong/napalm-linux
pip install -e napalm-linux/
When working in the NetOrk monorepo, install both packages as editable:
pip install -e vendor/napalm-device-types/ -e vendor/napalm-linux/
Quick start
from napalm import get_network_driver
Driver = get_network_driver("linux")
with Driver(
"10.0.0.5",
"admin",
"s3cr3t",
optional_args={
# "port": 22,
# "pkg_manager": "apt", # force package manager; auto-detected by default
# "secret": "sudo-pass", # password for sudo / enable (defaults to login password)
# "debugging": True, # enable verbose logging
},
) as dev:
facts = dev.get_facts()
print(facts)
# OS-specific methods (from napalm-device-types OSDriver)
packages = dev.get_packages()
updates = dev.get_pending_updates()
services = dev.get_services()
users = dev.get_users()
procs = dev.get_processes()
jobs = dev.get_cron_jobs()
# Upgrade specific packages
result = dev.apply_updates(["openssh-server", "curl"])
print(result) # {"success": True, "output": "..."}
# Upgrade everything with pending updates
result = dev.apply_updates([])
Supported NAPALM methods
Standard NAPALM
| Method | Supported | Notes |
|---|---|---|
open() / close() |
✅ | SSH via netmiko linux |
is_alive() |
✅ | |
get_facts() |
✅ | DMI / /proc/uptime / ip link |
get_interfaces() |
✅ | ip link show |
get_interfaces_ip() |
✅ | ip addr show |
get_arp_table() |
✅ | ip neigh show |
get_config() |
✅ | Returns ip addr + ip route output |
ping() |
✅ | Executes ping on the remote host |
load_merge_candidate() |
❌ | Not applicable for generic Linux |
load_replace_candidate() |
❌ | Not applicable for generic Linux |
compare_config() |
❌ | Not applicable for generic Linux |
commit_config() |
❌ | Not applicable for generic Linux |
discard_config() |
❌ | Not applicable for generic Linux |
rollback() |
❌ | Not applicable for generic Linux |
OSDriver extensions (napalm-device-types)
| Method | Supported | Package managers |
|---|---|---|
get_packages() |
✅ | apt, dnf, yum, apk, pacman |
get_pending_updates() |
✅ | apt, dnf, yum, apk, pacman |
apply_updates(packages) |
✅ | apt, dnf, yum, apk, pacman |
get_services() |
✅ | systemd (fallback: SysV service) |
get_users() |
✅ | /etc/passwd + /etc/group |
get_processes() |
✅ | ps axo |
get_cron_jobs() |
✅ | user crontabs + /etc/cron.d/ |
Package manager auto-detection
The driver probes for each binary in order via command -v:
apt → dnf → yum → apk → pacman
Force a specific package manager:
optional_args={"pkg_manager": "dnf"}
SSH user permissions
The SSH user needs read access to:
| Data | Required permission |
|---|---|
/etc/passwd, /etc/group |
world-readable (default) |
/proc/uptime, /sys/class/dmi/… |
world-readable (default) |
User crontabs (/var/spool/cron/…) |
root or sudo required |
systemctl is-enabled <unit> |
unprivileged on most distros |
apt list --upgradable |
may require apt-get update (root) |
dnf check-update / yum check-update |
unprivileged, but slower without cache |
For full functionality it is recommended to run as root or grant passwordless sudo for
the above commands.
Tested distributions
| Distribution | Version | Package manager | Tested |
|---|---|---|---|
| Debian | 12 (Bookworm) | apt | ✅ |
| Ubuntu | 22.04 LTS | apt | ✅ |
| Rocky Linux | 9 | dnf | planned |
| Alpine Linux | 3.19 | apk | planned |
| Arch Linux | rolling | pacman | planned |
Contributions for additional distributions and versions are welcome.
Development
# Create venv
python -m venv .venv
source .venv/bin/activate
# Install in editable mode with dev dependencies
pip install -e ../napalm-device-types/ -e ".[dev]"
# Run tests
pytest tests/ -v
# Lint / format
ruff check napalm_linux/
ruff format napalm_linux/
License
Apache 2.0
Languages
Python
100%