Ansible uses a so-called “inventory” to determine the list of nodes and
groups of nodes it can use. This inventory file defaults to
and typically looks something like this in INI file format:
The above example defines two groups (devservers and dbservers) each with the
specified host names, which need to be resolvable from the Ansible management
system. If you cater for special configurations (e.g. Vagrant boxes on your workstation,
or something behind a jump-host) you can use the
ansible_ssh_* variables to
define particular addresses and/or port numbers to use.
If you prefer to separate out, say, “production” and “development” systems, you
can also have two distinct inventory files which you pass to
ansible-playbook with the
-i switch, or by setting
$ANSIBLE_HOSTS to point
to the respective file.
A less known fact is that the inventory can also be read from a program. Say you already have a configuration management database (CMDB) and wish to use that for driving Ansible, it’s pretty easy to do. While you can, for example, periodically dump that database into a “hosts” file for Ansible, you can also have Ansible query your database on the fly.
I accomplish this by setting
$ANSIBLE_HOSTS to the full pathname of the executable
program which will provide the inventory.
A small example
As a small example, consider the following SQLite table with the three columns id, type, and name:
I want to massage the type column into a group for Ansible, whereby NULL types will be placed into a group with the exciting name “ungrouped”.
Let’s see some results.
The group name “dbserver” has been expanded and Ansible shows me the names of the two hosts it contains.
Ansible invokes the inventory script at least twice: once to find all groups
and the hosts they contains, and once for each host. In other words, when
Ansible starts doing something to the “dbserver” group, our
will be invoked like this:
Our little program produces this JSON output from above database, when invoked
inv.py program is simple enough:
As alluded to in the comments, I can create variables which Ansible will use in, say, templates. I could obtain these from our CMDB, pull them from files, etc. I could easily also create special groups by injecting appropriate JSON. For example, a customer of mine wanted groups defined based on the kind of hardware and its location; a few lines of Python did the trick.
Note, that due to the inventory program being invoked frequently, it will impose an additional load on your CMDB. (There is talk of modifying Ansible to not have that done, but it’s a work in progress.)
If necessary, you could employ some form of caching such as the ec2 inventory script uses.
Dynamic inventory and more vars
There are loads of places from which Ansible reads variables if you want them, and using inventory scripts, such as shown above, adds yet another source.
In addition to whichever variables my inventory script produces, Ansible
will also populate
group_vars from the respective directories
if these are placed in the directory containing my
inv.py. For example:
Mixing static and dynamic
In addition to inventory scripts, I can set
$ANSIBLE_HOSTS to point to a directory.
In this case, Ansible runs any executable files it finds therein and merges
static inventory files (in INI file format) it finds into their output.
You’ll notice there are more nodes shown than in the first JSON output above (
manager, for example) – these come from additional inventory files in