Inventory Hostnames and Docker dynamic inventory

I was thinking of creating an issue & submitting a PR to address a core issue with the docker dynamic inventory script (ansible/contrib/inventory/docker.py). In its current state, it adds one or more docker hosts to the inventory, and any of the containers on those docker hosts. It also adds a group for each of the same, such that:

  • The inventory_hostnames and the corresponding group name for each docker hosts is set to the URI used to connect to the Docker API, which results in Ansible inventory hosts with names like unix:///var/run/docker.sock or https://127.0.0.1:2376.
  • Similarly, for containers, among the groups automatically created for each is one which takes the format image_[*repository*/]<*image*>[:*tag*], which results in groups like image_milo/centos:7

This causes a couple of problems.

  1. Managing host_vars and group_vars for these hosts becomes very painful due to filesystem file naming restrictions, which generally do not permit filenames containing a /. As a consequence, host_vars and group_vars need to be set in the host file, instead of managed through per host/group files and/or directories.
  2. As is likely often the case, if one of the docker hosts is running locally on the Ansible host, and localhost is listed in the inventory, plays targeting all, for example, will be run twice on the Ansible host (i.e. once against localhost and again against unix:///var/run/docker.sock). This could raise problems, and it also highlights again the issue it creates with host_vars and group_vars management, since you’d need to ensure common variables are set in the hosts file. This problem also arises if one of the inventory hosts is also one of the docker hosts (e.g. foo.example.com and https://foo.example.com:2376)
  3. As of v.2.4.0 (I think), Ansible emits a warning for all of the dynamically added docker hosts & containers, for example: [WARNING]: Found both group and host with same name: unix:///var/run/docker.sock

In addition to these issues, I think semantically it doesn’t make sense for the URI scheme (https://, unix://) to be part of the inventory_hostname in Ansible, since Ansible is ostensibly for managing hosts, where a unique host should generally be addressable under a single DNS hostname or IP address (I think there are some exceptions but not sure this needs to be one). Nor does it make sense for the docker API port to be part of the inventory hostname, which may be confused for a non-standard ssh port.

Thoughts?

Also, is there documentation/guidance somewhere which clearly defines what constitutes valid inventory_hostnames and group names, or possibly a dynamic inventory test script to verify that dynamic inventory scripts are not violating any such naming rules/conventions?

After digging into this a little more, I’ve noticed this problem is even more pronounced when defining Ansible hosts files in the standard/typical INI format. I hadn’t noticed before, since I use the YAML format, but in the INI format, it is not even possible to configure the dynamically added Docker groups, since colons (and perhaps forward slashes?) are not legal characters for section (group) names. For example, there’s no way to do the following (as far as I can tell):

[unix://var/run/docker.sock:vars] ansible_connection=docker

At any rate, I think we need to define clearly what characters can/should be used in inventory_hostname and group names, so that they do not create issues in either YAML or INI and play nicely with Ansible patterns. Secondly, we need to decide what the best implementation of the Docker dynamic inventory script looks like. I’m happy to take a cut at the first implementation, but I’d like to get everyone else’s thoughts and feedback to make sure the core use cases are covered. Notionally, I like the idea behind creating an Ansible node for each Docker host and a corresponding group containing all of that host’s containers, but naming the group and the docker host identically is confusing and could lead to subtle issues.

I also imagine some of these naming concerns are also present for Ansible chroot hosts - anyone with experience in that area and know of any good lessons we can take from there?

As part of the inventory revamp effort in 2.4
(https://github.com/ansible/ansible/pull/23001) I was going to create
a new docker plugin (among others), as proof of concept.

The new plugin system will allow for very simple plugins to pull data
from external sources and allow complex processing afterwards (example
https://gist.github.com/bcoca/13045ca3f54f42dd4173c99b9cbbb4ae), in
case you want to take a stab at this instead of redeveloping the
inventory script.