Wildcards in ansible_facts

Hello,

I’m attempting to loop over numerous network interfaces and send them to our NetBox instance. Unfortunately, due to the disparate types of servers and network interfaces that are provided, I would like to be able to use wildcards to loop over all interfaces of certain types. So far I have attempted the following:

    - name: Write interfaces and addresses
      include_tasks:
        file: interfaces.yml
      loop:
        - "{{ ansible_facts['ansible_eth*'] }}"
        - "{{ ansible_facts['ansible_'+eno*] }}"
        - "{{ ansible_facts['ansible_'+enp24s0f*] }}"

Unsurprisingly, ansible isn’t happy when I tried to do so:

TASK [Write interfaces and addresses] ********************************************************************************************
fatal: [<hostname>]: FAILED! => {"msg": "'dict object' has no attribute 'ansible_eth*'. 'dict object' has no attribute 'ansible_eth*'"}

I’m looking for guidance on how to best iterate over the interfaces. Any advice is greatly appreciated. If it’s relevant, ansible version info is below:

ansible [core 2.16.6]
  config file = /home/user/project-hpc-netbox-migration/ansible.cfg
  configured module search path = ['/home/user/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /opt/rci/miniconda3/envs/ansible/lib/python3.12/site-packages/ansible
  ansible collection location = /home/user/.ansible/collections:/usr/share/ansible/collections
  executable location = /opt/rci/miniconda3/envs/ansible/bin/ansible
  python version = 3.12.3 | packaged by Anaconda, Inc. | (main, May  6 2024, 19:46:43) [GCC 11.2.0] (/opt/rci/miniconda3/envs/ansible/bin/python)
  jinja version = 3.1.4
  libyaml = True

Hii

| sam_karateman
September 4 |

  • | - |

Hello,

I’m attempting to loop over numerous network interfaces and send them to our NetBox instance. Unfortunately, due to the disparate types of servers and network interfaces that are provided, I would like to be able to use wildcards to loop over all interfaces of certain types. So far I have attempted the following:

    - name: Write interfaces and addresses
      include_tasks:
        file: interfaces.yml
      loop:
        - "{{ ansible_facts['ansible_eth*'] }}"
        - "{{ ansible_facts['ansible_'+eno*] }}"
        - "{{ ansible_facts['ansible_'+enp24s0f*] }}"

Unsurprisingly, ansible isn’t happy when I tried to do so:

TASK [Write interfaces and addresses] ********************************************************************************************
fatal: [<hostname>]: FAILED! => {"msg": "'dict object' has no attribute 'ansible_eth*'. 'dict object' has no attribute 'ansible_eth*'"}

I’m looking for guidance on how to best iterate over the interfaces. Any advice is greatly appreciated.

Try looping over this:

loop: “{{ ansible_facts.interfaces | select(‘search’, ‘(eth|eno|enp24s0f)\d+’) }}”

That is a regex there, you may have to tweak it a bit further for your situation.

Dick

3 Likes

As a best practice you first filter facts using set_fact module using filters and iterate over the that variable or list of facts. loop matching the exact attribute name from facts.

ansible.builtin.set_fact:
my_loop_facts: “{{ ansible_facts[‘interfaces’] | select(‘search’, ‘^eth|^eno|^enp24s0f’) | list }}”

and then iterate over my_loop_facts variable.
loop:
my_loop_facts

-Mayur

I was able to get it working for the lookup based on the replies, but I’m having trouble referencing the variable from within ansible_facts. I would like to do something like this:

  when:
    - ansible_facts[\"{{ item }}\"][active] is true

but I’m not sure of what the correct syntax would be for referencing a variable from within the ansible_facts variable. Would anybody have a recommendation?