diff options
author | Chris Houseknecht <chouseknecht@ansible.com> | 2016-04-25 23:46:26 -0400 |
---|---|---|
committer | Chris Houseknecht <chouseknecht@ansible.com> | 2016-04-25 23:46:26 -0400 |
commit | b68114f838c00ed6d53c21527c6a86e3a2b6f63d (patch) | |
tree | 05749ecdede8c2232ab29869daa3f87d9898bff4 | |
parent | e6fb933c3c68552300f98f9b449087ddbf73e09f (diff) | |
parent | 1d2be970132bc314c1bdf90e55515dd05079d75c (diff) | |
download | ansible-modules-core-b68114f838c00ed6d53c21527c6a86e3a2b6f63d.tar.gz |
Merge pull request #3505 from chouseknecht/docker_image
Adding refactored docker_image module.
-rw-r--r-- | cloud/docker/docker_image.py | 835 |
1 files changed, 447 insertions, 388 deletions
diff --git a/cloud/docker/docker_image.py b/cloud/docker/docker_image.py index 12ba67de..2715eadd 100644 --- a/cloud/docker/docker_image.py +++ b/cloud/docker/docker_image.py @@ -1,457 +1,516 @@ #!/usr/bin/python # - -# (c) 2014, Pavel Antonov <antonov@adwz.ru> +# Copyright 2016 Red Hat | Ansible # # This file is part of Ansible # -# This module is free software: you can redistribute it and/or modify +# Ansible is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # -# This software is distributed in the hope that it will be useful, +# Ansible is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this software. If not, see <http://www.gnu.org/licenses/>. - -###################################################################### +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. DOCUMENTATION = ''' --- module: docker_image -author: "Pavel Antonov (@softzilla)" + +short_description: Manage docker images. + version_added: "1.5" -short_description: manage docker images + description: - - Create, check and remove docker images + - Build, load or pull an image, making the image available for creating containers. Also supports tagging an + image into a repository and archiving an image to a .tar file. + options: - path: + archive_path: description: - - Path to directory with Dockerfile + - Use with state 'present' to archive an image to a .tar file. required: false default: null - aliases: [] + version_added: "2.1" dockerfile: description: - - Dockerfile to use - required: false + - Use with state 'present' to provide an alternate name for the Dockerfile to use when building an image. default: Dockerfile version_added: "2.0" - name: + force: description: - - Image name to work with - required: true - default: null - aliases: [] - tag: - description: - - Image tag to work with - required: false - default: "latest" - aliases: [] - nocache: - description: - - Do not use cache with building - required: false + - Use with absent state to un-tag and remove all images matching the specified name. Use with states 'present' + and 'tagged' to take action even when an image already exists. default: false - aliases: [] - docker_url: + version_added: "2.1" + http_timeout: description: - - URL of docker host to issue commands to + - Timeout for HTTP requests during the image build operation. Provide a positive integer value for the number of + seconds. + default: null required: false - default: ${DOCKER_HOST} or unix://var/run/docker.sock - aliases: [] - use_tls: + version_added: "2.1" + name: description: - - Whether to use tls to connect to the docker server. "no" means not to - use tls (and ignore any other tls related parameters). "encrypt" means - to use tls to encrypt the connection to the server. "verify" means to - also verify that the server's certificate is valid for the server - (this both verifies the certificate against the CA and that the - certificate was issued for that host. If this is unspecified, tls will - only be used if one of the other tls options require it. - choices: [ "no", "encrypt", "verify" ] - version_added: "2.0" - tls_client_cert: + - "Image name. Name format will be one of: name, repository/name, registry_server:port/name. + When pushing or pulling an image the name can optionally include the tag by appending ':tag_name'." + required: true + path: description: - - Path to the PEM-encoded certificate used to authenticate docker client. - If specified tls_client_key must be valid - default: ${DOCKER_CERT_PATH}/cert.pem - version_added: "2.0" - tls_client_key: + - Use with state 'present' to build an image. Will be the path to a directory containing the context and + Dockerfile for building an image. + aliases: + - build_path + default: null + required: false + pull: description: - - Path to the PEM-encoded key used to authenticate docker client. If - specified tls_client_cert must be valid - default: ${DOCKER_CERT_PATH}/key.pem - version_added: "2.0" - tls_ca_cert: + - When building an image downloads any updates to the FROM image in Dockerfile. + default: true + version_added: "2.1" + rm: description: - - Path to a PEM-encoded certificate authority to secure the Docker connection. - This has no effect if use_tls is encrypt. - default: ${DOCKER_CERT_PATH}/ca.pem - version_added: "2.0" - tls_hostname: + - Remove intermediate containers after build. + default: true + version_added: "2.1" + nocache: description: - - A hostname to check matches what's supplied in the docker server's - certificate. If unspecified, the hostname is taken from the docker_url. - default: Taken from docker_url - version_added: "2.0" - docker_api_version: + - Do not use cache when building an image. + default: false + repository: description: - - Remote API version to use. This defaults to the current default as - specified by docker-py. - default: docker-py default remote API version - version_added: "2.0" + - Full path to a repository. Use with state 'present' to tag the image into the repository. + required: false + default: null + version_added: "2.1" state: description: - - Set the state of the image - required: false + - Make assertions about the state of an image. + - When 'absent' an image will be removed. Use the force option to un-tag and remove all images + matching the provided name. + - When 'present' check if an image exists using the provided name and tag. If the image is not found or the + force option is used, the image will either be pulled, built or loaded. By default the image will be pulled + from Docker Hub. To build the image, provide a path value set to a directory containing a context and + Dockerfile. To load an image, specify load_path to provide a path to an archive file. To tag an image to a + repository, provide a repository path. If the name contains a repository path, it will be pushed. + - "NOTE: 'build' is DEPRECATED. Specifying 'build' will behave the same as 'present'." default: present - choices: [ "present", "absent", "build" ] - aliases: [] - timeout: + choices: + - absent + - present + - build (DEPRECATED) + tag: description: - - Set image operation timeout - required: false - default: 600 - aliases: [] -requirements: - - "python >= 2.6" - - "docker-py" - - "requests" -''' - -EXAMPLES = ''' -Build docker image if required. Path should contains Dockerfile to build image: + - Used to select an image when pulling. Will be added to the image when pushing, tagging or building. Defaults to + 'latest' when pulling an image. + default: latest + use_tls: + description: + - "DEPRECATED. Whether to use tls to connect to the docker server. Set to 'no' when TLS will not be used. Set to + 'encrypt' to use TLS. And set to 'verify' to use TLS and verify that the server's certificate is valid for the + server. NOTE: If you specify this option, it will set the value of the tls or tls_verify parameters." + choices: + - no + - encrypt + - verify + default: no + version_added: "2.0" -- hosts: web - become: yes - tasks: - - name: check or build image - docker_image: path="/path/to/build/dir" name="my/app" state=present +extends_documentation_fragment: + - docker -Build new version of image: +requirements: + - "python >= 2.6" + - "docker-py >= 1.7.0" + - "Docker API >= 1.20" -- hosts: web - become: yes - tasks: - - name: check or build image - docker_image: path="/path/to/build/dir" name="my/app" state=build +authors: + - Pavel Antonov (@softzilla) + - Chris Houseknecht (@chouseknecht) + - James Tanner (@jctanner) -Remove image from local docker storage: +''' -- hosts: web - become: yes - tasks: - - name: remove image - docker_image: name="my/app" state=absent +EXAMPLES = ''' +- name: pull an image + docker_image: + name: pacur/centos-7 + +- name: Tag to repository to a private registry and push it + docker_image: + name: pacur/centos-7 + repository: registry.ansible.com/chouseknecht/centos_images + tag: 7.0 + +- name: Remove image + docker_image: + state: absent + name: registry.ansible.com/chouseknecht/sinatra + tag: v1 + +- name: Build an image ad push it to a private repo + docker_image: + path: ./sinatra + name: registry.ansible.com/chouseknecht/sinatra + tag: v1 + +- name: Archive image + docker_image: + name: registry.ansible.com/chouseknecht/sinatra + tag: v1 + archive_path: my_sinatra.tar + +- name: Load image from archive and push it to a private registry + docker_image: + name: registry.ansible.com/chouseknecht/sinatra + tag: v1 + load_path: my_sinatra.tar ''' -import re -import os -from urlparse import urlparse +RETURN = ''' +actions: + description: List of actions taken by the module. + returned: always + type: list + sample: [ + "Removed image myimage" + ] +image: + description: Facts representing the current state of the image. + returned: always + type: dict + sample: { + + } +''' -try: - import json -except ImportError: - import simplejson as json +from ansible.module_utils.docker_common import * try: - from requests.exceptions import * - HAS_REQUESTS = True + from docker import auth + from docker import utils except ImportError: - HAS_REQUESTS = False - -try: - import docker.client - HAS_DOCKER_CLIENT = True -except ImportError: - HAS_DOCKER_CLIENT = False - -DEFAULT_DOCKER_API_VERSION = None -if HAS_DOCKER_CLIENT: - try: - from docker.errors import APIError as DockerAPIError - except ImportError: - from docker.client import APIError as DockerAPIError - - try: - # docker-py 1.2+ - import docker.constants - DEFAULT_DOCKER_API_VERSION = docker.constants.DEFAULT_DOCKER_API_VERSION - except (ImportError, AttributeError): - # docker-py less than 1.2 - DEFAULT_DOCKER_API_VERSION = docker.client.DEFAULT_DOCKER_API_VERSION - -class DockerImageManager: - - def __init__(self, module): - self.module = module - self.path = self.module.params.get('path') - self.dockerfile = self.module.params.get('dockerfile') - self.name = self.module.params.get('name') - self.tag = self.module.params.get('tag') - self.nocache = self.module.params.get('nocache') - - # Connect to the docker server using any configured host and TLS settings. - - env_host = os.getenv('DOCKER_HOST') - env_docker_verify = os.getenv('DOCKER_TLS_VERIFY') - env_cert_path = os.getenv('DOCKER_CERT_PATH') - env_docker_hostname = os.getenv('DOCKER_TLS_HOSTNAME') - - docker_url = module.params.get('docker_url') - if not docker_url: - if env_host: - docker_url = env_host + # missing docker-py handled in docker_common + pass + + +class ImageManager(DockerBaseClass): + + def __init__(self, client, results): + + super(ImageManager, self).__init__() + + self.client = client + self.results = results + parameters = self.client.module.params + self.check_mode = self.client.check_mode + + self.archive_path = parameters.get('archive_path') + self.container_limits = parameters.get('container_limits') + self.dockerfile = parameters.get('dockerfile') + self.force = parameters.get('force') + self.load_path = parameters.get('load_path') + self.name = parameters.get('name') + self.nocache = parameters.get('nocache') + self.path = parameters.get('path') + self.pull = parameters.get('pull') + self.repository = parameters.get('repository') + self.rm = parameters.get('rm') + self.state = parameters.get('state') + self.tag = parameters.get('tag') + self.http_timeout = parameters.get('http_timeout') + self.debug = parameters.get('debug') + self.push = False + + if self.state in ['present', 'build']: + self.present() + elif self.state == 'absent': + self.absent() + + def fail(self, msg): + self.client.fail(msg) + + def present(self): + ''' + Handles state = 'present', which includes building, loading or pulling an image, + depending on user provided parameters. + + :returns None + ''' + image = self.client.find_image(name=self.name, tag=self.tag) + + if not image or self.force: + if self.path: + # Build the image + image_name = self.name + if self.tag: + image_name = "%s:%s" % (self.name, self.tag) + self.log("Building image %s" % image_name) + self.results['actions'].append("Built image %s from %s" % (image_name, self.path)) + self.results['changed'] = True + self.push = True + if not self.check_mode: + self.results['image'] = self.build_image() + elif self.load_path: + # Load the image from an archive + if not os.path.isfile(self.load_path): + self.fail("Error loading image %s. Specified path %s does not exist." % (self.name, + self.load_path)) + self.push = True + image_name = self.name + if self.tag: + image_name = "%s:%s" % (self.name, self.tag) + self.results['actions'].append("Loaded image %s from %s" % (image_name, self.load_path)) + self.results['changed'] = True + if not self.check_mode: + self.results['image'] = self.load_image() else: - docker_url = 'unix://var/run/docker.sock' - - docker_api_version = module.params.get('docker_api_version') + # pull the image + self.results['actions'].append('Pulled image %s:%s' % (self.name, self.tag)) + self.results['changed'] = True + if not self.check_mode: + self.results['image'] = self.client.pull_image(self.name, tag=self.tag) + + if self.archive_path: + self.archive_image(self.name, self.tag) + + if self.push and not self.repository: + self.push_image(self.name, self.tag) + elif self.repository: + self.tag_image(self.name, self.tag, self.repository, force=self.force) + + def absent(self): + ''' + Handles state = 'absent', which removes an image. + + :return None + ''' + image = self.client.find_image(self.name, self.tag) + if image: + name = self.name + if self.tag: + name = "%s:%s" % (self.name, self.tag) + if not self.check_mode: + try: + self.client.remove_image(name, force=self.force) + except Exception as exc: + self.fail("Error removing image %s - %s" % (name, str(exc))) + + self.results['changed'] = True + self.results['actions'].append("Removed image %s" % (name)) + self.results['image']['state'] = 'Deleted' + + def archive_image(self, name, tag): + ''' + Archive an image to a .tar file. Called when archive_path is passed. + + :param name - name of the image. Type: str + :return None + ''' + + if not tag: + tag = "latest" + + image = self.client.find_image(name=name, tag=tag) + if not image: + self.log("archive image: image %s:%s not found" % (name, tag)) + return + + image_name = "%s:%s" % (name, tag) + self.results['actions'].append('Archived image %s to %s' % (image_name, self.archive_path)) + self.results['changed'] = True + if not self.check_mode: + self.log("Getting archive of image %s" % image_name) + try: + image = self.client.get_image(image_name) + except Exception as exc: + self.fail("Error getting image %s - %s" % (image_name, str(exc))) - tls_client_cert = module.params.get('tls_client_cert', None) - if not tls_client_cert and env_cert_path: - tls_client_cert = os.path.join(env_cert_path, 'cert.pem') + try: + image_tar = open(self.archive_path, 'w') + image_tar.write(image.data) + image_tar.close() + except Exception as exc: + self.fail("Error writing image archive %s - %s" % (self.archive_path, str(exc))) + + image = self.client.find_image(name=name, tag=tag) + if image: + self.results['image'] = image + + def push_image(self, name, tag=None): + ''' + If the name of the image contains a repository path, then push the image. + + :param name Name of the image to push. + :param tag Use a specific tag. + :return: None + ''' + + repository = name + if not tag: + repository, tag = utils.parse_repository_tag(name) + registry, repo_name = auth.resolve_repository_name(repository) + + if re.search('/', repository): + if registry: + config = auth.load_config() + if not auth.resolve_authconfig(config, registry): + self.fail("Error: configuration for %s not found. Try logging into %s first." % registry) + + self.log("pushing image %s" % repository) + self.results['actions'].append("Pushed image %s to %s:%s" % (self.name, self.repository, self.tag)) + self.results['changed'] = True + if not self.check_mode: + status = None + try: + for line in self.client.push(repository, tag=tag, stream=True): + line = json.loads(line) + self.log(line, pretty_print=True) + if line.get('errorDetail'): + raise Exception(line['errorDetail']['message']) + status = line.get('status') + except Exception as exc: + if re.search('unauthorized', str(exc)): + self.fail("Error pushing image %s: %s. Does the repository exist?" % (repository, str(exc))) + self.fail("Error pushing image %s: %s" % (repository, str(exc))) + self.results['image'] = self.client.find_image(name=repository, tag=tag) + if not self.results['image']: + self.results['image'] = dict() + self.results['image']['push_status'] = status + + def tag_image(self, name, tag, repository, force=False): + ''' + Tag an image into a repository. + + :param name: name of the image. required. + :param tag: image tag. + :param repository: path to the repository. required. + :param force: bool. force tagging, even it image already exists with the repository path. + :param push: bool. push the image once it's tagged. + :return: None + ''' + repo, repo_tag = utils.parse_repository_tag(repository) + image = self.client.find_image(name=repo, tag=repo_tag) + found = 'found' if image else 'not found' + self.log("image %s was %s" % (repo, found)) + if not image or force: + self.log("tagging %s:%s to %s" % (name, tag, repository)) + self.results['changed'] = True + self.results['actions'].append("Tagged image %s:%s to %s" % (name, tag, repository)) + if not self.check_mode: + try: + # Finding the image does not always work, especially running a localhost registry. In those + # cases, if we don't set force=True, it errors. + image_name = name + if tag and not re.search(tag, name): + image_name = "%s:%s" % (name, tag) + tag_status = self.client.tag(image_name, repository, tag=tag, force=True) + if not tag_status: + raise Exception("Tag operation failed.") + except Exception as exc: + self.fail("Error: failed to tag image %s - %s" % (name, str(exc))) + self.results['image'] = self.client.find_image(name=repository, tag=tag) + self.push_image(repository, tag) + + def build_image(self): + ''' + Build an image + + :return: image dict + ''' + params = dict( + path=self.path, + tag=self.name, + rm=self.rm, + nocache=self.nocache, + stream=True, + timeout=self.http_timeout, + pull=self.pull, + forcerm=self.rm, + dockerfile=self.dockerfile, + decode=True + ) + if self.tag: + params['tag'] = "%s:%s" % (self.name, self.tag) + if self.container_limits: + params['container_limits'] = self.container_limits, + for line in self.client.build(**params): + # line = json.loads(line) + self.log(line, pretty_print=True) + if line.get('error'): + if line.get('errorDetail'): + errorDetail = line.get('errorDetail') + self.fail("Error building %s - code: %s message: %s" % (self.name, + errorDetail.get('code'), + errorDetail.get('message'))) + else: + self.fail("Error building %s - %s" % (self.name, line.get('error'))) + return self.client.find_image(name=self.name, tag=self.tag) - tls_client_key = module.params.get('tls_client_key', None) - if not tls_client_key and env_cert_path: - tls_client_key = os.path.join(env_cert_path, 'key.pem') + def load_image(self): + ''' + Load an image from a .tar archive - tls_ca_cert = module.params.get('tls_ca_cert') - if not tls_ca_cert and env_cert_path: - tls_ca_cert = os.path.join(env_cert_path, 'ca.pem') + :return: image dict + ''' + try: + self.log("Reading image data from %s" % self.load_path) + image_tar = open(self.load_path, 'r') + image_data = image_tar.read() + image_tar.close() + except Exception as exc: + self.fail("Error reading image data %s - %s" % (self.load_path, str(exc))) - tls_hostname = module.params.get('tls_hostname') - if tls_hostname is None: - if env_docker_hostname: - tls_hostname = env_docker_hostname - else: - parsed_url = urlparse(docker_url) - if ':' in parsed_url.netloc: - tls_hostname = parsed_url.netloc[:parsed_url.netloc.rindex(':')] - else: - tls_hostname = parsed_url - if not tls_hostname: - tls_hostname = True - - # use_tls can be one of four values: - # no: Do not use tls - # encrypt: Use tls. We may do client auth. We will not verify the server - # verify: Use tls. We may do client auth. We will verify the server - # None: Only use tls if the parameters for client auth were specified - # or tls_ca_cert (which requests verifying the server with - # a specific ca certificate) - use_tls = module.params.get('use_tls') - if use_tls is None and env_docker_verify is not None: - use_tls = 'verify' - - tls_config = None - if use_tls != 'no': - params = {} - - # Setup client auth - if tls_client_cert and tls_client_key: - params['client_cert'] = (tls_client_cert, tls_client_key) - - # We're allowed to verify the connection to the server - if use_tls == 'verify' or (use_tls is None and tls_ca_cert): - if tls_ca_cert: - params['ca_cert'] = tls_ca_cert - params['verify'] = True - params['assert_hostname'] = tls_hostname - else: - params['verify'] = True - params['assert_hostname'] = tls_hostname - elif use_tls == 'encrypt': - params['verify'] = False - - if params: - # See https://github.com/docker/docker-py/blob/d39da11/docker/utils/utils.py#L279-L296 - docker_url = docker_url.replace('tcp://', 'https://') - tls_config = docker.tls.TLSConfig(**params) - - self.client = docker.Client( - base_url=docker_url, - version=module.params.get('docker_api_version'), - timeout=module.params.get('timeout'), - tls=tls_config) - - self.changed = False - self.log = [] - self.error_msg = None - - def get_log(self, as_string=True): - return "".join(self.log) if as_string else self.log - - def build(self): - stream = self.client.build(self.path, dockerfile=self.dockerfile, tag=':'.join([self.name, self.tag]), nocache=self.nocache, rm=True, stream=True) - success_search = r'Successfully built ([0-9a-f]+)' - image_id = None - self.changed = True - - for chunk in stream: - if not chunk: - continue + try: + self.log("Loading image from %s" % self.load_path) + self.client.load_image(image_data) + except Exception as exc: + self.fail("Error loading image %s - %s" % (self.name, str(exc))) - try: - chunk_json = json.loads(chunk) - except ValueError: - continue - - if 'error' in chunk_json: - self.error_msg = chunk_json['error'] - return None - - if 'stream' in chunk_json: - output = chunk_json['stream'] - self.log.append(output) - match = re.search(success_search, output) - if match: - image_id = match.group(1) - - # Just in case we skipped evaluating the JSON returned from build - # during every iteration, add an error if the image_id was never - # populated - if not image_id: - self.error_msg = 'Unknown error encountered' - - return image_id - - def has_changed(self): - return self.changed - - def get_images(self): - filtered_images = [] - images = self.client.images() - for i in images: - # Docker-py version >= 0.3 (Docker API >= 1.8) - if 'RepoTags' in i: - repotag = ':'.join([self.name, self.tag]) - if not self.name or repotag in i['RepoTags']: - filtered_images.append(i) - # Docker-py version < 0.3 (Docker API < 1.8) - elif (not self.name or self.name == i['Repository']) and (not self.tag or self.tag == i['Tag']): - filtered_images.append(i) - return filtered_images - - def remove_images(self): - images = self.get_images() - for i in images: - try: - self.client.remove_image(i['Id']) - self.changed = True - except DockerAPIError as e: - # image can be removed by docker if not used - pass + return self.client.find_image(self.name, self.tag) def main(): - module = AnsibleModule( - argument_spec = dict( - path = dict(required=False, default=None, type='path'), - dockerfile = dict(required=False, default="Dockerfile"), - name = dict(required=True), - tag = dict(required=False, default="latest"), - nocache = dict(default=False, type='bool'), - state = dict(default='present', choices=['absent', 'present', 'build']), - use_tls = dict(default=None, choices=['no', 'encrypt', 'verify']), - tls_client_cert = dict(required=False, default=None, type='str'), - tls_client_key = dict(required=False, default=None, type='str'), - tls_ca_cert = dict(required=False, default=None, type='str'), - tls_hostname = dict(required=False, type='str', default=None), - docker_url = dict(), - docker_api_version = dict(required=False, - default=DEFAULT_DOCKER_API_VERSION, - type='str'), - timeout = dict(default=600, type='int'), - ) + argument_spec = dict( + archive_path=dict(type='str'), + container_limits=dict(type='dict'), + dockerfile=dict(type='str'), + force=dict(type='bool', default=False), + http_timeout=dict(type='int'), + load_path=dict(type='str'), + name=dict(type='str', required=True), + nocache=dict(type='str', default=False), + path=dict(type='str', aliases=['build_path']), + pull=dict(type='bool', default=True), + repository=dict(type='str'), + rm=dict(type='bool', default=True), + state=dict(type='str', choices=['absent', 'present'], default='present'), + tag=dict(type='str', default='latest'), + use_tls=dict(type='str', default='no', choices=['no', 'encrypt', 'verify']) ) - if not HAS_DOCKER_CLIENT: - module.fail_json(msg='docker-py is needed for this module') - if not HAS_REQUESTS: - module.fail_json(msg='requests is needed for this module') - - try: - manager = DockerImageManager(module) - state = module.params.get('state') - failed = False - image_id = None - msg = '' - do_build = False - - # build image if not exists - if state == "present": - images = manager.get_images() - if len(images) == 0: - do_build = True - # build image - elif state == "build": - do_build = True - # remove image or images - elif state == "absent": - manager.remove_images() - - if do_build: - image_id = manager.build() - if image_id: - msg = "Image built: %s" % image_id - else: - failed = True - msg = "Error: %s\nLog:%s" % (manager.error_msg, manager.get_log()) - - module.exit_json(failed=failed, changed=manager.has_changed(), msg=msg, image_id=image_id) - - except SSLError as e: - if get_platform() == "Darwin": - # Ensure that the environment variables has been set - if "DOCKER_HOST" not in os.environ: - environment_error = ''' - It looks like you have not set your docker environment - variables. Please ensure that you have set the requested - variables as instructed when running boot2docker up. If - they are set in .bash_profile you will need to symlink - it to .bashrc. - ''' - module.exit_json(failed=True, changed=manager.has_changed(), msg="SSLError: " + str(e) + environment_error) - # If the above is true it's likely the hostname does not match - else: - environment_error = ''' - You may need to ignore hostname missmatches by setting - tls_hostname=boot2docker in your role. If this does not - resolve the issue please open an issue at - ansible/ansible-modules-core and ping michaeljs1990 - ''' - module.exit_json(failed=True, changed=manager.has_changed(), msg="SSLError: " + str(e) + environment_error) - # General error for non darwin users - else: - module.exit_json(failed=True, changed=manager.has_changed(), msg="SSLError: " + str(e)) - - except ConnectionError as e: - if get_platform() == "Darwin" and "DOCKER_HOST" not in os.environ: - # Ensure that the environment variables has been set - environment_error = ''' - It looks like you have not set your docker environment - variables. Please ensure that you have set the requested - variables as instructed when running boot2docker up. If - they are set in .bash_profile you will need to symlink - it to .bashrc. - ''' - module.exit_json(failed=True, changed=manager.has_changed(), msg="ConnectionError: " + str(e) + environment_error) - - module.exit_json(failed=True, changed=manager.has_changed(), msg="ConnectionError: " + str(e)) - - except DockerAPIError as e: - module.exit_json(failed=True, changed=manager.has_changed(), msg="Docker API error: " + e.explanation) - - except RequestException as e: - module.exit_json(failed=True, changed=manager.has_changed(), msg=repr(e)) + + client = AnsibleDockerClient( + argument_spec=argument_spec, + supports_check_mode=True, + ) + + results = dict( + changed=False, + actions=[], + image={} + ) + + ImageManager(client, results) + client.module.exit_json(**results) + # import module snippets from ansible.module_utils.basic import * + if __name__ == '__main__': main() |