Search code examples
ansiblejinja2ansible-template

Ansible create a list from a loop inline


I have a playbook that goes like this:

    - name: Install php extensions
      ansible.builtin.apt:
        pkg:
        - php{{ php_version }}{{ item.pkg_extension }}
       loop:
        - { pkg_extension: -mysql }
        - { pkg_extension: -bz2 }
        - { pkg_extension: -curl }
        - { pkg_extension: -gd }
        - { pkg_extension: -imap }
        - { pkg_extension: -mbstring }
        - { pkg_extension: -xml }
        - { pkg_extension: -zip }
      when: php_key_setup is succeeded and nginx_install is succeeded and php_base_install is succeeded
      register: php_install

Sometimes for reasons unknown to me, this fails for one of the packages in the loop. I want to pass these packages as a list or a dictionary to the apt module instead, like in

https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_loops.html#iterating-over-a-simple-list :

- name: Optimal yum
  ansible.builtin.yum:
    name: "{{ list_of_packages }}"
    state: present

How can I create this list from this loop, concatenating everything without adding an extra step to create this list and reuse it afterwards?


Solution

  • Given the variables

      php_version: 8.3
      php_pkg_extensions:
        - mysql
        - bz2
        - curl
        - gd
        - imap
        - mbstring
        - xml
        - zip
    

    Declare the list

      packages: "{{ ['php' ~ php_version]|
                    product(php_pkg_extensions)|
                    map('join', '-') }}"
    

    gives what you want

      packages:
      - php8.3-mysql
      - php8.3-bz2
      - php8.3-curl
      - php8.3-gd
      - php8.3-imap
      - php8.3-mbstring
      - php8.3-xml
      - php8.3-zip
    

    Example of a complete playbook for testing

    - hosts: localhost
    
      vars:
    
        php_version: 8.3
        php_pkg_extensions:
            - mysql
            - bz2
            - curl
            - gd
            - imap
            - mbstring
            - xml
            - zip
        packages: "{{ ['php' ~ php_version]|
                      product(php_pkg_extensions)|
                      map('join', '-') }}"
    
      tasks:
    
        - debug:
            var: packages
    
        - name: Install php extensions
          ansible.builtin.apt:
            pkg: "{{ packages }}"
          when: install_php_extensions|d(false)|bool