SysDeck/bridge/containers.py

77 lines
2.1 KiB
Python
Executable File

#!/usr/bin/env python3
"""
SysDeck - Containers Bridge Helper
Author: Jeremy Anderson (https://dcos.net)
Aggregates podman container state with systemd unit status so the JS
panel can render a unified view in a single spawn call.
Usage:
python3 -m sysdeck.bridge.containers list
python3 -m sysdeck.bridge.containers inspect <id>
"""
import json
import subprocess
import sys
from typing import Any
def run(argv: list[str]) -> str:
"""Run a command and return stdout. Raises CalledProcessError on failure."""
return subprocess.run(
argv, capture_output=True, text=True, check=True,
).stdout
def list_containers() -> list[dict[str, Any]]:
"""Return containers with their matching systemd unit name (if any)."""
try:
raw = run(["podman", "ps", "-a", "--format", "json"])
containers = json.loads(raw) if raw.strip() else []
except (subprocess.CalledProcessError, FileNotFoundError):
return []
# Step-down: enrich each container with its systemd scope unit.
# cgroup name pattern: /machine.slice/libpod-<id>.scope
return [
{
"id": c.get("Id", "")[:12],
"name": c.get("Names", [""])[0],
"image": c.get("Image", ""),
"status": c.get("Status", ""),
"state": c.get("State", ""),
"systemdUnit": f"libpod-{c.get('Id', '')}.scope",
}
for c in containers
]
def inspect(container_id: str) -> dict[str, Any]:
"""Inspect a single container by ID prefix."""
raw = run(["podman", "inspect", container_id])
data = json.loads(raw)
return data[0] if data else {}
COMMANDS = {
"list": lambda _args: list_containers(),
"inspect": lambda args: inspect(args[0]) if args else {},
}
def main(argv: list[str]) -> int:
if not argv or argv[0] in ("-h", "--help"):
print(__doc__)
return 0
cmd = COMMANDS.get(argv[0])
if not cmd:
print(f"Unknown subcommand: {argv[0]}", file=sys.stderr)
return 2
print(json.dumps(cmd(argv[1:]), indent=2))
return 0
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))