Dan Fishman
Dan Fishman

Reputation: 5

How to Loop through multiple lists of dictionaries using 'loop' syntax?

I'm new to Ansible and trying to figure out the syntax of YAML and Ansible.

I ran into a fatal error while trying to loop through multiple lists of dictionaries, using 'loop' and not 'with_items'.

---
- hosts: localhost
  vars:
     allow_list:
      - {name: user1, uid: 1001}
      - {name: user2, uid: 1002}
      - {name: user3, uid: 1003}
      - {name: user4, uid: 1004}
      
     deny_list: 
      - {name: user11, uid: 1011}
      - {name: user12, uid: 1012}
      - {name: user13, uid: 1013}
      - {name: user14, uid: 1014}

  tasks:
     - name: debug all users
       debug:
        msg: "{{user.name}} {{user.uid}}"
       loop:
          - "{{allow_list}}"
          - "{{deny_list}}"
       loop_control:
        loop_var: user

error log:

fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'list object' has no attribute 'name'\n\nThe error appears to have been in '/Ansible/playbook.yml': line 17, column 8, 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: debug all users\n       ^ here\n"}

Upvotes: 0

Views: 429

Answers (1)

toydarian
toydarian

Reputation: 4554

You are looping over one list with two items here and the items are your initial lists. What you need to do is to join those two lists with {{ allow_list + deny_list }}. Check out this post.

Your code fixed:

---
- hosts: localhost
  vars:
     allow_list:
      - { name: user1, uid: 1001 }
      - { name: user2, uid: 1002 }
      - { name: user3, uid: 1003 }
      - { name: user4, uid: 1004 }
      
     deny_list: 
      - { name: user11, uid: 1011 }
      - { name: user12, uid: 1012 }
      - { name: user13, uid: 1013 }
      - { name: user14, uid: 1014 }

  tasks:
     - name: debug all users
       debug:
         msg: "{{ item.name }} {{ item.uid }}"
       loop: "{{ allow_list + deny_list }}"

If you wanted to handle it in a set_fact block:

---
- hosts: localhost
  vars:
     allow_list:
      - { name: user1, uid: 1001 }
      - { name: user2, uid: 1002 }
      - { name: user3, uid: 1003 }
      - { name: user4, uid: 1004 }
      
     deny_list: 
      - { name: user11, uid: 1011 }
      - { name: user12, uid: 1012 }
      - { name: user13, uid: 1013 }
      - { name: user14, uid: 1014 }

     some_var: 42

  tasks:
    - name: set fact on condition
      set_fact:
        userlist: "{{ allow_list }}"
      when: some_var <= 5

    - name: set fact on negated condition
      set_fact:
        userlist: "{{ allow_list + deny_list }}"
      when: some_var > 5

    - name: debug all users
      debug:
        msg: "{{ item.name }} {{ item.uid }}"
      loop: "{{ userlist }}"

You need to make sure that exactly one of your set_fact blocks runs every time, otherwise you will end up with errors or unexpected results.

Upvotes: 1

Related Questions