The first module Ansible implicitly runs on a playbook is the
setup module, which gathers “facts” about the system (unless you’ve disabled
that with the brand-new gather_facts: False
option in the playbook). We can gather our
own facts by writing modules we invoke explicitly in playbooks.
- We write the module in any language we want: the sole prerequisite is that the module output JSON. (Recall that the module is invoked on the managed node, so the node must have any language-specific modules your module requires installed.)
- Copy the module to the
$ANSIBLE_LIBRARY
directory on the Ansible manager (or onto each node when using Ansible in pull-mode). - Add an invocation of our module to our playbooks.
A fact-gathering module really can be written as trivially as something like this:
#!/bin/sh
COUNT=`who | wc -l`
cat <<EOF
{
"ansible_facts" : {
"users_logged_in" : $COUNT
}
}
EOF
The example I’m going to show you contains everything I consider important to know about the subject.
It reports facts about the target node:
- Number of files in
/tmp
and a constant. - Reads “contact” information from a file /etc/sysinfo which exists on all nodes. (I provision that file at system installation-time with, say, contact information, what the box is for, etc.)
- The Kerberos keytab name (configurable) and the principals contained therein. (If you’re “into” Kerberos, you may be interested to read how I automatically deploy Kerberos keytabs.)
The JSON string returned by our module looks like this. The ansible_facts
key
is important, as it triggers Ansible to use the values as facts:
{
"ansible_facts": {
"kerberos_keytab_princs": [
"host/a1.ww.mens.de@MENS.DE",
"service/wallet@MENS.DE"
],
"keytab": "/etc/krb5.keytab",
"sysinfo": {
"syscontact": "Jane Jolie",
"sysemail": "janej@example.com"
},
"tmpfiles": 21,
"year": 2006
}
}
Facts returned by our localsetup module are available to all statements in the playbook just after it’s invoked, so I call it first (well, after setup has been invoked automatically):
---
- hosts: 127.0.0.1
tasks:
- name: Gather our facts
action: localsetup keytab=/etc/krb5.keytab
- name: Demotemplate
action: template src=info.in dest=/tmp/info.txt
If I want to split fact-gathering out into more than one module, I can do that as well, invoking them all in my playbook.
The next action uses the template module with the following template:
{% if sysinfo.syscontact is defined -%}
The manager hereabouts is {{ sysinfo.syscontact }} <{{sysinfo.sysemail}}>
{% endif -%}
Currently {{tmpfiles}} files in /tmp
Kerberos information for {{ ansible_fqdn }}:
keytab name: {{ keytab }}
principals:
{% for p in kerberos_keytab_princs -%}
-> {{ p }}
{% endfor -%}
and it produces the following output on the machine I ran it against:
The manager hereabouts is Jane Jolie <janej@example.com>
Currently 23 files in /tmp
Kerberos information for a1.ww.mens.de:
keytab name: /etc/krb5.keytab
principals:
-> host/a1.ww.mens.de@MENS.DE
-> service/wallet@MENS.DE
I’ve put the module’s source-code and all supporting files on Github for you.
See also: A very welcome addition to Ansible’s setup module.