Browse Source

Add support for TLS config command-line options

Signed-off-by: Joffrey F <[email protected]>
Joffrey F 9 năm trước cách đây
mục cha
commit
1ac33ea7e5
3 tập tin đã thay đổi với 58 bổ sung5 xóa
  1. 11 4
      compose/cli/command.py
  2. 40 1
      compose/cli/docker_client.py
  3. 7 0
      compose/cli/main.py

+ 11 - 4
compose/cli/command.py

@@ -12,6 +12,7 @@ from .. import config
 from ..const import API_VERSIONS
 from ..project import Project
 from .docker_client import docker_client
+from .docker_client import TLSArgs
 from .utils import get_version_info
 
 log = logging.getLogger(__name__)
@@ -23,6 +24,8 @@ def project_from_options(project_dir, options):
         get_config_path_from_options(options),
         project_name=options.get('--project-name'),
         verbose=options.get('--verbose'),
+        host=options.get('--host'),
+        tls_args=TLSArgs.from_options(options),
     )
 
 
@@ -37,8 +40,8 @@ def get_config_path_from_options(options):
     return None
 
 
-def get_client(verbose=False, version=None):
-    client = docker_client(version=version)
+def get_client(verbose=False, version=None, tls_args=None, host=None):
+    client = docker_client(version=version, tls_args=tls_args, host=host)
     if verbose:
         version_info = six.iteritems(client.version())
         log.info(get_version_info('full'))
@@ -49,7 +52,8 @@ def get_client(verbose=False, version=None):
     return client
 
 
-def get_project(project_dir, config_path=None, project_name=None, verbose=False):
+def get_project(project_dir, config_path=None, project_name=None, verbose=False,
+                host=None, tls_args=None):
     config_details = config.find(project_dir, config_path)
     project_name = get_project_name(config_details.working_dir, project_name)
     config_data = config.load(config_details)
@@ -57,7 +61,10 @@ def get_project(project_dir, config_path=None, project_name=None, verbose=False)
     api_version = os.environ.get(
         'COMPOSE_API_VERSION',
         API_VERSIONS[config_data.version])
-    client = get_client(verbose=verbose, version=api_version)
+    client = get_client(
+        verbose=verbose, version=api_version, tls_args=tls_args,
+        host=host
+    )
 
     return Project.from_config(project_name, config_data, client)
 

+ 40 - 1
compose/cli/docker_client.py

@@ -3,9 +3,11 @@ from __future__ import unicode_literals
 
 import logging
 import os
+from collections import namedtuple
 
 from docker import Client
 from docker.errors import TLSParameterError
+from docker.tls import TLSConfig
 from docker.utils import kwargs_from_env
 
 from ..const import HTTP_TIMEOUT
@@ -14,7 +16,24 @@ from .errors import UserError
 log = logging.getLogger(__name__)
 
 
-def docker_client(version=None):
+class TLSArgs(namedtuple('_TLSArgs', 'tls cert key ca_cert verify')):
+    @classmethod
+    def from_options(cls, options):
+        return cls(
+            tls=options.get('--tls', False),
+            ca_cert=options.get('--tlscacert'),
+            cert=options.get('--tlscert'),
+            key=options.get('--tlskey'),
+            verify=options.get('--tlsverify')
+        )
+
+    # def has_config(self):
+    #     return (
+    #         self.tls or self.ca_cert or self.cert or self.key or self.verify
+    #     )
+
+
+def docker_client(version=None, tls_args=None, host=None):
     """
     Returns a docker-py client configured using environment variables
     according to the same logic as the official Docker client.
@@ -31,6 +50,26 @@ def docker_client(version=None):
             "and DOCKER_CERT_PATH are set correctly.\n"
             "You might need to run `eval \"$(docker-machine env default)\"`")
 
+    if host:
+        kwargs['base_url'] = host
+    if tls_args and any(tls_args):
+        if tls_args.tls is True:
+            kwargs['tls'] = True
+        else:
+            client_cert = None
+            if tls_args.cert or tls_args.key:
+                client_cert = (tls_args.cert, tls_args.key)
+            try:
+                kwargs['tls'] = TLSConfig(
+                    client_cert=client_cert, verify=tls_args.verify,
+                    ca_cert=tls_args.ca_cert
+                )
+            except TLSParameterError as e:
+                raise UserError(
+                    "TLS configuration is invalid. Please double-check the "
+                    "TLS command-line arguments. ({0})".format(e)
+                )
+
     if version:
         kwargs['version'] = version
 

+ 7 - 0
compose/cli/main.py

@@ -149,6 +149,13 @@ class TopLevelCommand(object):
       -p, --project-name NAME   Specify an alternate project name (default: directory name)
       --verbose                 Show more output
       -v, --version             Print version and exit
+      -H, --host HOST           Daemon socket to connect to
+
+      --tls                     Use TLS; implied by --tlsverify
+      --tlsacert                Trust certs signed only by this CA
+      --tlscert                 Path to TLS certificate file
+      --tlskey                  Path to TLS key file
+      --tlsverify               Use TLS and verify the remote
 
     Commands:
       build              Build or rebuild services