ansible loop over dict with loop control

46 Views Asked by At

i read a yml file with lookup and try to loop over the dict.

yml file:

    ---
    root:
      children_one:
        attribute_one: true
        attribute_two: foo
      children_two:
        attribute_one: false
        attribute_two: bar
      children_three:
        attribute_one: false
        attribute_two: foo`

in the ansible playbook i will print out all children with the attribute_two when the attribute_one is false

    - ansible.builtin.debug:
        msg: "{{ item }} - {{ item.attribute_two }}"
      with_items: "{{ (lookup('template', 'file.yml.j2') | from_yaml).root }}"
      when: (item.attribute_one | lower) == 'false'

the error say there ist no attribute attribute_one.

how can i resolve it?

Thanks

1

There are 1 best solutions below

0
Vladimir Botka On

Use with_dict. This converts the dictionary to a list. The type of attribute_one is boolean. This simplifies the condition

    - debug:
        msg: "{{ item }}"
      with_dict: "{{ (lookup('template', 'file.yml') | from_yaml).root }}"
      when: not item.value.attribute_one

gives

skipping: [localhost] => (item={'key': 'children_one', 'value': {'attribute_one': True, 'attribute_two': 'foo'}}) 
ok: [localhost] => (item={'key': 'children_two', 'value': {'attribute_one': False, 'attribute_two': 'bar'}}) => 
  msg:
    key: children_two
    value:
      attribute_one: false
      attribute_two: bar
ok: [localhost] => (item={'key': 'children_three', 'value': {'attribute_one': False, 'attribute_two': 'foo`'}}) => 
  msg:
    key: children_three
    value:
      attribute_one: false
      attribute_two: foo`

You'll get the same using loop and the filter dict2items

    - debug:
        msg: "{{ item }}"
      loop: "{{ (lookup('template', 'file.yml') | from_yaml).root |
                 dict2items }}"
      when: not item.value.attribute_one

This can be further improved by simplifying the label and rejecting attribute_one in the pipe

    - debug:
        msg: "{{ item }}"
      loop: "{{ (lookup('template', 'file.yml') | from_yaml).root |
                dict2items |
                rejectattr('value.attribute_one') }}"
      loop_control:
        label: "{{ item.key }}"

gives

ok: [localhost] => (item=children_two) => 
  msg:
    key: children_two
    value:
      attribute_one: false
      attribute_two: bar
ok: [localhost] => (item=children_three) => 
  msg:
    key: children_three
    value:
      attribute_one: false
      attribute_two: foo`

Example of a complete playbook for testing

shell> cat file.yml 
---
root:
  children_one:
    attribute_one: true
    attribute_two: foo
  children_two:
    attribute_one: false
    attribute_two: bar
  children_three:
    attribute_one: false
    attribute_two: foo`
shell> cat pb.yml
- hosts: localhost

  tasks:

    - debug:
        msg: "{{ item }}"
      with_dict: "{{ (lookup('template', 'file.yml') | from_yaml).root }}"
      when: not item.value.attribute_one

    - debug:
        msg: "{{ item }}"
      loop: "{{ (lookup('template', 'file.yml') | from_yaml).root |
                 dict2items }}"
      when: not item.value.attribute_one

    - debug:
        msg: "{{ item }}"
      loop: "{{ (lookup('template', 'file.yml') | from_yaml).root |
                dict2items |
                rejectattr('value.attribute_one') }}"
      loop_control:
        label: "{{ item.key }}"