diff options
author | Kelley Spoon <kelley.spoon@linaro.org> | 2018-02-21 19:11:34 -0600 |
---|---|---|
committer | Kelley Spoon <kelley.spoon@linaro.org> | 2018-02-28 15:24:28 +0000 |
commit | 52061c6d3fbd59df13e88f310846fef314e8cfac (patch) | |
tree | 92e88fca1427a43952f0ef25c645797a6bec89c7 | |
parent | c9f023127cb7b310cedc1ce1fb9200d86da10f66 (diff) |
Docker: Add a dynamic inventory of docker hosts script
This change adds the docker_hosts script that will build an
inventory file from running docker containers.
See the script comments for information on requirments,
usage, and an example.
Change-Id: I80478db3d691d34fc00ee201318e38014bbf726f
Reviewed-on: https://review.linaro.org/23990
Reviewed-by: Benjamin Copeland <ben.copeland@linaro.org>
-rwxr-xr-x | docker_hosts | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/docker_hosts b/docker_hosts new file mode 100755 index 00000000..6f78ac6f --- /dev/null +++ b/docker_hosts @@ -0,0 +1,109 @@ +#!/usr/bin/env python + +import docker +import re +import json +import sys + +""" + Ansible Docker Dynamic Inventory Script + +External components: + https://git.linaro.org/infrastructure/docker-ansible-baseimage.git/ + +Requirements: + pip install docker + chmod 755 docker_hosts + +Example: + + docker-compose -f linaro_dev up -d + docker run -d \ + -e ANSIBLE_GROUP=gerrit \ + -e ANSIBLE_HOST=review.linaro.org \ + -e ALIAS=review.linaro.org \ + --name review ansible/baseimage:14.04 + ansible-playbook -u root -v -i docker_hosts \ + -c local -l review.linaro.org gerrit.yml + +Options: + +ANSIBLE_HOST overrides the container's name in the inventory + Let's you use the host_vars for a real server for testing. +ANSIBLE_GROUP is a comma separated list of groups that the host + should belong to. +ALIAS is a feature of the linaro/devdns container that replaces the + local DNS entry for the target with the container's IP address + +""" + +class DockerInventory(): + client = None + ip_table = {} + hosts = {} + groups = {} + + def __init__(self): + self.client = docker.from_env() + + # build ip lookup table + for network_entry in self.client.networks.list(): + network = self.client.networks.get( network_entry.name ) + for entry in network.attrs["Containers"]: + ip = network.attrs["Containers"][entry]["IPv4Address"] + name = network.attrs["Containers"][entry]["Name"] + self.ip_table[ name ] = re.sub( u"/\d+$", '', ip) + + # build up all inventory + for container in self.client.containers.list(): + + # if ANSIBLE_HOST is set, use that instead of the container.name + # We should only add hosts that have an ANSIBLE_HOST set + #TODO: find a way to set other hostvars + hostname = container.name + for env_var in container.attrs["Config"]["Env"]: + found_ansible = re.match( 'ANSIBLE_HOST=(?P<ansible_host>.*)', env_var ) + if found_ansible: + hostname = found_ansible.group("ansible_host") + self.hosts[hostname] = { "ansible_host": self.ip_table[container.name] } + + # add in any groups listed in ANSIBLE_GROUP and make this + # container a member + for env_var in container.attrs["Config"]["Env"]: + found_ansible = re.match( 'ANSIBLE_GROUP=(?P<ansible_group>.*)', env_var ) + + if found_ansible: + groups = found_ansible.group("ansible_group") + for group in groups.split(','): + if not self.groups.has_key( group ): + self.groups[group] = [] + self.groups[group].append( hostname ) + #TODO: find a way to add in groupvars + + def build_meta(self): + meta = {'_meta': { 'hostvars' : {} } } + + for key in self.hosts.keys(): + meta['_meta']['hostvars'][key] = self.hosts[key] + + return meta + + def list(self): + full = self.groups + full["_meta"] = self.build_meta()["_meta"] + return json.dumps( full ) + + def host(self, hostname): + try: + return json.dumps( self.hosts[hostname] ) + except IndexError as e: + return json.dumps( {} ) + +if __name__ == '__main__': + + inventory = DockerInventory() + + if len( sys.argv ) <= 2: + print inventory.list() + elif len(sys.argv ) >= 3: + print inventory.host( sys.argv[2] ) |