From c22e580d3d146391884acc34fcf45b3b4a68b647 Mon Sep 17 00:00:00 2001 From: jakub Date: Sun, 30 Aug 2026 01:01:28 +0200 Subject: [PATCH] Add tagged Portainer update role --- roles/update_portainer/defaults/main.yml | 4 ++ roles/update_portainer/tasks/main.yml | 66 ++++++++++++++++++++++++ update.yml | 12 ++++- 3 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 roles/update_portainer/defaults/main.yml create mode 100644 roles/update_portainer/tasks/main.yml diff --git a/roles/update_portainer/defaults/main.yml b/roles/update_portainer/defaults/main.yml new file mode 100644 index 0000000..e132cf0 --- /dev/null +++ b/roles/update_portainer/defaults/main.yml @@ -0,0 +1,4 @@ +--- +# Watchtower is used only as a one-shot updater. It recreates the selected +# Portainer containers with their existing configuration and then removes itself. +portainer_watchtower_image: containrrr/watchtower:latest diff --git a/roles/update_portainer/tasks/main.yml b/roles/update_portainer/tasks/main.yml new file mode 100644 index 0000000..af01678 --- /dev/null +++ b/roles/update_portainer/tasks/main.yml @@ -0,0 +1,66 @@ +--- +- name: Check whether Docker is available + ansible.builtin.command: + argv: + - docker + - info + register: portainer_docker_info + changed_when: false + failed_when: false + +- name: Find Docker containers + when: portainer_docker_info.rc == 0 + block: + - name: List all container IDs + ansible.builtin.command: + argv: + - docker + - container + - ls + - --all + - --quiet + register: portainer_all_containers + changed_when: false + + - name: Inspect container images + ansible.builtin.command: + argv: + - docker + - container + - inspect + - --format + - "{% raw %}{{.Config.Image}}{% endraw %}" + - "{{ item }}" + loop: "{{ portainer_all_containers.stdout_lines }}" + register: portainer_container_inspections + changed_when: false + + - name: Select Portainer CE and Business Edition server containers + ansible.builtin.set_fact: + portainer_container_ids: >- + {{ portainer_container_inspections.results + | selectattr('stdout', 'match', + '^(?:[^/]+/)?portainer/(?:portainer|portainer-(?:ce|ee))(?::|@|$)') + | map(attribute='item') + | list }} + + - name: Update discovered Portainer containers + ansible.builtin.command: + argv: >- + {{ ['docker', 'run', '--rm', '--pull', 'always', + '--volume', '/var/run/docker.sock:/var/run/docker.sock', + portainer_watchtower_image, '--run-once', '--cleanup', + '--include-stopped'] + + portainer_container_ids }} + register: portainer_watchtower + changed_when: >- + (portainer_watchtower.stdout ~ portainer_watchtower.stderr) + is regex('Updated=[1-9][0-9]*') + when: + - portainer_container_ids | length > 0 + - not ansible_check_mode + + - name: Report when no Portainer server is installed + ansible.builtin.debug: + msg: No Portainer CE or Business Edition server container found; skipping. + when: portainer_container_ids | length == 0 diff --git a/update.yml b/update.yml index 3a336d6..20932f3 100644 --- a/update.yml +++ b/update.yml @@ -88,4 +88,14 @@ - name: Notify if reboot required debug: msg: "Reboot required on {{ inventory_hostname }}" - when: reboot_required.stat.exists \ No newline at end of file + when: reboot_required.stat.exists + + - name: Update Portainer containers + ansible.builtin.include_role: + name: update_portainer + apply: + tags: + - portainer + tags: + - never + - portainer