Loop over vars not working

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 \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 \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
}

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] }}"

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.

Those were correcting your syntax, but that aside, the module has a
bug (always the case if you see MODULE_FAILURE).

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:

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.