Ansible: Dynamic Inventory

I know that Ansible could use as inventory virtually anything, including scripts. However, all inventories on my day job are static, and we keep them in a source repository, and until now, I haven't had a chance to create or use one.

As any developer, I have checked the Stack Exchange before looking into Ansible documentation where I  find a boiled-down solution. There are a few ground rules for scripting dynamic directories:

  • Script should accept at least two arguments:
    • --list - return all hosts as a response
    • --host <hostname> - return a singe host
  • The script result is valid invnetory JSON data

Lets combain all we have learned and create a simple dynamic inventory script with two groups, one static and one dynamic.  

#!/bin/sh
set +x
if [ "$1" == "--list" ]; then
 echo -e '{ "static_group": {\n\t"hosts": [ "localhost"]},'
 echo -e ' "dynamic_group": {\n\t"hosts": ['
 # Calcualte second group member
 coin=$(( $RANDOM % 2 ))
 if [ $coin -ge 1 ]; then
  echo -e '"localhost"]},'
 else
  echo -e ']},'
 fi
 echo -e '"_meta": {"hostvars": {}}\n}'

elif [ "$1" == "--host" ]; then
  echo '{"_meta": {"hostvars": { }}}'
else
 echo "{ }"
fi
Dynamic repository script randomgroup.sh 

Script accepts required parameters and returns group and hstnames only for the --list argument, otherwise it returns an empty (almost) JSON object. To demonstrate the dynamic nature of the script I use special environment variable $RANDOM. For odd number script returns a list ["localhost] and empty list for even numbers. On the screenshot below, you may see a different set of targets for the same command.

Hosts list with the dynamic inventory

Athough, this code is merely a demonstration of capabilities, some advanced version could be useful fo automated collection or module tests.

Sample code and playbook are published on the site Github project.