At $WORK the other day somebody asked me for a bit of assistance with a rather basic shell script: he was trying to sudo into a number of remote systems, do something on those machines, gather output of that something, and bring it all back to a central location for further processing. He got it going (I think), and I left it at that.
Back at my desk I thought it would be neat to have something like Func, but $WORK doesn’t have that: they use Ansible, and then it hit me, and I slapped my face: Ansible does that too. This can easily be done with the API provided by Ansible which, among other things, allows me to control nodes, run Ansible modules, and obtain any output they produce. For example, I could
- obtain a list of zones on my authoritative servers (irrespective of their brands) and compare the list for completeness
- check and possibly clean up e-mail queues of misbehaving mail servers and report back how many messages where deleted on each / in total
- find out if there are ‘root’ users logged on somewhere, etc., etc.
As a small example, let’s go out and determine how much free disk space we have on our nodes. (We might have this information in, say, Nagios or Icinga, but it could be a mite difficult to get at the raw data.)
We could do something like this, grab the output and massage that, but it’ll get messy at some point.
Obtaining the information in a more structured way seems useful, so here is my-df, a small Python program which lists mount points and available space in kilobytes. In a few moments I’ll be calling this program, unmodified, a “module”. :-)
When I run that on the same machine, I see the following output:
Let me now apply a bit of Ansible power to obtain results from a number of systems in my “data center” (cough).
disks.py is a Python program which invokes Ansible’s
Runner method, the low-level machinery which is used by
/usr/bin/ansible-playbook. Documentation for
Runner is in the source, which you’ll find in the file
When this program runs, Ansible’s Runner will copy the specified module
my-df from the management machine to the nodes we query, will execute that there and report the results back.
my-df lives in Ansible’s library, which can mean either in the default library path or simply in a directory called
library/ in my program’s directory.
Looking at the
response from the Runner we see the following data structure (truncated for brevity).
The rest of the program just “does something” with the data. In this case, I just print it to stdout:
I can use any Ansible module with the Runner. Say, for example, I use the command module to obtain a list of files in
/tmp/, the resulting data structure returned by Runner contains stdout (and stderr) from which I’d have to split the newline-terminated lines.
This is the reason I produced JSON in my-df – it makes things a bit easier later on.
With Ansible in my environment, I can quite easily leverage its functionality into my own programs.