#!/usr/bin/env python3 """This script replaces `podman auto-update`. If a digest in a registry has been updated, `podman pull` may not necessarily pull the image for quite some time. However, `auto-update` will still try every day, but since it doesn't check if the new digest has actually been pulled it will restart the service again and again. This script attempts to solve the problem by explicitly checking the digest after the pull. However, it assumes that there is only service that needs restarting on updates and that its called .service so it is not (yet) a drop-in replacement for `podman auto-update`. """ import getpass import json import subprocess def podman_ps(): out = subprocess.run(["podman", "ps", "--format", "json"], capture_output=True, check=True) return json.loads(out.stdout) def podman_image_inspect(image): out = subprocess.run(["podman", "image", "inspect", "--format", "json", image], capture_output=True, check=True) inspect = json.loads(out.stdout) assert inspect if len(inspect) > 1: raise ValueError("podman image inspect returned multiple entries") return inspect[0] def podman_pull(image): subprocess.run(["podman", "pull", image], capture_output=True, check=True) if __name__ == "__main__": containers = podman_ps() images = set() for container in containers: labels = container.get("Labels", None) if labels is None: continue autoupdate = labels.get("io.containers.autoupdate", None) if (autoupdate is None) or (autoupdate == "disabled"): continue if autoupdate != "image": raise ValueError(f"unrecognised autopdate label: {autoupdate}") images.add(container["Image"]) updated = [] for image in images: inspect = podman_image_inspect(image) original_digest = inspect["Digest"] podman_pull(image) inspect = podman_image_inspect(image) new_digest = inspect["Digest"] if new_digest != original_digest: updated.append(image) if updated: print(f"The following images have been updated: {updated}") subprocess.run(["systemctl", "--user", "restart", f"{getpass.getuser()}.service"], check=True)