Catch healthcheck exceptions in parallel_execute

Signed-off-by: Joffrey F <joffrey@docker.com>
This commit is contained in:
Joffrey F 2017-01-17 13:22:16 -08:00
parent 5ade097d74
commit 56a1b02aac
2 changed files with 26 additions and 18 deletions

View File

@ -12,6 +12,8 @@ from six.moves.queue import Empty
from six.moves.queue import Queue from six.moves.queue import Queue
from compose.cli.signals import ShutdownException from compose.cli.signals import ShutdownException
from compose.errors import HealthCheckFailed
from compose.errors import NoHealthCheckConfigured
from compose.errors import OperationFailedError from compose.errors import OperationFailedError
from compose.utils import get_output_stream from compose.utils import get_output_stream
@ -48,7 +50,7 @@ def parallel_execute(objects, func, get_name, msg, get_deps=None):
elif isinstance(exception, APIError): elif isinstance(exception, APIError):
errors[get_name(obj)] = exception.explanation errors[get_name(obj)] = exception.explanation
writer.write(get_name(obj), 'error') writer.write(get_name(obj), 'error')
elif isinstance(exception, OperationFailedError): elif isinstance(exception, (OperationFailedError, HealthCheckFailed, NoHealthCheckConfigured)):
errors[get_name(obj)] = exception.msg errors[get_name(obj)] = exception.msg
writer.write(get_name(obj), 'error') writer.write(get_name(obj), 'error')
elif isinstance(exception, UpstreamError): elif isinstance(exception, UpstreamError):
@ -164,21 +166,27 @@ def feed_queue(objects, func, get_deps, results, state):
for obj in pending: for obj in pending:
deps = get_deps(obj) deps = get_deps(obj)
try:
if any(dep[0] in state.failed for dep in deps): if any(dep[0] in state.failed for dep in deps):
log.debug('{} has upstream errors - not processing'.format(obj)) log.debug('{} has upstream errors - not processing'.format(obj))
results.put((obj, None, UpstreamError())) results.put((obj, None, UpstreamError()))
state.failed.add(obj) state.failed.add(obj)
elif all( elif all(
dep not in objects or ( dep not in objects or (
dep in state.finished and (not ready_check or ready_check(dep)) dep in state.finished and (not ready_check or ready_check(dep))
) for dep, ready_check in deps ) for dep, ready_check in deps
): ):
log.debug('Starting producer thread for {}'.format(obj)) log.debug('Starting producer thread for {}'.format(obj))
t = Thread(target=producer, args=(obj, func, results)) t = Thread(target=producer, args=(obj, func, results))
t.daemon = True t.daemon = True
t.start() t.start()
state.started.add(obj) state.started.add(obj)
except (HealthCheckFailed, NoHealthCheckConfigured) as e:
log.debug(
'Healthcheck for service(s) upstream of {} failed - '
'not processing'.format(obj)
)
results.put((obj, None, e))
if state.is_done(): if state.is_done():
results.put(STOP) results.put(STOP)

View File

@ -1443,7 +1443,7 @@ class ProjectTest(DockerClientTestCase):
project = Project.from_config( project = Project.from_config(
name='composetest', config_data=config_data, client=self.client name='composetest', config_data=config_data, client=self.client
) )
with pytest.raises(HealthCheckFailed): with pytest.raises(ProjectError):
project.up() project.up()
containers = project.containers() containers = project.containers()
assert len(containers) == 1 assert len(containers) == 1
@ -1479,7 +1479,7 @@ class ProjectTest(DockerClientTestCase):
project = Project.from_config( project = Project.from_config(
name='composetest', config_data=config_data, client=self.client name='composetest', config_data=config_data, client=self.client
) )
with pytest.raises(NoHealthCheckConfigured): with pytest.raises(ProjectError):
project.up() project.up()
containers = project.containers() containers = project.containers()
assert len(containers) == 1 assert len(containers) == 1