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.

Screenshot demostrates ansible=playbook --list-hosts execution results. Te first try has hosts only in the static group, the second try shows hosts in all groups.
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.