Skip to content
This repository has been archived by the owner on Oct 30, 2018. It is now read-only.

Improved error handling for pull and build #5159

Merged
merged 2 commits into from Oct 5, 2016
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
182 changes: 111 additions & 71 deletions cloud/docker/docker_service.py
Expand Up @@ -464,7 +464,7 @@
try:
from compose import __version__ as compose_version
from compose.cli.command import project_from_options
from compose.service import ConvergenceStrategy
from compose.service import ConvergenceStrategy, NoSuchImageError
from compose.cli.main import convergence_strategy_from_opts, build_action_from_opts, image_type_from_opt
from compose.const import DEFAULT_TIMEOUT
except ImportError as exc:
Expand All @@ -484,7 +484,7 @@
u'tls_verify': u'--tlsverify'
}


class ContainerManager(DockerBaseClass):

def __init__(self, client):
Expand Down Expand Up @@ -598,11 +598,11 @@ def _get_auth_options(self):
return options

def cmd_up(self):

start_deps = self.dependencies
service_names = self.services
detached = True
result = dict(changed=False, actions=dict(), ansible_facts=dict())
result = dict(changed=False, actions=[], ansible_facts=dict())

up_options = {
u'--no-recreate': False,
Expand All @@ -624,26 +624,29 @@ def cmd_up(self):
self.log("convergence strategy: %s" % converge)

if self.pull:
result.update(self.cmd_pull())
pull_output = self.cmd_pull()
result['changed'] = pull_output['changed']
result['actions'] += pull_output['actions']

if self.build:
result.update(self.cmd_build())
build_output = self.cmd_build()
result['changed'] = build_output['changed']
result['actions'] += build_output['actions']

for service in self.project.services:
if not service_names or service.name in service_names:
plan = service.convergence_plan(strategy=converge)
if plan.action != 'noop':
result['changed'] = True
if self.debug or self.check_mode:
if not result['actions'].get(service.name):
result['actions'][service.name] = dict()
result['actions'][service.name][plan.action] = []
result_action = dict(service=service.name)
result_action[plan.action] = []
for container in plan.containers:
result['actions'][service.name][plan.action].append(dict(
result_action[plan.action].append(dict(
id=container.id,
name=container.name,
short_id=container.short_id,
))
result['actions'].append(result_action)

if not self.check_mode and result['changed']:
try:
Expand All @@ -661,13 +664,19 @@ def cmd_up(self):
self.client.fail("Error starting project - %s" % str(exc))

if self.stopped:
result.update(self.cmd_stop(service_names))
stop_output = self.cmd_stop(service_names)
result['changed'] = stop_output['changed']
result['actions'] += stop_output['actions']

if self.restarted:
result.update(self.cmd_restart(service_names))
restart_output = self.cmd_restart(service_names)
result['changed'] = restart_output['changed']
result['actions'] += restart_output['actions']

if self.scale:
result.update(self.cmd_scale())
scale_output = self.cmd_scale()
result['changed'] = scale_output['changed']
result['actions'] += scale_output['actions']

for service in self.project.services:
result['ansible_facts'][service.name] = dict()
Expand Down Expand Up @@ -729,105 +738,131 @@ def cmd_up(self):
def cmd_pull(self):
result = dict(
changed=False,
actions=dict(),
actions=[],
)

if not self.check_mode:
for service in self.project.get_services(self.services, include_deps=False):
if 'image' not in service.options:
continue

self.log('Pulling image for service %s' % service.name)
# store the existing image ID
image = service.image()
old_image_id = None
if image and image.get('Id'):
old_image_id = image['Id']
old_image_id = ''
try:
image = service.image()
if image and image.get('Id'):
old_image_id = image['Id']
except NoSuchImageError:
pass
except Exception as exc:
self.client.fail("Error: service image lookup failed - %s" % str(exc))

# pull the image
service.pull(ignore_pull_failures=False)
try:
service.pull(ignore_pull_failures=False)
except Exception as exc:
self.client.fail("Error: pull failed with %s" % str(exc))

# store the new image ID
image = service.image()
new_image_id = None
if image and image.get('Id'):
new_image_id = image['Id']
new_image_id = ''
try:
image = service.image()
if image and image.get('Id'):
new_image_id = image['Id']
except NoSuchImageError as exc:
self.client.fail("Error: service image lookup failed after pull - %s" % str(exc))

if new_image_id != old_image_id:
# if a new image was pulled
result['changed'] = True
result['actions'][service.name] = dict()
result['actions'][service.name]['pulled_image'] = dict(
name=service.image_name,
id=service.image()['Id']
)
result['actions'].append(dict(
service=service.name,
pulled_image=dict(
name=service.image_name,
id=new_image_id
)
))
return result

def cmd_build(self):
result = dict(
changed=False,
actions=dict(),
actions=[]
)
if not self.check_mode:
for service in self.project.get_services(self.services, include_deps=False):
self.log('Building image for service %s' % service.name)
if service.can_be_built():
self.log('Building image for service %s' % service.name)
# store the existing image ID
image = service.image()
old_image_id = None
if image and image.get('Id'):
old_image_id = image['Id']
old_image_id = ''
try:
image = service.image()
if image and image.get('Id'):
old_image_id = image['Id']
except NoSuchImageError:
pass
except Exception as exc:
self.client.fail("Error: service image lookup failed - %s" % str(exc))

# build the image
new_image_id = service.build(pull=True, no_cache=self.nocache)
try:
new_image_id = service.build(pull=True, no_cache=self.nocache)
except Exception as exc:
self.client.fail("Error: build failed with %s" % str(exc))

if new_image_id not in old_image_id:
# if a new image was built
result['changed'] = True
result['actions'][service.name] = dict()
result['actions'][service.name]['built_image'] = dict(
name=service.image_name,
id=service.image()['Id']
)
result['actions'].append(dict(
service=service.name,
built_image=dict(
name=service.image_name,
id=new_image_id
)
))
return result

def cmd_down(self):
result = dict(
changed=False,
actions=dict(),
actions=[]
)

for service in self.project.services:
containers = service.containers(stopped=True)
if len(containers):
result['changed'] = True
if self.debug or self.check_mode:
result['actions'][service.name] = dict()
result['actions'][service.name]['deleted'] = [container.name for container in containers]

result['actions'].append(dict(
service=service.name,
deleted=[container.name for container in containers]
))
if not self.check_mode and result['changed']:
image_type = image_type_from_opt('--rmi', self.remove_images)
try:
self.project.down(image_type, self.remove_volumes, self.remove_orphans)
except Exception as exc:
self.client.fail("Error stopping project - %s" % str(exc))

return result

def cmd_stop(self, service_names):
result = dict(
changed=False,
actions=dict()
actions=[]
)
for service in self.project.services:
if not service_names or service.name in service_names:
result['actions'][service.name] = dict()
result['actions'][service.name]['stop'] = []
service_res = dict(
service=service.name,
stop=[]
)
for container in service.containers(stopped=False):
result['changed'] = True
if self.debug:
result['actions'][service.name]['stop'].append(dict(
id=container.id,
name=container.name,
short_id=container.short_id,
))
service_res['stop'].append(dict(
id=container.id,
name=container.name,
short_id=container.short_id
))
result['actions'].append(service_res)

if not self.check_mode and result['changed']:
try:
Expand All @@ -840,22 +875,24 @@ def cmd_stop(self, service_names):
def cmd_restart(self, service_names):
result = dict(
changed=False,
actions=dict()
actions=[]
)

for service in self.project.services:
if not service_names or service.name in service_names:
result['actions'][service.name] = dict()
result['actions'][service.name]['restart'] = []
service_res = dict(
service=service.name,
restart=[]
)
for container in service.containers(stopped=True):
result['changed'] = True
if self.debug or self.check_mode:
result['actions'][service.name]['restart'].append(dict(
id=container.id,
name=container.name,
short_id=container.short_id,
))

service_res['restart'].append(dict(
id=container.id,
name=container.name,
short_id=container.short_id
))
result['actions'].append(service_res)
if not self.check_mode and result['changed']:
try:
self.project.restart(service_names=service_names, timeout=self.timeout)
Expand All @@ -867,22 +904,25 @@ def cmd_restart(self, service_names):
def cmd_scale(self):
result = dict(
changed=False,
actions=dict()
actions=[]
)

for service in self.project.services:
if service.name in self.scale:
result['actions'][service.name] = dict()
service_res = dict(
service=service.name,
scale=0
)
containers = service.containers(stopped=True)
if len(containers) != self.scale[service.name]:
result['changed'] = True
if self.debug or self.check_mode:
result['actions'][service.name]['scale'] = self.scale[service.name] - len(containers)
service_res['scale'] = self.scale[service.name] - len(containers)
if not self.check_mode:
try:
service.scale(int(self.scale[service.name]))
except Exception as exc:
self.client.fail("Error scaling %s - %s" % (service.name, str(exc)))
result['actions'].append(service_res)
return result


Expand Down