--- - name: Install and configure Podman hosts: ci_runners become: true vars: # Packages common to both Debian and RHEL families podman_base_packages: - podman - podman-docker # Debian/Ubuntu specific packages podman_debian_packages: - podman-compose # RHEL-family specific packages (adjust or add epel-release if compose is needed) podman_rhel_packages: [] # Set to true if you need the Docker-compatible API socket (e.g., for Woodpecker CI) podman_enable_socket: true tasks: - name: Gather distribution-specific facts ansible.builtin.setup: gather_subset: - "!all" - distribution - os_family - name: Install Podman packages on Debian/Ubuntu ansible.builtin.apt: name: "{{ podman_base_packages + podman_debian_packages }}" state: present update_cache: true cache_valid_time: 3600 when: ansible_facts['os_family'] == 'Debian' - name: Install Podman packages on RHEL/Rocky/AlmaLinux/CentOS ansible.builtin.dnf: name: "{{ podman_base_packages + podman_rhel_packages }}" state: present when: ansible_facts['os_family'] == 'RedHat' - name: Enable and start system-wide Podman socket ansible.builtin.systemd: name: podman.socket state: started enabled: true when: podman_enable_socket - name: Verify Podman installation ansible.builtin.command: podman --version register: podman_version_output changed_when: false - name: Run Podman containers hosts: ci_runners become: true tasks: - name: Determine mount host paths ansible.builtin.set_fact: _mount_paths: >- {{ _mount_paths | default([]) + (item.value.volumes | map('regex_replace', ':.*$', '') | list) }} loop: "{{ podman_containers | default({}) | dict2items }}" when: - item.value.volumes is defined - item.value.state | default('started') != 'absent' - name: Check status of mount paths on host ansible.builtin.stat: path: "{{ item }}" loop: "{{ _mount_paths | default([]) | unique }}" register: _mount_stats - name: Ensure container mount directories exist ansible.builtin.file: # If the target path exists and is a file/socket/link, create its parent dir. # If it doesn't exist at all, create it as a directory. path: "{{ (item.stat.exists and not item.stat.isdir) | ternary(item.item | dirname, item.item) }}" state: directory mode: "0755" loop: "{{ _mount_stats.results }}" # Skip creating anything if the file/socket already exists when: not (item.stat.exists and not item.stat.isdir) - name: Manage Podman containers containers.podman.podman_container: name: "{{ item.key }}" image: "{{ item.value.image | default(omit) }}" state: "{{ item.value.state | default('started') }}" command: "{{ item.value.command | default(omit) }}" ports: "{{ item.value.ports | default(omit) }}" volumes: "{{ item.value.volumes | default(omit) }}" env: "{{ item.value.env | default(omit) }}" network: "{{ item.value.network | default(omit) }}" privileged: "{{ item.value.privileged | default(false) }}" recreate: "{{ item.value.recreate | default(false) }}" generate_systemd: "{{ item.value.generate_systemd | default(omit) }}" loop: "{{ podman_containers | default({}) | dict2items }}"