| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 | from __future__ import absolute_importfrom __future__ import unicode_literalsimport contextlibimport loggingimport socketfrom distutils.spawn import find_executablefrom textwrap import dedentimport sixfrom docker.errors import APIErrorfrom requests.exceptions import ConnectionError as RequestsConnectionErrorfrom requests.exceptions import ReadTimeoutfrom requests.exceptions import SSLErrorfrom requests.packages.urllib3.exceptions import ReadTimeoutErrorfrom ..const import API_VERSION_TO_ENGINE_VERSIONfrom .utils import is_docker_for_mac_installedfrom .utils import is_macfrom .utils import is_ubuntufrom .utils import is_windowslog = logging.getLogger(__name__)class UserError(Exception):    def __init__(self, msg):        self.msg = dedent(msg).strip()    def __unicode__(self):        return self.msg    __str__ = __unicode__class ConnectionError(Exception):    pass@contextlib.contextmanagerdef handle_connection_errors(client):    try:        yield    except SSLError as e:        log.error('SSL error: %s' % e)        raise ConnectionError()    except RequestsConnectionError as e:        if e.args and isinstance(e.args[0], ReadTimeoutError):            log_timeout_error(client.timeout)            raise ConnectionError()        exit_with_error(get_conn_error_message(client.base_url))    except APIError as e:        log_api_error(e, client.api_version)        raise ConnectionError()    except (ReadTimeout, socket.timeout) as e:        log_timeout_error(client.timeout)        raise ConnectionError()    except Exception as e:        if is_windows():            import pywintypes            if isinstance(e, pywintypes.error):                log_windows_pipe_error(e)                raise ConnectionError()        raisedef log_windows_pipe_error(exc):    if exc.winerror == 232:  # https://github.com/docker/compose/issues/5005        log.error(            "The current Compose file version is not compatible with your engine version. "            "Please upgrade your Compose file to a more recent version, or set "            "a COMPOSE_API_VERSION in your environment."        )    else:        log.error(            "Windows named pipe error: {} (code: {})".format(exc.strerror, exc.winerror)        )def log_timeout_error(timeout):    log.error(        "An HTTP request took too long to complete. Retry with --verbose to "        "obtain debug information.\n"        "If you encounter this issue regularly because of slow network "        "conditions, consider setting COMPOSE_HTTP_TIMEOUT to a higher "        "value (current value: %s)." % timeout)def log_api_error(e, client_version):    explanation = e.explanation    if isinstance(explanation, six.binary_type):        explanation = explanation.decode('utf-8')    if 'client is newer than server' not in explanation:        log.error(explanation)        return    version = API_VERSION_TO_ENGINE_VERSION.get(client_version)    if not version:        # They've set a custom API version        log.error(explanation)        return    log.error(        "The Docker Engine version is less than the minimum required by "        "Compose. Your current project requires a Docker Engine of "        "version {version} or greater.".format(version=version))def exit_with_error(msg):    log.error(dedent(msg).strip())    raise ConnectionError()def get_conn_error_message(url):    if find_executable('docker') is None:        return docker_not_found_msg("Couldn't connect to Docker daemon.")    if is_docker_for_mac_installed():        return conn_error_docker_for_mac    if find_executable('docker-machine') is not None:        return conn_error_docker_machine    return conn_error_generic.format(url=url)def docker_not_found_msg(problem):    return "{} You might need to install Docker:\n\n{}".format(        problem, docker_install_url())def docker_install_url():    if is_mac():        return docker_install_url_mac    elif is_ubuntu():        return docker_install_url_ubuntu    elif is_windows():        return docker_install_url_windows    else:        return docker_install_url_genericdocker_install_url_mac = "https://docs.docker.com/engine/installation/mac/"docker_install_url_ubuntu = "https://docs.docker.com/engine/installation/ubuntulinux/"docker_install_url_windows = "https://docs.docker.com/engine/installation/windows/"docker_install_url_generic = "https://docs.docker.com/engine/installation/"conn_error_docker_machine = """    Couldn't connect to Docker daemon - you might need to run `docker-machine start default`."""conn_error_docker_for_mac = """    Couldn't connect to Docker daemon. You might need to start Docker for Mac."""conn_error_generic = """    Couldn't connect to Docker daemon at {url} - is it running?    If it's at a non-standard location, specify the URL with the DOCKER_HOST environment variable."""
 |