Search code examples
ansibleansible-2.xansible-facts

Using multi-valued variable in a playbook


I am following the redhat ansible course online and I followed the below steps to use multi-valued variable in a playbook. But I am hitting an error stating there's an undefined variable

Below is my arrays.yaml file

---
- name: show arrays
  hosts: ansible1.example.com
  vars_files:
    - vars/users
  tasks:
    - name: print array values
      debug:
        msg: "User {{ item.username }} has homedirectory {{ item.homedir }} and shell {{ item.shell }}"
      with_items: "{{ users }}"

And below is vars/users file

users:
  linda:
    username: linda
    homedir: /home/linda
    shell: /bin/bash

  gokul:
    username: gokul
    homedir: /home/gokul
    shell: /bin/bash

  saha:
    username: saha
    homedir: /home/gokul/saha
    shell: /bin/bash

And below is the error that I am hitting

ansible-playbook arrays.yaml

PLAY [show arrays] *****************************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************************************************************************************************************************************************
ok: [ansible1.example.com]

TASK [print array values] **********************************************************************************************************************************************************************************************************************************
fatal: [ansible1.example.com]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'ansible.utils.unsafe_proxy.AnsibleUnsafeText object' has no attribute 'username'\n\nThe error appears to be in '/home/ansible/install/arrays.yaml': line 7, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n  tasks:\n    - name: print array values\n      ^ here\n"}

PLAY RECAP *************************************************************************************************************************************************************************************************************************************************
ansible1.example.com       : ok=1    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

However, when I try to refer individual values like below in the playbook, it works fine.

---
- name: show arrays
  hosts: ansible1.example.com
  vars_files:
    - vars/users
  tasks:
    - name: print array values
      debug:
        msg: "User {{ users.gokul.username }} has homedirectory {{ users.gokul.homedir }} and shell {{ users.gokul.shell }}"

Solution

  • It's not possible to iterate a dictionary. Either the code or the data should be changed.

    1. Change data

    Use a list of users instead of a dictionary. For example, the list below

    users:
      - username: linda
        homedir: /home/linda
        shell: /bin/bash
      - username: gokul
        homedir: /home/gokul
        shell: /bin/bash
      - username: saha
        homedir: /home/gokul/saha
        shell: /bin/bash
    

    would work as expected

    - name: print array values
      debug:
        msg: "User {{ item.username }}
              has homedirectory {{ item.homedir }}
              and shell {{ item.shell }}"
      loop: "{{ users }}"
    

    2. Change code

    It's possible to use the users dictionary with the filter dict2items. For example, the task below would give the same result

    - name: print array values
      debug:
        msg: "User {{ item.value.username }}
              has homedirectory {{ item.value.homedir }}
              and shell {{ item.value.shell }}"
      loop: "{{ users|dict2items }}"