Преглед изворни кода

TLS support, with same env vars as docker client

Thanks to @jkingyens for the bulk of the work.

Signed-off-by: Aanand Prasad <[email protected]>
Aanand Prasad пре 11 година
родитељ
комит
b318585f3c
4 измењених фајлова са 42 додато и 11 уклоњено
  1. 6 4
      fig/cli/command.py
  2. 34 0
      fig/cli/docker_client.py
  3. 0 4
      fig/cli/utils.py
  4. 2 3
      tests/integration/testcases.py

+ 6 - 4
fig/cli/command.py

@@ -1,7 +1,6 @@
 from __future__ import unicode_literals
 from __future__ import absolute_import
-from docker import Client
-from requests.exceptions import ConnectionError
+from requests.exceptions import ConnectionError, SSLError
 import errno
 import logging
 import os
@@ -12,7 +11,8 @@ import six
 from ..project import Project
 from ..service import ConfigError
 from .docopt_command import DocoptCommand
-from .utils import docker_url, call_silently, is_mac, is_ubuntu
+from .utils import call_silently, is_mac, is_ubuntu
+from .docker_client import docker_client
 from . import verbose_proxy
 from . import errors
 from .. import __version__
@@ -26,6 +26,8 @@ class Command(DocoptCommand):
     def dispatch(self, *args, **kwargs):
         try:
             super(Command, self).dispatch(*args, **kwargs)
+        except SSLError, e:
+            raise errors.UserError('SSL error: %s' % e)
         except ConnectionError:
             if call_silently(['which', 'docker']) != 0:
                 if is_mac():
@@ -49,7 +51,7 @@ class Command(DocoptCommand):
         handler(project, command_options)
 
     def get_client(self, verbose=False):
-        client = Client(docker_url())
+        client = docker_client()
         if verbose:
             version_info = six.iteritems(client.version())
             log.info("Fig version %s", __version__)

+ 34 - 0
fig/cli/docker_client.py

@@ -0,0 +1,34 @@
+from docker import Client
+from docker import tls
+import ssl
+import os
+
+
+def docker_client():
+    """
+    Returns a docker-py client configured using environment variables
+    according to the same logic as the official Docker client.
+    """
+    cert_path = os.environ.get('DOCKER_CERT_PATH', '')
+    if cert_path == '':
+        cert_path = os.path.join(os.environ.get('HOME'), '.docker')
+
+    base_url = os.environ.get('DOCKER_HOST')
+    tls_config = None
+
+    if os.environ.get('DOCKER_TLS_VERIFY', '') != '':
+        parts = base_url.split('://', 1)
+        base_url = '%s://%s' % ('https', parts[1])
+
+        client_cert = (os.path.join(cert_path, 'cert.pem'), os.path.join(cert_path, 'key.pem'))
+        ca_cert = os.path.join(cert_path, 'ca.pem')
+
+        tls_config = tls.TLSConfig(
+            ssl_version=ssl.PROTOCOL_TLSv1,
+            verify=True,
+            assert_hostname=False,
+            client_cert=client_cert,
+            ca_cert=ca_cert,
+        )
+
+    return Client(base_url=base_url, tls=tls_config)

+ 0 - 4
fig/cli/utils.py

@@ -62,10 +62,6 @@ def mkdir(path, permissions=0o700):
     return path
 
 
-def docker_url():
-    return os.environ.get('DOCKER_HOST')
-
-
 def split_buffer(reader, separator):
     """
     Given a generator which yields strings and a separator string,

+ 2 - 3
tests/integration/testcases.py

@@ -1,8 +1,7 @@
 from __future__ import unicode_literals
 from __future__ import absolute_import
-from docker import Client
 from fig.service import Service
-from fig.cli.utils import docker_url
+from fig.cli.docker_client import docker_client
 from fig.progress_stream import stream_output
 from .. import unittest
 
@@ -10,7 +9,7 @@ from .. import unittest
 class DockerClientTestCase(unittest.TestCase):
     @classmethod
     def setUpClass(cls):
-        cls.client = Client(docker_url())
+        cls.client = docker_client()
 
     def setUp(self):
         for c in self.client.containers(all=True):