diff --git a/library/cloud/docker b/library/cloud/docker index e1a9b27f61c..dbfb4bed8f6 100644 --- a/library/cloud/docker +++ b/library/cloud/docker @@ -213,6 +213,13 @@ def _human_to_bytes(number): def _ansible_facts(container_list): return {"docker_containers": container_list} +def _docker_id_quirk(inspect): + # XXX: some quirk in docker + if 'ID' in inspect: + inspect['Id'] = inspect['ID'] + del inspect['ID'] + return inspect + class DockerManager: counters = {'created':0, 'started':0, 'stopped':0, 'killed':0, 'removed':0, 'restarted':0, 'pull':0} @@ -220,10 +227,46 @@ class DockerManager: def __init__(self, module): self.module = module + self.binds = None + self.volumes = None + if self.module.params.get('volumes'): + self.binds = {} + self.volumes = {} + vols = self.module.params.get('volumes').split(" ") + for vol in vols: + parts = vol.split(":") + # host mount (e.g. /mnt:/tmp, bind mounts host's /tmp to /mnt in the container) + if len(parts) == 2: + self.volumes[parts[1]] = {} + self.binds[parts[0]] = parts[1] + # docker mount (e.g. /www, mounts a docker volume /www on the container at the same location) + else: + self.volumes[parts[0]] = {} + + self.lxc_conf = None + if self.module.params.get('lxc_conf'): + self.lxc_conf = [] + options = self.module.params.get('lxc_conf').split(" ") + for option in options: + parts = option.split(':') + self.lxc_conf.append({"Key": parts[0], "Value": parts[1]}) + + self.ports = None + if self.module.params.get('ports'): + self.ports = self.module.params.get('ports').split(",") + # connect to docker server docker_url = urlparse(module.params.get('docker_url')) self.client = docker.Client(base_url=docker_url.geturl()) + + def get_split_image_tag(self, image): + tag = None + if image.find(':') > 0: + return image.split(':') + else: + return image, tag + def get_summary_counters_msg(self): msg = "" for k, v in self.counters.iteritems(): @@ -240,21 +283,36 @@ class DockerManager: return True return False + + def get_inspect_containers(self, containers): + inspect = [] + for i in containers: + details = self.client.inspect_container(i['Id']) + details = _docker_id_quirk(details) + inspect.append(details) + + return inspect def get_deployed_containers(self): # determine which images/commands are running already containers = self.client.containers() image = self.module.params.get('image') command = self.module.params.get('command') + if command: + command = command.strip() deployed = [] + # if we weren't given a tag with the image, we need to only compare on the image name, as that + # docker will give us back the full image name including a tag in the container list if one exists. + image, tag = self.get_split_image_tag(image) + for i in containers: - if i["Image"].split(":")[0] == image.split(":")[0] and (not command or i["Command"].strip() == command.strip()): + running_image, running_tag = self.get_split_image_tag(image) + running_command = i['Command'].strip() + + if running_image == image and (not tag or tag == running_tag) and (not command or running_command == command): details = self.client.inspect_container(i['Id']) - # XXX: some quirk in docker - if 'ID' in details: - details['Id'] = details['ID'] - del details['ID'] + details = _docker_id_quirk(details) deployed.append(details) return deployed @@ -262,7 +320,7 @@ class DockerManager: def get_running_containers(self): running = [] for i in self.get_deployed_containers(): - if i['State']['Running'] == True: + if i['State']['Running'] == True and i['State']['Ghost'] == False: running.append(i) return running @@ -270,6 +328,8 @@ class DockerManager: def create_containers(self, count=1): params = {'image': self.module.params.get('image'), 'command': self.module.params.get('command'), + 'ports': self.ports, + 'volumes': self.volumes, 'volumes_from': self.module.params.get('volumes_from'), 'mem_limit': _human_to_bytes(self.module.params.get('memory_limit')), 'environment': self.module.params.get('env'), @@ -279,9 +339,6 @@ class DockerManager: 'privileged': self.module.params.get('privileged'), } - if self.module.params.get('ports'): - params['ports'] = self.module.params.get('ports').split(",") - def do_create(count, params): results = [] for _ in range(count): @@ -301,24 +358,8 @@ class DockerManager: return containers def start_containers(self, containers): - binds = None - if self.module.params.get('volumes'): - binds = {} - vols = self.module.params.get('volumes').split(" ") - for vol in vols: - parts = vol.split(":") - binds[parts[0]] = parts[1] - - lxc_conf = None - if self.module.params.get('lxc_conf'): - lxc_conf = [] - options = self.module.params.get('lxc_conf').split(" ") - for option in options: - parts = option.split(':') - lxc_conf.append({"Key": parts[0], "Value": parts[1]}) - for i in containers: - self.client.start(i['Id'], lxc_conf=lxc_conf, binds=binds) + self.client.start(i['Id'], lxc_conf=self.lxc_conf, binds=self.binds) self.increment_counter('started') def stop_containers(self, containers): @@ -387,7 +428,7 @@ def main(): # start/stop containers if state == "present": - + # start more containers if we don't have enough if delta > 0: containers = manager.create_containers(delta) @@ -395,15 +436,15 @@ def main(): # stop containers if we have too many elif delta < 0: - manager.stop_containers(running_containers[0:abs(delta)]) - manager.remove_containers(running_containers[0:abs(delta)]) - + containers = manager.stop_containers(running_containers[0:abs(delta)]) + manager.remove_containers(containers) + facts = manager.get_running_containers() # stop and remove containers elif state == "absent": facts = manager.stop_containers(deployed_containers) - manager.remove_containers(containers) + manager.remove_containers(deployed_containers) # stop containers elif state == "stopped": @@ -415,8 +456,9 @@ def main(): # restart containers elif state == "restarted": - manager.restart_containers(running_containers) - + manager.restart_containers(running_containers) + facts = manager.get_inspect_containers(running_containers) + msg = "%s container(s) running image %s with command %s" % \ (manager.get_summary_counters_msg(), module.params.get('image'), module.params.get('command')) changed = manager.has_changed()