Bootstrap FreeKB - Ansible - Loop through a nested List
Ansible - Loop through a nested List

Updated:   |  Ansible articles

Let's say you are using the vars plugin to create a nested list. In this example, the "food" key is an outer list that contains two inner lists, fruit and veggies. debug can be used to output the entire list.

---
- hosts: localhost
  gather_facts: false
  vars:
    food:
      - fruit:
        - apple
        - banana
        - orange
        - grapes
      - veggies:
        - onion
        - pepper
        - carrot
        - celery
  tasks:
  - ansible.builtin.debug:
      var: food
...

 

Which should return the following.

ok: [localhost] => {
    "food": [
        {
            "fruit": [
                "apple", 
                "banana", 
                "orange", 
                "grapes"
            ]
        }, 
        {
            "veggies": [
                "onion", 
                "pepper", 
                "carrot", 
                "celery"
            ]
        }
    ]
}

 

You can loop through the outer list.

---
- hosts: localhost
  gather_facts: false
  vars:
    food:
      - fruit:
        - apple
        - banana
        - orange
        - grapes
      - veggies:
        - onion
        - pepper
        - carrot
        - celery
  tasks:
  - name: loop through the food list
    ansible.builtin.debug:
      msg: "{{ item }}"
    with_items: "{{ food }}"
...

 

Which should return the following.

ok: [localhost] => (item={u'fruit': [u'apple', u'banana', u'orange', u'grapes']}) => {
    "msg": {
        "fruit": [
            "apple", 
            "banana", 
            "orange", 
            "grapes"
        ]
    }
}
ok: [localhost] => (item={u'veggies': [u'onion', u'pepper', u'carrot', u'celery']}) => {
    "msg": {
        "veggies": [
            "onion", 
            "pepper", 
            "carrot", 
            "celery"
        ]
    }
}

 

You can use an index numbers to loop through the inner lists.

---
- hosts: localhost
  gather_facts: false
  vars:
    food:
      - fruit:
        - apple
        - banana
        - orange
        - grapes
      - veggies:
        - onion
        - pepper
        - carrot
        - celery
  tasks:
  - name: loop through the fruit list
    ansible.builtin.debug:
      msg: "{{ item }}"
    with_items: "{{ food[0].fruit }}"

  - name: loop through the veggies
    ansible.builtin.debug:
      msg: "{{ item }}"
    with_items: "{{ food[1].veggies }}"
...

 

Which should return the following.

TASK [loop through the fruit list]
ok: [localhost] => (item=apple) => {
    "msg": "apple"
}
ok: [localhost] => (item=banana) => {
    "msg": "banana"
}
ok: [localhost] => (item=orange) => {
    "msg": "orange"
}
ok: [localhost] => (item=grapes) => {
    "msg": "grapes"
}

TASK [loop through the veggies list]
ok: [localhost] => (item=onion) => {
    "msg": "onion"
}
ok: [localhost] => (item=pepper) => {
    "msg": "pepper"
}
ok: [localhost] => (item=carrot) => {
    "msg": "carrot"
}
ok: [localhost] => (item=celery) => {
    "msg": "celery"
}

 


Set Fact

One option is to use the set_fact module to create a new variable that contains the nested list. In this example, a variable named "fruit" is created that contains the nested "fruit" list.

---
- hosts: localhost
  gather_facts: false
  vars:
    food:
      - fruit:
        - apple
        - banana
        - orange
        - grapes
  tasks:
  - name: set_fact fruit
    ansible.builtin.set_fact:
      fruit: "{{ item.fruit }}"
    with_items: "{{ food }}"

  - name: loop through the 'fruit' list
    ansible.builtin.debug:
      var: item
    with_items: "{{ fruit }}"
...

 

Which should produce the following.

ok: [localhost] => (item=apple) => {
    "ansible_loop_var": "item", 
    "item": "apple"
}
ok: [localhost] => (item=banana) => {
    "ansible_loop_var": "item", 
    "item": "banana"
}
ok: [localhost] => (item=orange) => {
    "ansible_loop_var": "item", 
    "item": "orange"
}
ok: [localhost] => (item=grapes) => {
    "ansible_loop_var": "item", 
    "item": "grapes"
}

 


Inner / Outer Playbooks

Another option is to create two playbooks to loop through the "food" and "fruit" keys. Let's say outer.yml contains the following. This playbook uses the include_tasks module and the loop parameter with the loop_control loop_var option so that each item of the "food" list uses "food_item" as it's identifier.

---
- hosts: localhost
  gather_facts: false
  vars:
    food:
      - fruit:
        - apple
        - banana
        - orange
        - grapes
  tasks:
  - include_tasks: inner.yml
    loop: "{{ food }}"
      loop_var: food_item
...

 

And inner.yml could have the following to loop through the items in the "fruit" key.

- debug:
    var: item
  loop: "{{ food_item.fruit }}"

 

Which should output the following.

ok: [localhost] => (item=apple) => {
    "ansible_loop_var": "item", 
    "item": "apple"
}
ok: [localhost] => (item=banana) => {
    "ansible_loop_var": "item", 
    "item": "banana"
}
ok: [localhost] => (item=orange) => {
    "ansible_loop_var": "item", 
    "item": "orange"
}
ok: [localhost] => (item=grapes) => {
    "ansible_loop_var": "item", 
    "item": "grapes"
}

 




Did you find this article helpful?

If so, consider buying me a coffee over at Buy Me A Coffee



Comments


Add a Comment


Please enter 99fbc5 in the box below so that we can be sure you are a human.