Loop over vars not working

157 views
Skip to first unread message

Sharon Day

unread,
Mar 19, 2021, 9:24:36 AM3/19/21
to Ansible Project
I have a playbook that is doing two lookup for the next available Infoblox network subnet in two different networks.  I set the facts and I'm trying to loop over the results of the two lookups.  I print the results of the lookup so I can see I'm getting back what I expected.  I think the issue is I'm trying to create the network from the lookup results with a single task.  If I break it out into two different task one for each network returned from the lookup it fails.  Its somehow related to the loop statement.   I've changed the IPs so not to show our acutal IP space.

Here's my playbook:

vars:
   verizon: 1.1.1.0/20
   at_t: 1.1.2.0/20

    - name: Return the next available Verizon IP subnet for network
      set_fact:
         verizon_pe_ce: "{{ lookup('nios_next_network', verizon, cidr=30, provider=cli_infoblox ) }}"
      delegate_to: localhost
    - name: Print the subnet
      debug:
        var: verizon_pe_ce

    - name: Return the next available at_t IP subnet for network
      set_fact:
         att_pe_ce: "{{ lookup('nios_next_network', at_t, cidr=30, provider=cli_infoblox ) }}"
      delegate_to: localhost
    - name: Print the subnet
      debug:
        var: att_pe_ce

    - name: configure a network ipv4
      nios_network:
        network: "{{ item }}"
        comment: WAN ansible assignment
        extattrs:
          Network_Name: ansible_test_assignment
          Network_Environment: CLIENT_REMOTE
          Client_Site_#: "{{ client_num }}-{{ client_name }} - ({{ city }}, {{ state }})"
          CL_RTR_INT: [ "RTR A", "WAN Network _30" ]
          VRF_NAME: CL
          Network_Container: SNG
        state: present
        provider: "{{ cli_infoblox }}"
      loop: 
          - verizon_pe_ce
          - att_pe_ce
      delegate_to: localhost

This is the output from the lookups:

TASK [Print the subnet] **********************************************************************************************************************************
task path: /automation/ansible/playbooks/infoblox/next_available_network.yml:28
ok: [10.x.x.x] => {
    "verizon_pe_ce": [
        "1.1.1.36/30"
    ]
}

TASK [Print the subnet] **********************************************************************************************************************************
task path: /automation/ansible/playbooks/infoblox/next_available_network.yml:36
ok: [10.x.x.x] => {
    "att_pe_ce": [
        "1.1.2.36/30"
    ]
}


The error is the same for both the verizon_pe_ce and the att_pe_ce.  Here's the output related to the att_pe_ce.

TypeError: 'NoneType' object is not iterable
failed: [10.x.x.x] (item=att_pe_ce) => {
    "ansible_loop_var": "item",
    "changed": false,
    "item": "att_pe_ce",
    "module_stderr": "Traceback (most recent call last):\n  File \"/home/e001gx/.ansible/tmp/ansible-tmp-1616159168.3519313-122151-53449377816842/AnsiballZ_nios_network.py\", line 102, in <module>\n    _ansiballz_main()\n  File \"/home/e001gx/.ansible/tmp/ansible-tmp-1616159168.3519313-122151-53449377816842/AnsiballZ_nios_network.py\", line 94, in _ansiballz_main\n    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n  File \"/home/e0013192gx/.ansible/tmp/ansible-tmp-1616159168.3519313-122151-53449377816842/AnsiballZ_nios_network.py\", line 40, in invoke_module\n    runpy.run_module(mod_name='ansible_collections.infoblox.nios_modules.plugins.modules.nios_network', init_globals=None, run_name='__main__', alter_sys=True)\n  File \"/opt/rh/rh-python36/root/usr/lib64/python3.6/runpy.py\", line 205, in run_module\n    return _run_module_code(code, init_globals, run_name, mod_spec)\n  File \"/opt/rh/rh-python36/root/usr/lib64/python3.6/runpy.py\", line 96, in _run_module_code\n    mod_name, mod_spec, pkg_name, script_name)\n  File \"/opt/rh/rh-python36/root/usr/lib64/python3.6/runpy.py\", line 85, in _run_code\n    exec(code, run_globals)\n  File \"/tmp/ansible_nios_network_payload_5eez7968/ansible_nios_network_payload.zip/ansible_collections/infoblox/nios_modules/plugins/modules/nios_network.py\", line 302, in <module>\n  File \"/tmp/ansible_nios_network_payload_5eez7968/ansible_nios_network_payload.zip/ansible_collections/infoblox/nios_modules/plugins/modules/nios_network.py\", line 290, in main\nTypeError: 'NoneType' object is not iterable\n",
    "module_stdout": "",
    "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
    "rc": 1
}


Brian Coca

unread,
Mar 19, 2021, 10:37:46 AM3/19/21
to Ansible Project
You are looping over 2 strings, loop does not template by default:

loop: '{{ [verizon_pe_ce, att_pe_ce] }}'

or
loop:
- ' {{verizon_pe_ce }}'
- '{{ att_pe_ce }}'

or keep loop as you have it but then use

network: "{{ q('vars', item)[0] }}"

--
----------
Brian Coca

Sharon Day

unread,
Mar 19, 2021, 1:09:16 PM3/19/21
to Ansible Project
I tried,

loop: '{{ [verizon_pe_ce, att_pe_ce] }}'

And

loop:
- ' {{verizon_pe_ce }}'
- '{{ att_pe_ce }}'

Both fail with the same error message.  I'm not sure what you meant by your third example.

Brian Coca

unread,
Mar 19, 2021, 1:19:46 PM3/19/21
to Ansible Project
Those were correcting your syntax, but that aside, the module has a
bug (always the case if you see MODULE_FAILURE).

--
----------
Brian Coca

Gaétan QUENTIN@Work

unread,
Jun 22, 2021, 5:09:03 PM6/22/21
to Ansible Project

Hi,

 My goal is to iterate items on a json list response, and find the good item. The good item is the one on which all test tasks succeed. Tests are done in the included_task yaml file.


 But my playbook do not work, i am unable to break the outer calling loop task if i found the good item from within  the called included task list.


The outer task :

- name: set item_ok
set_fact:
item_ok: false
- name: call included task for each items
include_tasks: "tests_on_item.yml"
loop: "{{ item_list }}"
loop_control:
loop_var: outer_item
when: item_ok is false


and inner task , tests_on_item.yml:

---
- name: tests on item
vars:
task_status: "OK"
block:
- name: Show item_ok value
debug:
msg: "item_ok: {{ item_ok }}"
- name: test 1
assert:
that:
- blah blah
fail_msg: "blah "
- name: test 2
assert:
that: blah blah
fail_msg: "blah blah"
# if all preceding tasks were successfull, we have the good searched item so the last task is to set item_ok to true . But this won't work ...the calling outer task will continue to call included task for next items
- name: item found
set_fact:
item_ok: true
# if one of the tests fails, the rescue directive is executed ans this included inner tasks yaml file is ended. The outer calling task will compute the next item.
rescue:
- name: set var error
vars:
task_status: "ERROR"
debug:
msg : "task_status: ERROR"
when: task_status == 'OK'



Have you an idea?


Regards,


Gaetan

Vladimir Botka

unread,
Jun 23, 2021, 1:59:23 AM6/23/21
to Gaétan QUENTIN@Work, ansible...@googlegroups.com
On Tue, 22 Jun 2021 23:08:50 +0200
Gaétan QUENTIN@Work <work.gaet...@gmail.com> wrote:

> - name: set item_ok
> set_fact:
> item_ok: false
> - name: call included task for each items
> include_tasks: "tests_on_item.yml"
> loop: "{{ item_list }}"
> loop_control:
> loop_var: outer_item
> when: item_ok is false

It's not possible to break a loop. In some cases you can use
registered value to skip the rest of the list. But, there might be a
solution to your use-case: "Find the first item in a list that meets
a list of conditions". For example, given the list

_list:
- {a1: A, a2: 1, a3: first}
- {a1: A, a2: 2, a3: second}
- {a1: B, a2: 3, a3: third}
- {a1: A, a2: 2, a3: last}

find the first item that meets the conditions

- a1 == 'A'
- a2 == 2

The task

- set_fact:
x: "{{ _list|
selectattr('a1', 'eq', 'A')|
selectattr('a2', 'eq', 2)|
first }}"

gives

x:
a1: A
a2: 2
a3: second

If you need the index of the item

- set_fact:
i: "{{ _list.index(x) }}"

gives

i: '1'

The next option is *json_query*. The task below gives the same result

- set_fact:
x: "{{ _list|json_query(query)|first }}"
vars:
query: "[?a1 == 'A']|
[?a2 == `2`]"


A custom filter might be the next option to improve the efficiency of
searching large lists.

--
Vladimir Botka
Reply all
Reply to author
Forward
0 new messages