Преглед на файлове

Merge pull request #1963 from shin-/1923-catch-timeout

Exit gracefully when requests encounter a ReadTimeout exception.
Aanand Prasad преди 10 години
родител
ревизия
10cb0c921a
променени са 5 файла, в които са добавени 27 реда и са изтрити 5 реда
  1. 9 2
      compose/cli/docker_client.py
  2. 8 0
      compose/cli/main.py
  3. 2 0
      compose/const.py
  4. 5 0
      docs/reference/overview.md
  5. 3 3
      tests/unit/cli/docker_client_test.py

+ 9 - 2
compose/cli/docker_client.py

@@ -1,9 +1,14 @@
+import logging
 import os
 import ssl
 
 from docker import Client
 from docker import tls
 
+from ..const import HTTP_TIMEOUT
+
+log = logging.getLogger(__name__)
+
 
 def docker_client():
     """
@@ -34,5 +39,7 @@ def docker_client():
             ca_cert=ca_cert,
         )
 
-    timeout = int(os.environ.get('DOCKER_CLIENT_TIMEOUT', 60))
-    return Client(base_url=base_url, tls=tls_config, version=api_version, timeout=timeout)
+    if 'DOCKER_CLIENT_TIMEOUT' in os.environ:
+        log.warn('The DOCKER_CLIENT_TIMEOUT environment variable is deprecated. Please use COMPOSE_HTTP_TIMEOUT instead.')
+
+    return Client(base_url=base_url, tls=tls_config, version=api_version, timeout=HTTP_TIMEOUT)

+ 8 - 0
compose/cli/main.py

@@ -10,11 +10,13 @@ from operator import attrgetter
 
 import dockerpty
 from docker.errors import APIError
+from requests.exceptions import ReadTimeout
 
 from .. import __version__
 from .. import legacy
 from ..config import parse_environment
 from ..const import DEFAULT_TIMEOUT
+from ..const import HTTP_TIMEOUT
 from ..progress_stream import StreamOutputError
 from ..project import ConfigurationError
 from ..project import NoSuchService
@@ -66,6 +68,12 @@ def main():
     except NeedsBuildError as e:
         log.error("Service '%s' needs to be built, but --no-build was passed." % e.service.name)
         sys.exit(1)
+    except ReadTimeout as e:
+        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)." % HTTP_TIMEOUT
+        )
 
 
 def setup_logging():

+ 2 - 0
compose/const.py

@@ -1,3 +1,4 @@
+import os
 
 DEFAULT_TIMEOUT = 10
 LABEL_CONTAINER_NUMBER = 'com.docker.compose.container-number'
@@ -6,3 +7,4 @@ LABEL_PROJECT = 'com.docker.compose.project'
 LABEL_SERVICE = 'com.docker.compose.service'
 LABEL_VERSION = 'com.docker.compose.version'
 LABEL_CONFIG_HASH = 'com.docker.compose.config-hash'
+HTTP_TIMEOUT = int(os.environ.get('COMPOSE_HTTP_TIMEOUT', os.environ.get('DOCKER_CLIENT_TIMEOUT', 60)))

+ 5 - 0
docs/reference/overview.md

@@ -44,6 +44,11 @@ the `docker` daemon.
 
 Configures the path to the `ca.pem`, `cert.pem`, and `key.pem` files used for TLS verification. Defaults to `~/.docker`.
 
+### COMPOSE\_HTTP\_TIMEOUT
+
+Configures the time (in seconds) a request to the Docker daemon is allowed to hang before Compose considers
+it failed. Defaults to 60 seconds.
+
 
 
 

+ 3 - 3
tests/unit/cli/docker_client_test.py

@@ -16,7 +16,7 @@ class DockerClientTestCase(unittest.TestCase):
             docker_client.docker_client()
 
     def test_docker_client_with_custom_timeout(self):
-        with mock.patch.dict(os.environ):
-            os.environ['DOCKER_CLIENT_TIMEOUT'] = timeout = "300"
+        timeout = 300
+        with mock.patch('compose.cli.docker_client.HTTP_TIMEOUT', 300):
             client = docker_client.docker_client()
-        self.assertEqual(client.timeout, int(timeout))
+            self.assertEqual(client.timeout, int(timeout))