Christian ManivongandClaude Opus 5 549e8c01e0 fix(docker): keep a resolvable image reference when the tag has moved
`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>
2026-09-01 05:37:52 +02:00

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

S
Description
No description provided
Readme
733 KiB
Languages
Python 100%