Pull newer image versions when requested.

This commit is contained in:
Ash Wilson 2014-12-12 11:14:24 -05:00 committed by Matt Clay
parent 6505ce3940
commit 338bbf6efc

View file

@ -326,6 +326,8 @@ EXAMPLES = '''
HAS_DOCKER_PY = True
import sys
import json
import re
from urlparse import urlparse
try:
import docker.client
@ -635,6 +637,18 @@ class DockerManager(object):
return False
def get_inspect_image(self):
image, tag = get_split_image_tag(self.module.params.get('image'))
if tag is None:
tag = 'latest'
resource = '%s:%s' % (image, tag)
matching_image = None
for image in self.client.images(name=image):
if resource in image.get('RepoTags', []):
matching_image = image
return matching_image
def get_inspect_containers(self, containers):
inspect = []
for i in containers:
@ -687,6 +701,41 @@ class DockerManager(object):
return running
def pull_image(self):
extra_params = {}
if self.module.params.get('insecure_registry'):
if self.ensure_capability('insecure_registry', fail=False):
extra_params['insecure_registry'] = self.module.params.get('insecure_registry')
resource = self.module.params.get('image')
image, tag = get_split_image_tag(resource)
if self.module.params.get('username'):
try:
self.client.login(
self.module.params.get('username'),
password=self.module.params.get('password'),
email=self.module.params.get('email'),
registry=self.module.params.get('registry')
)
except:
self.module.fail_json(msg="failed to login to the remote registry, check your username/password.")
try:
last = None
for line in self.client.pull(image, tag=tag, stream=True, **extra_params):
last = line
status = json.loads(last).get('status', '')
if status.startswith('Status: Image is up to date for'):
# Image is already up to date. Don't increment the counter.
pass
elif status.startswith('Status: Downloaded newer image for'):
# Image was updated. Increment the pull counter.
self.increment_counter('pull')
else:
# Unrecognized status string.
self.module.fail_json(msg="Unrecognized status from pull", status=status)
except:
self.module.fail_json(msg="failed to pull the specified image: %s" % resource)
def create_containers(self, count=1):
params = {'image': self.module.params.get('image'),
'command': self.module.params.get('command'),
@ -708,11 +757,6 @@ class DockerManager(object):
if params['volumes_from'] is not None:
self.ensure_capability('volumes_from')
extra_params = {}
if self.module.params.get('insecure_registry'):
if self.ensure_capability('insecure_registry', fail=False):
extra_params['insecure_registry'] = self.module.params.get('insecure_registry')
def do_create(count, params):
results = []
for _ in range(count):
@ -725,23 +769,7 @@ class DockerManager(object):
try:
containers = do_create(count, params)
except:
resource = self.module.params.get('image')
image, tag = get_split_image_tag(resource)
if self.module.params.get('username'):
try:
self.client.login(
self.module.params.get('username'),
password=self.module.params.get('password'),
email=self.module.params.get('email'),
registry=self.module.params.get('registry')
)
except:
self.module.fail_json(msg="failed to login to the remote registry, check your username/password.")
try:
self.client.pull(image, tag=tag, **extra_params)
except:
self.module.fail_json(msg="failed to pull the specified image: %s" % resource)
self.increment_counter('pull')
self.pull_image()
containers = do_create(count, params)
return containers
@ -807,6 +835,7 @@ def main():
argument_spec = dict(
count = dict(default=1),
image = dict(required=True),
pull = dict(required=False, default='missing', choices=['missing', 'always']),
command = dict(required=False, default=None),
expose = dict(required=False, default=None, type='list'),
ports = dict(required=False, default=None, type='list'),
@ -849,12 +878,25 @@ def main():
count = int(module.params.get('count'))
name = module.params.get('name')
image = module.params.get('image')
pull = module.params.get('pull')
if count < 0:
module.fail_json(msg="Count must be greater than zero")
if count > 1 and name:
module.fail_json(msg="Count and name must not be used together")
# Explicitly pull new container images, if requested.
# Do this before noticing running and deployed containers so that the image names will differ
# if a newer image has been pulled.
if pull == "always":
manager.pull_image()
# Find the ID of the requested image and tag, if available.
image_id = None
inspected_image = manager.get_inspect_image()
if inspected_image:
image_id = inspected_image.get('Id')
running_containers = manager.get_running_containers()
running_count = len(running_containers)
delta = count - running_count
@ -877,7 +919,7 @@ def main():
# the named container is running, but with a
# different image or tag, so we stop it first
if existing_container and existing_container.get('Config', dict()).get('Image') != image:
if existing_container and (image_id is None or existing_container.get('Image') != image_id):
manager.stop_containers([existing_container])
manager.remove_containers([existing_container])
running_containers = manager.get_running_containers()