mirror of https://github.com/docker/docs.git
Merge pull request #2142 from dnephin/fix_error_cant_connect
Fix error when compose can't connect to docker
This commit is contained in:
commit
fda615008c
|
@ -1,6 +1,7 @@
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import contextlib
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
@ -16,7 +17,6 @@ from .. import config
|
||||||
from ..project import Project
|
from ..project import Project
|
||||||
from ..service import ConfigError
|
from ..service import ConfigError
|
||||||
from .docker_client import docker_client
|
from .docker_client import docker_client
|
||||||
from .docopt_command import DocoptCommand
|
|
||||||
from .utils import call_silently
|
from .utils import call_silently
|
||||||
from .utils import is_mac
|
from .utils import is_mac
|
||||||
from .utils import is_ubuntu
|
from .utils import is_ubuntu
|
||||||
|
@ -24,40 +24,32 @@ from .utils import is_ubuntu
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Command(DocoptCommand):
|
@contextlib.contextmanager
|
||||||
base_dir = '.'
|
def friendly_error_message():
|
||||||
|
try:
|
||||||
def dispatch(self, *args, **kwargs):
|
yield
|
||||||
try:
|
except SSLError as e:
|
||||||
super(Command, self).dispatch(*args, **kwargs)
|
raise errors.UserError('SSL error: %s' % e)
|
||||||
except SSLError as e:
|
except ConnectionError:
|
||||||
raise errors.UserError('SSL error: %s' % e)
|
if call_silently(['which', 'docker']) != 0:
|
||||||
except ConnectionError:
|
if is_mac():
|
||||||
if call_silently(['which', 'docker']) != 0:
|
raise errors.DockerNotFoundMac()
|
||||||
if is_mac():
|
elif is_ubuntu():
|
||||||
raise errors.DockerNotFoundMac()
|
raise errors.DockerNotFoundUbuntu()
|
||||||
elif is_ubuntu():
|
|
||||||
raise errors.DockerNotFoundUbuntu()
|
|
||||||
else:
|
|
||||||
raise errors.DockerNotFoundGeneric()
|
|
||||||
elif call_silently(['which', 'boot2docker']) == 0:
|
|
||||||
raise errors.ConnectionErrorDockerMachine()
|
|
||||||
else:
|
else:
|
||||||
raise errors.ConnectionErrorGeneric(self.get_client().base_url)
|
raise errors.DockerNotFoundGeneric()
|
||||||
|
elif call_silently(['which', 'docker-machine']) == 0:
|
||||||
|
raise errors.ConnectionErrorDockerMachine()
|
||||||
|
else:
|
||||||
|
raise errors.ConnectionErrorGeneric(get_client().base_url)
|
||||||
|
|
||||||
def perform_command(self, options, handler, command_options):
|
|
||||||
if options['COMMAND'] in ('help', 'version'):
|
|
||||||
# Skip looking up the compose file.
|
|
||||||
handler(None, command_options)
|
|
||||||
return
|
|
||||||
|
|
||||||
project = get_project(
|
def project_from_options(base_dir, options):
|
||||||
self.base_dir,
|
return get_project(
|
||||||
get_config_path(options.get('--file')),
|
base_dir,
|
||||||
project_name=options.get('--project-name'),
|
get_config_path(options.get('--file')),
|
||||||
verbose=options.get('--verbose'))
|
project_name=options.get('--project-name'),
|
||||||
|
verbose=options.get('--verbose'))
|
||||||
handler(project, command_options)
|
|
||||||
|
|
||||||
|
|
||||||
def get_config_path(file_option):
|
def get_config_path(file_option):
|
||||||
|
|
|
@ -25,9 +25,6 @@ class DocoptCommand(object):
|
||||||
def dispatch(self, argv, global_options):
|
def dispatch(self, argv, global_options):
|
||||||
self.perform_command(*self.parse(argv, global_options))
|
self.perform_command(*self.parse(argv, global_options))
|
||||||
|
|
||||||
def perform_command(self, options, handler, command_options):
|
|
||||||
handler(command_options)
|
|
||||||
|
|
||||||
def parse(self, argv, global_options):
|
def parse(self, argv, global_options):
|
||||||
options = docopt_full_help(getdoc(self), argv, **self.docopt_options())
|
options = docopt_full_help(getdoc(self), argv, **self.docopt_options())
|
||||||
command = options['COMMAND']
|
command = options['COMMAND']
|
||||||
|
|
|
@ -23,7 +23,9 @@ from ..project import NoSuchService
|
||||||
from ..service import BuildError
|
from ..service import BuildError
|
||||||
from ..service import ConvergenceStrategy
|
from ..service import ConvergenceStrategy
|
||||||
from ..service import NeedsBuildError
|
from ..service import NeedsBuildError
|
||||||
from .command import Command
|
from .command import friendly_error_message
|
||||||
|
from .command import project_from_options
|
||||||
|
from .docopt_command import DocoptCommand
|
||||||
from .docopt_command import NoSuchCommand
|
from .docopt_command import NoSuchCommand
|
||||||
from .errors import UserError
|
from .errors import UserError
|
||||||
from .formatter import Formatter
|
from .formatter import Formatter
|
||||||
|
@ -89,6 +91,15 @@ def setup_logging():
|
||||||
logging.getLogger("requests").propagate = False
|
logging.getLogger("requests").propagate = False
|
||||||
|
|
||||||
|
|
||||||
|
def setup_console_handler(verbose):
|
||||||
|
if verbose:
|
||||||
|
console_handler.setFormatter(logging.Formatter('%(name)s.%(funcName)s: %(message)s'))
|
||||||
|
console_handler.setLevel(logging.DEBUG)
|
||||||
|
else:
|
||||||
|
console_handler.setFormatter(logging.Formatter())
|
||||||
|
console_handler.setLevel(logging.INFO)
|
||||||
|
|
||||||
|
|
||||||
# stolen from docopt master
|
# stolen from docopt master
|
||||||
def parse_doc_section(name, source):
|
def parse_doc_section(name, source):
|
||||||
pattern = re.compile('^([^\n]*' + name + '[^\n]*\n?(?:[ \t].*?(?:\n|$))*)',
|
pattern = re.compile('^([^\n]*' + name + '[^\n]*\n?(?:[ \t].*?(?:\n|$))*)',
|
||||||
|
@ -96,7 +107,7 @@ def parse_doc_section(name, source):
|
||||||
return [s.strip() for s in pattern.findall(source)]
|
return [s.strip() for s in pattern.findall(source)]
|
||||||
|
|
||||||
|
|
||||||
class TopLevelCommand(Command):
|
class TopLevelCommand(DocoptCommand):
|
||||||
"""Define and run multi-container applications with Docker.
|
"""Define and run multi-container applications with Docker.
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
|
@ -130,20 +141,24 @@ class TopLevelCommand(Command):
|
||||||
version Show the Docker-Compose version information
|
version Show the Docker-Compose version information
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
base_dir = '.'
|
||||||
|
|
||||||
def docopt_options(self):
|
def docopt_options(self):
|
||||||
options = super(TopLevelCommand, self).docopt_options()
|
options = super(TopLevelCommand, self).docopt_options()
|
||||||
options['version'] = get_version_info('compose')
|
options['version'] = get_version_info('compose')
|
||||||
return options
|
return options
|
||||||
|
|
||||||
def perform_command(self, options, *args, **kwargs):
|
def perform_command(self, options, handler, command_options):
|
||||||
if options.get('--verbose'):
|
setup_console_handler(options.get('--verbose'))
|
||||||
console_handler.setFormatter(logging.Formatter('%(name)s.%(funcName)s: %(message)s'))
|
|
||||||
console_handler.setLevel(logging.DEBUG)
|
|
||||||
else:
|
|
||||||
console_handler.setFormatter(logging.Formatter())
|
|
||||||
console_handler.setLevel(logging.INFO)
|
|
||||||
|
|
||||||
return super(TopLevelCommand, self).perform_command(options, *args, **kwargs)
|
if options['COMMAND'] in ('help', 'version'):
|
||||||
|
# Skip looking up the compose file.
|
||||||
|
handler(None, command_options)
|
||||||
|
return
|
||||||
|
|
||||||
|
project = project_from_options(self.base_dir, options)
|
||||||
|
with friendly_error_message():
|
||||||
|
handler(project, command_options)
|
||||||
|
|
||||||
def build(self, project, options):
|
def build(self, project, options):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from requests.exceptions import ConnectionError
|
||||||
|
|
||||||
|
from compose.cli import errors
|
||||||
|
from compose.cli.command import friendly_error_message
|
||||||
|
from tests import mock
|
||||||
|
from tests import unittest
|
||||||
|
|
||||||
|
|
||||||
|
class FriendlyErrorMessageTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_dispatch_generic_connection_error(self):
|
||||||
|
with pytest.raises(errors.ConnectionErrorGeneric):
|
||||||
|
with mock.patch(
|
||||||
|
'compose.cli.command.call_silently',
|
||||||
|
autospec=True,
|
||||||
|
side_effect=[0, 1]
|
||||||
|
):
|
||||||
|
with friendly_error_message():
|
||||||
|
raise ConnectionError()
|
Loading…
Reference in New Issue