skip to Main Content

I’d like to set a common_apt_packages list based on OS distribution, so I’ve used jinja2 if condition as the script below, but the return common_apt_packages type is AnsibleUnsafeText

- hosts: localhost
  vars:
    common_apt_packages_ubuntu_22_04:
    - ack-grep
    - acl
    - apt-transport-https
    - build-essential
    - dstat
    - git-core
    - htop
    - iftop
    - iotop
  tasks:
    - name: Set common_apt_packages for ubuntu {{ ansible_distribution_version }}
      set_fact:
        common_apt_packages: "{% if ansible_distribution_version =='22.04' %} {{ common_apt_packages_ubuntu_22_04 }} {% else %} {{ common_apt_packages_ubuntu_18_04 }} {% endif %}"

How can I improve the script to return common_apt_packages as a List variable?

2

Answers


  1. Just remove the white spaces between %} {{ and }} {%, because Ansible will then handle it as a string, not as a list.
    With type_debug you can get the output type.

    - hosts: localhost
      vars:
        common_apt_packages_ubuntu_22_04:
        - ack-grep
        - acl
        common_apt_packages_ubuntu_18_04:
        - vim
        - nano
      tasks:
        - name: Set common_apt_packages for ubuntu {{ ansible_distribution_version }}
          set_fact:
            common_apt_packages_without_spaces: "{% if ansible_distribution_version =='22.04' %}{{ common_apt_packages_ubuntu_22_04 }}{% else %}{{ common_apt_packages_ubuntu_18_04 }}{% endif %}"
    
        - name: Set common_apt_packages for ubuntu {{ ansible_distribution_version }}
          set_fact:
            common_apt_packages_with_spaces: "{% if ansible_distribution_version =='22.04' %} {{ common_apt_packages_ubuntu_22_04 }} {% else %} {{ common_apt_packages_ubuntu_18_04 }} {% endif %}"
    
        - debug:
            msg: "{{ common_apt_packages_without_spaces }} ==> {{ common_apt_packages_without_spaces | type_debug }}"
    
        - debug:
            msg: "{{ common_apt_packages_with_spaces }} ==> {{ common_apt_packages_with_spaces | type_debug }}"
    
    TASK [Set common_apt_packages for ubuntu 20.04] ************
    ok: [localhost]
    
    TASK [debug] ***********************************************
    ok: [localhost] => {
        "msg": "['vim', 'nano'] ==> list"
    }
    
    TASK [debug] ***********************************************
    ok: [localhost] => {
        "msg": " ['vim', 'nano']  ==> AnsibleUnsafeText"
    }
    

    When you try to install them using the apt module:

    # without white spaces
    "package": [
                    "vim",
                    "nano"
                ]
    
    # with white spaces
    "package": [
                    " ['vim'",
                    " 'nano'] "
                ]
    "msg": "No package(s) matching '['vim'' available"
    
    Login or Signup to reply.
  2. Create the lists. For example in group_vars

    shell> cat group_vars/all/packages.yml
    list_of_packages_for_18_04: [pkg1_18_04, pkg2_18_04, pkg3_18_04]
    list_of_packages_for_20_04: [pkg1_20_04, pkg2_20_04, pkg3_20_04]
    list_of_packages_for_22_04: [pkg1_22_04, pkg2_22_04, pkg3_22_04]
    default_list_of_packages: [pkg1, pkg2, pkg3]
    

    and put the lists of the packages into a dictionary. For example,

    - hosts: localhost
      vars:
        packages:
          '18.04': "{{ list_of_packages_for_18_04 }}"
          '20.04': "{{ list_of_packages_for_20_04 }}"
          '22.04': "{{ list_of_packages_for_22_04 }}"
          'default': "{{ default_list_of_packages }}"
        my_packages: "{{ packages[ansible_distribution_version]|
                         default(packages.default) }}"
      tasks:
        - debug:
            var: ansible_distribution_version
        - debug:
            var: my_packages
    

    gives (abridged)

    TASK [debug] ******************************************************
    ok: [localhost] => 
      ansible_distribution_version: '20.04'
    
    TASK [debug] ******************************************************
    ok: [localhost] => 
    my_packages:
      - pkg1_20_04
      - pkg2_20_04
      - pkg3_20_04
    

    Your problem is that output of Jinja is always a string. Ansible should convert it automatically if it is a valid YAML. If you for whatever reason have to use Jinja create the string first and convert it to YAML explicitly. For example,

        - set_fact:
            packages_str: |
              {% if ansible_distribution_version == '22.04' %}
              {{ common_apt_packages_ubuntu_22_04 }}
              {% else %}
              {{ common_apt_packages_ubuntu_18_04 }}
              {% endif %}"
        - set_fact:
            packages: "{{ packages_str|from_yaml }}"
    

    You can’t put the declarations into a single set_fact because the second declaration knows nothing about the first one. But, you can put them into any vars, of course.


    Test of the conversion in Ansible 2.12.9 Python 3.8.5, and Jinja 3.0.1

    - hosts: localhost
      vars:
        packages_str: |
              {% if ansible_distribution_version == '20.04' %}
              {{ list_of_packages_for_20_04 }}
              {% else %}
              {{ list_of_packages_for_18_04 }}
              {% endif %}
        packages: "{{ packages_str|from_yaml }}"
    
      tasks:
        - debug:
            var: ansible_distribution_version
        - debug:
            var: packages_str|type_debug
        - debug:
            var: packages|type_debug
        - debug:
            var: packages_str
        - debug:
            var: packages
    

    gives (abridged)

    TASK [debug] **************************************************
    ok: [localhost] => 
      ansible_distribution_version: '20.04'
    
    TASK [debug] **************************************************
    ok: [localhost] => 
      packages_str|type_debug: list
    
    TASK [debug] **************************************************
    ok: [localhost] => 
      packages|type_debug: list
    
    TASK [debug] **************************************************
    ok: [localhost] => 
      packages_str:
      - pkg1_20_04
      - pkg2_20_04
      - pkg3_20_04
    
    TASK [debug] **************************************************
    ok: [localhost] => 
      packages:
      - pkg1_20_04
      - pkg2_20_04
      - pkg3_20_04
    

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search