Updater per PR comments

This commit is contained in:
chouseknecht 2016-04-23 10:09:44 -04:00 committed by Matt Clay
parent 720e7daa3a
commit 6aa76b835a

View file

@ -23,7 +23,7 @@ module: docker_image
short_description: Manage docker images. short_description: Manage docker images.
version_added: "2.1.0" version_added: "1.5"
description: description:
- Build, load or pull an image, making the image available for creating containers. Also supports tagging an - Build, load or pull an image, making the image available for creating containers. Also supports tagging an
@ -35,10 +35,6 @@ options:
- Use with state 'present' to archive an image to a .tar file. - Use with state 'present' to archive an image to a .tar file.
required: false required: false
default: null default: null
config_path:
description:
- Path to the Docker CLI config file.
default: '~/.docker/config.json'
dockerfile: dockerfile:
description: description:
- Use with state 'present' to provide an alternate name for the Dockerfile to use when building an image. - Use with state 'present' to provide an alternate name for the Dockerfile to use when building an image.
@ -68,14 +64,9 @@ options:
- build_path - build_path
default: null default: null
required: false required: false
push:
description:
- "Use with state present to always push an image to the registry. The image name must contain a repository
path and optionally a registry. For example: registry.ansible.com/user_a/repository"
default: false
pull: pull:
description: description:
- When building an image downloads any updates to the FROM image in Dockerfiles. - When building an image downloads any updates to the FROM image in Dockerfile.
default: true default: true
rm: rm:
description: description:
@ -99,7 +90,7 @@ options:
force option is used, the image will either be pulled, built or loaded. By default the image will be pulled 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 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 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. 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'." - "NOTE: 'build' is DEPRECATED. Specifying 'build' will behave the same as 'present'."
default: present default: present
choices: choices:
@ -144,12 +135,11 @@ EXAMPLES = '''
docker_image: docker_image:
name: pacur/centos-7 name: pacur/centos-7
- name: Tag to repository in private registry - name: Tag to repository to a private registry and push it
docker_image: docker_image:
name: pacur/centos-7 name: pacur/centos-7
repository: registry.ansible.com/chouseknecht/centos_images repository: registry.ansible.com/chouseknecht/centos_images
tag: 7.0 tag: 7.0
push: yes
- name: Remove image - name: Remove image
docker_image: docker_image:
@ -157,7 +147,7 @@ EXAMPLES = '''
name: registry.ansible.com/chouseknecht/sinatra name: registry.ansible.com/chouseknecht/sinatra
tag: v1 tag: v1
- name: Build an image - name: Build an image ad push it to a private repo
docker_image: docker_image:
path: ./sinatra path: ./sinatra
name: registry.ansible.com/chouseknecht/sinatra name: registry.ansible.com/chouseknecht/sinatra
@ -169,7 +159,7 @@ EXAMPLES = '''
tag: v1 tag: v1
archive_path: my_sinatra.tar archive_path: my_sinatra.tar
- name: Load image from archive - name: Load image from archive and push it to a private registry
docker_image: docker_image:
name: registry.ansible.com/chouseknecht/sinatra name: registry.ansible.com/chouseknecht/sinatra
tag: v1 tag: v1
@ -215,7 +205,6 @@ class ImageManager(DockerBaseClass):
self.check_mode = self.client.check_mode self.check_mode = self.client.check_mode
self.archive_path = parameters.get('archive_path') self.archive_path = parameters.get('archive_path')
self.config_path = parameters.get('config_path')
self.container_limits = parameters.get('container_limits') self.container_limits = parameters.get('container_limits')
self.dockerfile = parameters.get('dockerfile') self.dockerfile = parameters.get('dockerfile')
self.force = parameters.get('force') self.force = parameters.get('force')
@ -224,12 +213,12 @@ class ImageManager(DockerBaseClass):
self.nocache = parameters.get('nocache') self.nocache = parameters.get('nocache')
self.path = parameters.get('path') self.path = parameters.get('path')
self.pull = parameters.get('pull') self.pull = parameters.get('pull')
self.push = parameters.get('push')
self.repository = parameters.get('repository') self.repository = parameters.get('repository')
self.rm = parameters.get('rm') self.rm = parameters.get('rm')
self.state = parameters.get('state') self.state = parameters.get('state')
self.tag = parameters.get('tag') self.tag = parameters.get('tag')
self.http_timeout = parameters.get('http_timeout') self.http_timeout = parameters.get('http_timeout')
self.push = False
if self.state in ['present', 'build']: if self.state in ['present', 'build']:
self.present() self.present()
@ -251,6 +240,7 @@ class ImageManager(DockerBaseClass):
if not image or self.force: if not image or self.force:
if self.path: if self.path:
# build the image # build the image
self.push = True
params = dict( params = dict(
path=self.path, path=self.path,
tag=self.name, tag=self.name,
@ -268,11 +258,11 @@ class ImageManager(DockerBaseClass):
if self.container_limits: if self.container_limits:
params['container_limits'] = self.container_limits, params['container_limits'] = self.container_limits,
self.log("Building image %s" % (params['tag'])) self.log("Building image %s" % (params['tag']))
self.results['actions'].append("Built image %s from %s" % (params['tag'], self.path))
self.results['changed'] = True
if not self.check_mode: if not self.check_mode:
self.results['actions'].append("Built image %s from %s" % (params['tag'], self.path))
for line in self.client.build(**params): for line in self.client.build(**params):
self.log(line, pretty_print=True) self.log(line, pretty_print=True)
self.results['changed'] = True
image = self.client.find_image(name=self.name, tag=self.tag) image = self.client.find_image(name=self.name, tag=self.tag)
if image: if image:
self.results['image'] = image self.results['image'] = image
@ -282,12 +272,14 @@ class ImageManager(DockerBaseClass):
if not os.path.isfile(self.load_path): if not os.path.isfile(self.load_path):
self.fail("Error loading image %s. Specified path %s does not exist." % (self.name, self.fail("Error loading image %s. Specified path %s does not exist." % (self.name,
self.load_path)) self.load_path))
self.push = True
name = self.name name = self.name
if self.tag: if self.tag:
name = "%s:%s" % (self.name, self.tag) name = "%s:%s" % (self.name, self.tag)
self.results['actions'].append("Loaded image %s from %s" % (name, self.load_path))
self.results['changed'] = True
if not self.check_mode: if not self.check_mode:
self.results['actions'].append("Loaded image %s from %s" % (name, self.load_path))
try: try:
self.log("Reading image data from %s" % (self.load_path)) self.log("Reading image data from %s" % (self.load_path))
image_tar = open(self.load_path, 'r') image_tar = open(self.load_path, 'r')
@ -298,15 +290,13 @@ class ImageManager(DockerBaseClass):
try: try:
self.log("Loading image from %s" % (self.load_path)) self.log("Loading image from %s" % (self.load_path))
response = self.client.load_image(image_data) self.client.load_image(image_data)
except Exception, exc: except Exception, exc:
self.fail("Error loading image %s - %s" % (name, str(exc))) self.fail("Error loading image %s - %s" % (name, str(exc)))
self.results['changed'] = True
image = self.client.find_image(self.name, self.tag) image = self.client.find_image(self.name, self.tag)
if image: if image:
self.results['image'] = image self.results['image'] = image
else: else:
# pull the image # pull the image
if not self.check_mode: if not self.check_mode:
@ -368,8 +358,9 @@ class ImageManager(DockerBaseClass):
except Exception, exc: except Exception, exc:
self.fail("Error getting image %s - %s" % (image_name, str(exc))) self.fail("Error getting image %s - %s" % (image_name, str(exc)))
self.results['actions'].append('Archived image %s to %s' % (image_name, self.archive_path))
self.results['changed'] = True
if not self.check_mode: if not self.check_mode:
self.results['actions'].append('Archived image %s to %s' % (image_name, self.archive_path))
try: try:
image_tar = open(self.archive_path, 'w') image_tar = open(self.archive_path, 'w')
image_tar.write(image.data) image_tar.write(image.data)
@ -377,50 +368,52 @@ class ImageManager(DockerBaseClass):
except Exception, exc: except Exception, exc:
self.fail("Error writing image archive %s - %s" % (self.archive_path, str(exc))) self.fail("Error writing image archive %s - %s" % (self.archive_path, str(exc)))
self.results['changed'] = True
image = self.client.find_image(name=name, tag=tag) image = self.client.find_image(name=name, tag=tag)
if image: if image:
self.results['image'] = image self.results['image'] = image
def push_image(self, name, tag=None): def push_image(self, name, tag=None):
''' '''
Push an image to a repository. If the name of the image contains a repository path, then push the image.
:param name - name of the image to push. Type: str :param name Name of the image to push.
:param tag - use a specific tag. Type: str :param tag Use a specific tag.
:return: None :return: None
''' '''
repository = name repository = name
if not tag: if not tag:
repository, tag = utils.parse_repository_tag(name) repository, tag = utils.parse_repository_tag(name)
registry, repo_name = auth.resolve_repository_name(repository) registry, repo_name = auth.resolve_repository_name(repository)
if registry: if re.search('/', repository):
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)
try: if registry:
self.log("pushing image %s" % (repository)) config = auth.load_config()
status = None if not auth.resolve_authconfig(config, registry):
if not self.check_mode: self.fail("Error: configuration for %s not found. Try logging into %s first." % registry)
try:
self.log("pushing image %s" % (repository))
status = None
self.results['actions'].append("Pushed image %s to %s:%s" % (self.name, self.repository, self.tag)) self.results['actions'].append("Pushed image %s to %s:%s" % (self.name, self.repository, self.tag))
for line in self.client.push(repository, tag=tag, stream=True): self.results['changed'] = True
response = json.loads(line) if not self.check_mode:
self.log(response, pretty_print=True) for line in self.client.push(repository, tag=tag, stream=True):
if response.get('errorDetail'): response = json.loads(line)
# there was an error self.log(response, pretty_print=True)
raise Exception(response['errorDetail']['message']) if response.get('errorDetail'):
status = response.get('status') # there was an error
self.results['changed'] = True raise Exception(response['errorDetail']['message'])
image = self.client.find_image(name=repository, tag=tag) status = response.get('status')
if image: image = self.client.find_image(name=repository, tag=tag)
self.results['image'] = image if image:
self.results['image']['push_status'] = status self.results['image'] = image
except Exception, exc: self.results['image']['push_status'] = status
if re.search(r'unauthorized', str(exc)): except Exception, exc:
self.fail("Error pushing image %s: %s. Does the repository exist?" % (repository, str(exc))) if re.search(r'unauthorized', str(exc)):
self.fail("Error pushing image %s: %s" % (repository, 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)))
def tag_image(self, name, tag, repository, force=False, push=False): def tag_image(self, name, tag, repository, force=False, push=False):
''' '''
@ -441,11 +434,14 @@ class ImageManager(DockerBaseClass):
try: try:
self.log("tagging %s:%s to %s" % (name, tag, repository)) self.log("tagging %s:%s to %s" % (name, tag, repository))
self.results['changed'] = True self.results['changed'] = True
self.results['actions'].append("Tagged image %s:%s to %s" % (name, tag, repository))
if not self.check_mode: if not self.check_mode:
self.results['actions'].append("Tagged image %s:%s to %s" % (name, tag, repository))
# Finding the image does not always work, especially running a localhost registry. In those # Finding the image does not always work, especially running a localhost registry. In those
# cases, if we don't set force=True, it errors. # cases, if we don't set force=True, it errors.
tag_status = self.client.tag(name, repository, tag=tag, force=True) 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: if not tag_status:
raise Exception("Tag operation failed.") raise Exception("Tag operation failed.")
image = self.client.find_image(name=repository, tag=tag) image = self.client.find_image(name=repository, tag=tag)
@ -454,15 +450,12 @@ class ImageManager(DockerBaseClass):
except Exception, exc: except Exception, exc:
self.fail("Error: failed to tag image %s - %s" % (name, str(exc))) self.fail("Error: failed to tag image %s - %s" % (name, str(exc)))
if push: self.push_image(repository, tag)
self.log("push %s with tag %s" % (repository, tag))
self.push_image(repository, tag)
def main(): def main():
argument_spec = dict( argument_spec = dict(
archive_path=dict(type='str'), archive_path=dict(type='str'),
config_path=dict(type='str'),
container_limits=dict(type='dict'), container_limits=dict(type='dict'),
dockerfile=dict(type='str'), dockerfile=dict(type='str'),
force=dict(type='bool', default=False), force=dict(type='bool', default=False),
@ -472,7 +465,6 @@ def main():
nocache=dict(type='str', default=False), nocache=dict(type='str', default=False),
path=dict(type='str', aliases=['build_path']), path=dict(type='str', aliases=['build_path']),
pull=dict(type='bool', default=True), pull=dict(type='bool', default=True),
push=dict(type='bool', default=False),
repository=dict(type='str'), repository=dict(type='str'),
rm=dict(type='bool', default=True), rm=dict(type='bool', default=True),
state=dict(type='str', choices=['absent', 'present'], default='present'), state=dict(type='str', choices=['absent', 'present'], default='present'),