Hello,
I’m fairly new to Ansible and trying to do something very simple. I want to collect a piece of information (version number) from a number a network devices and generate a simple report.
- name: Get Data from devices
gather_facts: False
hosts: all
connection: local
roles:
tasks:
- name: Netconf test
wait_for: host={{ inventory_hostname }} port=830 timeout=5
Do a quick test to gather facts
-
name: Getting Facts
junos_get_facts: host={{ inventory_hostname }} logfile=tmp.log user=me passwd=passwd123
register: data
-
name: Save version data to jinja2 template
template: src=junos_version_report.j2 dest=./ver_report.txt
Here is the j2 file:
Device Serial Number Version
{% for i in play_hosts %}
{{ i }} {{ data.facts.serialnumber }}
{% endfor %}
The problem is when the report is written to the file, the information in the “data” variable is only from the last device that set it… As you can see, the Serial number is reported as being identical for each device ( which it is not…)
Device Serial Number Version
dev1 77633B97ACF0
dev2 77633B97ACF0
dev3 77633B97ACF0
I’ve seen an example like this with the hostvars variable but how do I define my own variable to be an array like hostvars so I can then reference each object in the array. For example:
{{ data[i].facts.serialnumber }}
Or open to other ideas?
Thanks
Al
Change the line to this.
{{ i }} {{ hostvars[i].data.facts.serialnumber }}
hostvars[i] works because that is predefined variable in ansible. However “data” is not. I tried data[i].facts.serialnumber but I get an error back thats says data is undefined.
Thx
Did you try my suggestion? You syntax is wrong, thats why I wrote what I wrote.
"data" exist since you used "register: data" on the task before called "Netconf test".
That was it Kia… Thank you. I should have looked at your response more closely. I missed that you had “data” as a child of hostvars. So is that true in all cases any time you define a register variable? That variable will be a child within hostvars?
Thank you again.
{{ hostvars[i].data.facts.serialnumber }}
Any recommendations for problem related to this solution. If connectivity to any one devices fails, then the registered variable (data) is not accessible for any of the other devices that actually passed. This results on the following error when the jinja2 template part of the playbook is executed. I understand the data variable not being available for the device that failed but why isn’t available for the other 3 devices that collected the data with no problems??
Thx
fatal: [device1]: FAILED! => {“changed”: false, “failed”: true, “msg”: “AnsibleUndefinedVariable: ‘dict object’ has no attribute ‘facts’”}
fatal: [device2]: FAILED! => {“changed”: false, “failed”: true, “msg”: “AnsibleUndefinedVariable: ‘dict object’ has no attribute ‘facts’”}
fatal: [device3]: FAILED! => {“changed”: false, “failed”: true, “msg”: “AnsibleUndefinedVariable: ‘dict object’ has no attribute ‘facts’”}
Ok, I got around this issue by editing the jinja template file to make sure the variable existed before referencing it… Then everything fell into place. The error message was throwing me off a bit as it was saying the variable did not exist even for the devices that passed. Anyhow, this is what I added to jinja template…
{%if hostvars[i].data.facts is defined %}
{{ “%-15s”|format(i) }} {{ “%-15s”|format(hostvars[i].data.facts.serialnumber) }} {{ “%-s”|format(hostvars[i].data.facts.version) }}
{% else %}
{{ “%-15s”|format(i) }} {{ “%-15s”|format(‘–’) }} {{ “%-s”|format(‘–’) }}
{% endif %}
Thanks
Al