# Jinja+facts :: how to get active interface

**URL:** <https://forum.ansible.com/t/jinja-facts-how-to-get-active-interface/8746>\
**Category:** Get Help\
**Tags:** jinja2\
**Created:** [September 25, 2024, 4:57am UTC](https://forum.ansible.com/t/jinja-facts-how-to-get-active-interface/8746 "2024-09-25T04:57:30Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![adriansev](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/adriansev/32/4866_2.png) [@adriansev](https://forum.ansible.com/u/adriansev)\
**Post date:** [September 25, 2024, 4:57am UTC](https://forum.ansible.com/t/jinja-facts-how-to-get-active-interface/8746/1 "2024-09-25T04:57:30Z")

</div>

I’m trying to get in a configuration file the active interface from facts … but i’m still wrong somewhere in the jinja code or in facts accessing …  
My tryout looks like this:

```auto
# Network interface to monitor (default eth0)
{% set active_eth_list = [] %}
{% for iface in ansible_interfaces if iface != 'lo' %}
    {% set fact_eth_name = "ansible_" ~ iface %}
    {% if ansible_facts[fact_eth_name]['active'] %}
        {{ active_eth_list.append(iface) }}
    {% endif %}
{% endfor %}

EOS_FST_NETWORK_INTERFACE="{{ active_eth_list[0] }}"

```

And the error message is

```auto
The full traceback is:
Traceback (most recent call last):
  File "/home/adrian/.local/lib/python3.9/site-packages/ansible/template/ __init__.py", line 1015, in do_template
    res = myenv.concat(rf)
  File "/home/adrian/.local/lib/python3.9/site-packages/ansible/template/native_helpers.py", line 83, in ansible_concat
    return ''.join([to_text(v) for v in nodes])
  File "/home/adrian/.local/lib/python3.9/site-packages/ansible/template/native_helpers.py", line 83, in <listcomp>
    return ''.join([to_text(v) for v in nodes])
  File "<template>", line 33, in root
  File "/home/adrian/.local/lib/python3.9/site-packages/jinja2/runtime.py", line 857, in _fail_with_undefined_error
    raise self._undefined_exception(self._undefined_message)
jinja2.exceptions.UndefinedError: 'dict object' has no attribute 'ansible_eno1'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/adrian/.local/lib/python3.9/site-packages/ansible/plugins/action/template.py", line 152, in run
    resultant = templar.do_template(template_data, preserve_trailing_newlines=True, escape_backslashes=False, overrides=overrides)
  File "/home/adrian/.local/lib/python3.9/site-packages/ansible/template/ __init__.py", line 1049, in do_template
    raise AnsibleUndefinedVariable(e, orig_exc=e)
ansible.errors.AnsibleUndefinedVariable: 'dict object' has no attribute 'ansible_eno1'. 'dict object' has no attribute 'ansible_eno1'
fatal: [fst16.spacescience.ro]: FAILED! => {
    "changed": false
}

MSG:

AnsibleUndefinedVariable: 'dict object' has no attribute 'ansible_eno1'. 'dict object' has no attribute 'ansible_eno1'

```

So, the name of the fact key is correctly constructed and i can confirm looking in the redis store:

```auto
redis-cli get fst16.spacescience.ro | jq | grep ansible_eno1
  "ansible_eno1": {

```

but somehow the ansible\_facts does not have it …  
I do have `gather_facts: False` as the facts are already cached in redis and my expectation is that the cache facts are available to playbook as if they were freshly gathered…

So, does anyone have an idea where i’m wrong?  
Thanks a lot

---

<div class="post-metadata">

**Author:** ![bvitnik](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/bvitnik/32/4132_2.png) [@bvitnik](https://forum.ansible.com/u/bvitnik)\
**Post date:** [September 25, 2024, 10:46pm UTC](https://forum.ansible.com/t/jinja-facts-how-to-get-active-interface/8746/2 "2024-09-25T22:46:36Z")

</div>

When accessing ansible facts from `ansible_facts` dictionary, there is no `ansible_` prefix in key names. In other words its:

```auto
ansible_facts['eno1']

```

instead of

```auto
ansible_facts['ansible_eno1']

```

---

<div class="post-metadata">

**Author:** ![adriansev](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/adriansev/32/4866_2.png) [@adriansev](https://forum.ansible.com/u/adriansev)\
**Post date:** [September 26, 2024, 4:55am UTC](https://forum.ansible.com/t/jinja-facts-how-to-get-active-interface/8746/3 "2024-09-26T04:55:58Z")

</div>

actually i do have all `ansible_` prefixes in the facts (i did a separate dump to be sure), but the thing is that `ansible_facts` dictionary seems to not exists, i can only use directly the keys name (instead of `ansible_facts["ansible_default_ipv4"]["interface"]` i can only use directly `ansible_default_ipv4["interface"]`)  
so, if the key is a composed one (name deduced from something else) i see no method to actually access it … but i got what i need with the above example so that’s nice.

---

<div class="post-metadata">

**Author:** ![bvitnik](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/bvitnik/32/4132_2.png) [@bvitnik](https://forum.ansible.com/u/bvitnik)\
**Post date:** [September 26, 2024, 12:23pm UTC](https://forum.ansible.com/t/jinja-facts-how-to-get-active-interface/8746/4 "2024-09-26T12:23:32Z")

</div>

This error message:

```auto
jinja2.exceptions.UndefinedError: 'dict object' has no attribute 'ansible_eno1'

```

suggests that `ansible_facts` variable is defined (it exists) but attribute/key `ansible_eno1` does not exist in it which is expected. If `ansible_facts` did not exist, you would get some other type of error like “variable `ansible_facts` not found”.

How did you do a dump to check?

---

<div class="post-metadata">

**Author:** ![adriansev](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/adriansev/32/4866_2.png) [@adriansev](https://forum.ansible.com/u/adriansev)\
**Post date:** [September 28, 2024, 7:36am UTC](https://forum.ansible.com/t/jinja-facts-how-to-get-active-interface/8746/5 "2024-09-28T07:36:42Z")

</div>

So, there are 2 things:

1. checking:  
1.a Check the content of the redis key for host  
1.b do a dump with [this task](https://github.com/adriansev/ansible_iss/blob/master/playbooks/tasks/dump_vars.yml)

2. i succeeded to do what i needed by using directly the key (which, i think, should not be possible) with:  
`EOS_FST_NETWORK_INTERFACE="{{ ansible_default_ipv4["interface"] }}"`

moreover i have `fact_caching_prefix =` in ansible.cfg so it’s not a prefix added by me … ansible is 2.9 (the only one i can install on alma9 without a venv)

---

<div class="post-metadata">

**Author:** ![bvitnik](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/bvitnik/32/4132_2.png) [@bvitnik](https://forum.ansible.com/u/bvitnik)\
**Post date:** [September 28, 2024, 11:52pm UTC](https://forum.ansible.com/t/jinja-facts-how-to-get-active-interface/8746/6 "2024-09-28T23:52:05Z")

</div>

> [@adriansev](#):
>
> So, there are 2 things:
> 
> 1. checking:  
> 1.a Check the content of the redis key for host  
> 1.b do a dump with [this task](https://github.com/adriansev/ansible_iss/blob/master/playbooks/tasks/dump_vars.yml)

To get a better understanding of Ansible facts and `ansible_facts` dictionary, you should dump them like this:

```yaml
---
- hosts: all

  tasks:
  - name: "Dump ansible_facts"
    debug:
      msg: "{{ ansible_facts }}"

```

This is not the same as dumping `hostvars[inventory_hostname]` presented in your example.

> [@adriansev](#):
>
> 1. i succeeded to do what i needed by using directly the key (which, i think, should not be possible) with:  
> `EOS_FST_NETWORK_INTERFACE="{{ ansible_default_ipv4["interface"] }}"`
> 
> moreover i have `fact_caching_prefix =` in ansible.cfg so it’s not a prefix added by me … ansible is 2.9 (the only one i can install on alma9 without a venv)

Oh, it’s pretty much possible and intentional. In some early days of Ansible, all Ansible facts were only accessible by using an `ansible_` prefixed host variables. In other words by using, e.g:

```auto
{{ ansible_default_ipv4 }}

```

which is the same as:

```auto
{{ hostvars[inventory_hostname]['ansible_default_ipv4'] }}

```

Starting from Ansible 2.5, I believe, there was a decision to namespace all Ansible facts by putting them inside the `ansible_facts` variable of type dictionary. So the previously mentioned `ansible_default_ipv4` variable could also be accessed by using:

```auto
{{ ansible_facts['default_ipv4'] }}

```

Note the missing `ansible_` prefix for the dict key compared to the previous case.

To maintain backward compatibility, lots of community created role for example, both of these ways of accessing Ansible facts is supported and valid. On the other hand, there are some security concerns when using `{{ ansible_default_ipv4 }}` as compared to `{{ ansible_facts['default_ipv4'] }}` so there is a Ansible configuration option to disable usage of `{{ ansible_default_ipv4 }}` form:

[https://docs.ansible.com/ansible/latest/reference\_appendices/config.html#inject-facts-as-vars](https://docs.ansible.com/ansible/latest/reference_appendices/config.html#inject-facts-as-vars)

The default is `true` so both ways are supported.

The security concerns are described here:

[https://docs.ansible.com/ansible/devel/reference\_appendices/faq.html#argsplat-unsafe](https://docs.ansible.com/ansible/devel/reference_appendices/faq.html#argsplat-unsafe)

To summarize. There are two ways (three if you count `hostvars`) to get the value of some Ansible fact, old and new one. The old one uses `ansible_` prefix for all of the facts. The new one uses `ansible_facts` dictionary with key names that are not prefixed with `ansible_`.

---

<div class="post-metadata">

**Author:** ![adriansev](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/adriansev/32/4866_2.png) [@adriansev](https://forum.ansible.com/u/adriansev)\
**Post date:** [September 30, 2024, 9:29pm UTC](https://forum.ansible.com/t/jinja-facts-how-to-get-active-interface/8746/7 "2024-09-30T21:29:38Z")

</div>

Thanks a lot for the comprehensive info!!!  
As a small comment on `ansible_facts` : this should be what is cached in redis isn’t it? So, AFAIK i do not need to dump anything as i can just look into the host key in redis …

---

<div class="post-metadata">

**Author:** ![bvitnik](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/bvitnik/32/4132_2.png) [@bvitnik](https://forum.ansible.com/u/bvitnik)\
**Post date:** [September 30, 2024, 10:17pm UTC](https://forum.ansible.com/t/jinja-facts-how-to-get-active-interface/8746/8 "2024-09-30T22:17:59Z")

</div>

I’m not sure how fact caching works, particularly in combination with Redis. It’s possible that what you see in Redis is not 1:1 compared to `ansible_facts` dictionary variable. In other words it is a good idea to dump/inspect the content of `ansible_facts` variable to get a better understanding of what you can find inside and how the hierarchy looks like instead of looking inside Redis.

---

<div class="post-metadata">

**Author:** ![adriansev](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/adriansev/32/4866_2.png) [@adriansev](https://forum.ansible.com/u/adriansev)\
**Post date:** [October 10, 2024, 11:55am UTC](https://forum.ansible.com/t/jinja-facts-how-to-get-active-interface/8746/9 "2024-10-10T11:55:31Z")

</div>

so, sorry for the late answer … using the following tasks:

```auto
  tasks:
  - name: "Dump ansible_facts"
    debug:
      msg: "{{ ansible_facts | to_nice_json }}"

  - name: "Dump ansible_facts"
    delegate_to: localhost
    run_once: true
    copy:
        content: "{{ ansible_facts | to_nice_json }}"
        dest: "/home/adrian/ansible/{{ inventory_hostname }}-dump.json"

```

i could confirm that the output is identical to the redis content.  
Thanks a lot ! 🙂

L.E. actually i was too fast to write … i still have `ansible_` prefixes in redis output

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/ansible/original/1X/1882d9a01da5d8996a862359b0913cc568a39b84.svg) [@system](https://forum.ansible.com/u/system)\
**Post date:** [November 9, 2024, 11:55am UTC](https://forum.ansible.com/t/jinja-facts-how-to-get-active-interface/8746/10 "2024-11-09T11:55:34Z")

</div>

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.
