mirror of https://github.com/docker/compose.git
service: detailed error messages for create and start
Fixes: #3355 Signed-off-by: Tomas Tomecek <ttomecek@redhat.com>
This commit is contained in:
parent
c3fd6a8f4d
commit
fea970dff3
|
@ -32,6 +32,7 @@ from ..service import BuildError
|
||||||
from ..service import ConvergenceStrategy
|
from ..service import ConvergenceStrategy
|
||||||
from ..service import ImageType
|
from ..service import ImageType
|
||||||
from ..service import NeedsBuildError
|
from ..service import NeedsBuildError
|
||||||
|
from ..service import OperationFailedError
|
||||||
from .command import get_config_from_options
|
from .command import get_config_from_options
|
||||||
from .command import project_from_options
|
from .command import project_from_options
|
||||||
from .docopt_command import DocoptDispatcher
|
from .docopt_command import DocoptDispatcher
|
||||||
|
@ -61,7 +62,8 @@ def main():
|
||||||
except (KeyboardInterrupt, signals.ShutdownException):
|
except (KeyboardInterrupt, signals.ShutdownException):
|
||||||
log.error("Aborting.")
|
log.error("Aborting.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
except (UserError, NoSuchService, ConfigurationError, ProjectError) as e:
|
except (UserError, NoSuchService, ConfigurationError,
|
||||||
|
ProjectError, OperationFailedError) as e:
|
||||||
log.error(e.msg)
|
log.error(e.msg)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
except BuildError as e:
|
except BuildError as e:
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
from __future__ import absolute_import
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
|
||||||
|
class OperationFailedError(Exception):
|
||||||
|
def __init__(self, reason):
|
||||||
|
self.msg = reason
|
|
@ -12,6 +12,7 @@ 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 OperationFailedError
|
||||||
from compose.utils import get_output_stream
|
from compose.utils import get_output_stream
|
||||||
|
|
||||||
|
|
||||||
|
@ -47,6 +48,9 @@ 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):
|
||||||
|
errors[get_name(obj)] = exception.msg
|
||||||
|
writer.write(get_name(obj), 'error')
|
||||||
elif isinstance(exception, UpstreamError):
|
elif isinstance(exception, UpstreamError):
|
||||||
writer.write(get_name(obj), 'error')
|
writer.write(get_name(obj), 'error')
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -27,6 +27,7 @@ from .const import LABEL_PROJECT
|
||||||
from .const import LABEL_SERVICE
|
from .const import LABEL_SERVICE
|
||||||
from .const import LABEL_VERSION
|
from .const import LABEL_VERSION
|
||||||
from .container import Container
|
from .container import Container
|
||||||
|
from .errors import OperationFailedError
|
||||||
from .parallel import parallel_execute
|
from .parallel import parallel_execute
|
||||||
from .parallel import parallel_start
|
from .parallel import parallel_start
|
||||||
from .progress_stream import stream_output
|
from .progress_stream import stream_output
|
||||||
|
@ -278,7 +279,11 @@ class Service(object):
|
||||||
if 'name' in container_options and not quiet:
|
if 'name' in container_options and not quiet:
|
||||||
log.info("Creating %s" % container_options['name'])
|
log.info("Creating %s" % container_options['name'])
|
||||||
|
|
||||||
return Container.create(self.client, **container_options)
|
try:
|
||||||
|
return Container.create(self.client, **container_options)
|
||||||
|
except APIError as ex:
|
||||||
|
raise OperationFailedError("Cannot create container for service %s: %s" %
|
||||||
|
(self.name, ex.explanation))
|
||||||
|
|
||||||
def ensure_image_exists(self, do_build=BuildAction.none):
|
def ensure_image_exists(self, do_build=BuildAction.none):
|
||||||
if self.can_be_built() and do_build == BuildAction.force:
|
if self.can_be_built() and do_build == BuildAction.force:
|
||||||
|
@ -448,7 +453,10 @@ class Service(object):
|
||||||
|
|
||||||
def start_container(self, container):
|
def start_container(self, container):
|
||||||
self.connect_container_to_networks(container)
|
self.connect_container_to_networks(container)
|
||||||
container.start()
|
try:
|
||||||
|
container.start()
|
||||||
|
except APIError as ex:
|
||||||
|
raise OperationFailedError("Cannot start service %s: %s" % (self.name, ex.explanation))
|
||||||
return container
|
return container
|
||||||
|
|
||||||
def connect_container_to_networks(self, container):
|
def connect_container_to_networks(self, container):
|
||||||
|
|
|
@ -738,7 +738,10 @@ class ServiceTest(DockerClientTestCase):
|
||||||
|
|
||||||
self.assertEqual(len(service.containers()), 1)
|
self.assertEqual(len(service.containers()), 1)
|
||||||
self.assertTrue(service.containers()[0].is_running)
|
self.assertTrue(service.containers()[0].is_running)
|
||||||
self.assertIn("ERROR: for composetest_web_2 Boom", mock_stderr.getvalue())
|
self.assertIn(
|
||||||
|
"ERROR: for composetest_web_2 Cannot create container for service web: Boom",
|
||||||
|
mock_stderr.getvalue()
|
||||||
|
)
|
||||||
|
|
||||||
def test_scale_with_unexpected_exception(self):
|
def test_scale_with_unexpected_exception(self):
|
||||||
"""Test that when scaling if the API returns an error, that is not of type
|
"""Test that when scaling if the API returns an error, that is not of type
|
||||||
|
|
Loading…
Reference in New Issue