cancel
Showing results for 
Search instead for 
Did you mean: 
Nehal
Cadet
Cadet
  • 29.1K Views

Ansible hostvars with jinja2 template

Jump to solution

Hello!

Can anyone confirm there is bug with "template" module if we use jinja2 template along with hostvars?

I check / search the post related to it but no one is able to clearcut provide solution.

The following simple code of jinja2 template is not able to generate ip address of all host on all host.

{% for host in groups['all'] %}
{{ hostvars['host']['ansible_facts']['default_ipv4']['address'] }}
{% endfor %}

my ansible version is 2.8

Additional details regarding my playbook files and other files.

image (3).pngimage (2).pngimage (1).png

Regards,

Nehal Patel

Labels (1)
15 Replies
McLinux
Cadet
Cadet
  • 2,669 Views

I tried the first thing you posted and it worked for me. node1 is CentOS8 and node5 is RHEL9:

---
- name: get ip-adresses from all hosts
  hosts: all
  tasks:
  - name: get ipaddresses
    template:
      src: host.j2
      dest: myhosts

host.j2:

{% for host in groups['all'] %}
{{ hostvars[host]['ansible_facts']['default_ipv4']['address'] }}
{% endfor %

PLAY [get ip-adresses from all hosts] ******************************************************************************************************************************************

TASK [Gathering Facts] *********************************************************************************************************************************************************
[DEPRECATION WARNING]: Distribution rhel 9.0 on host node5.example.com should use /usr/libexec/platform-python, but is using /usr/bin/python for backward compatibility with
prior Ansible releases. A future Ansible release will default to using the discovered platform python for this host. See
https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information. This feature will be removed in version 2.12. Deprecation warnings
can be disabled by setting deprecation_warnings=False in ansible.cfg.
ok: [node5.example.com]
ok: [node1.example.com]

TASK [get ipaddresses] *********************************************************************************************************************************************************
changed: [node1.example.com]
changed: [node5.example.com]

PLAY RECAP *********************************************************************************************************************************************************************
node1.example.com : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node5.example.com : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

 

 

ddnehalp
Cadet
Cadet
  • 2,645 Views

Hello!

 

Yes. This problem is resolved. you have removed single quotes from host at host.j2. and as describe by Yasirsharif(in this thread)  we need to apply when statement for selected group.

Thanks

  • 1,872 Views

The above post of Tech_Hub_YT works like a charm! I did however manage to still get the hideous `'dict object' has no attribute 'default_ipv4'`!!!

The thing is you'll have to remember to keep all of your hosts in the play! If you'd deploy the above template, but you only need it deployed on `node1` so you add `-l node1` to your `ansible-playbook` command, then it'll still try to loop over all the hosts in the `hosts:` setting, but it will only gather facts about `node1`! And you'll receive the above-mentioned problem...

 

Hope I could save somebodies half an hour debugging...

bonnevil
Starfighter Starfighter
Starfighter
  • 1,866 Views

@geertGeurts  The ansible_facts['default_ipv4'] fact does not exist if you do not have a default route on the system. The fact points at the info for whatever interface is on the network with the default gateway.  That might be why you're getting that dict object error from ansible_facts.

  • 1,856 Views
Thanks for the info, but the facts first need to be collected from I
guess...
0 Kudos
  • 8,610 Views

I agree with everyone that you need to remove the single quotes from host:

{% for host in groups['all'] %}
{{ hostvars[host]['ansible_facts']['default_ipv4']['address'] }}
{% endfor %}

Most importantly, in your playbook you identified 'hosts: webservers'

All you need to make it 'hosts: all' instead and then apply a 'when' statement to perform the task to webservers only like this:

---
- name: create myhost
hosts: all
tasks:
- name: create /etc/myhost
template:
src: myhost.j2
dest: /etc/myhost
when: '"webservers" in group_names'
...

 

Tags (3)
Join the discussion
You must log in to join this conversation.