123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- from __future__ import absolute_import
- from __future__ import unicode_literals
- import contextlib
- import logging
- import socket
- from textwrap import dedent
- from docker.errors import APIError
- from requests.exceptions import ConnectionError as RequestsConnectionError
- from requests.exceptions import ReadTimeout
- from requests.exceptions import SSLError
- from requests.packages.urllib3.exceptions import ReadTimeoutError
- from ..const import API_VERSION_TO_ENGINE_VERSION
- from .utils import call_silently
- from .utils import is_docker_for_mac_installed
- from .utils import is_mac
- from .utils import is_ubuntu
- log = 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.contextmanager
- def 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()
- raise ConnectionError()
- 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):
- if b'client is newer than server' not in e.explanation:
- log.error(e.explanation)
- return
- version = API_VERSION_TO_ENGINE_VERSION.get(client_version)
- if not version:
- # They've set a custom API version
- log.error(e.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 call_silently(['which', 'docker']) != 0:
- if is_mac():
- return docker_not_found_mac
- if is_ubuntu():
- return docker_not_found_ubuntu
- return docker_not_found_generic
- if is_docker_for_mac_installed():
- return conn_error_docker_for_mac
- if call_silently(['which', 'docker-machine']) == 0:
- return conn_error_docker_machine
- return conn_error_generic.format(url=url)
- docker_not_found_mac = """
- Couldn't connect to Docker daemon. You might need to install Docker:
- https://docs.docker.com/engine/installation/mac/
- """
- docker_not_found_ubuntu = """
- Couldn't connect to Docker daemon. You might need to install Docker:
- https://docs.docker.com/engine/installation/ubuntulinux/
- """
- docker_not_found_generic = """
- Couldn't connect to Docker daemon. You might need to install Docker:
- 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.
- """
|