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.
Regards,
Nehal Patel
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
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
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...
@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.
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'
...
Red Hat
Learning Community
A collaborative learning environment, enabling open source skill development.