From 1ac33ea7e5f5c2c4d4facd5b52143f0a962515bc Mon Sep 17 00:00:00 2001 From: Joffrey F Date: Tue, 15 Mar 2016 14:19:25 -0700 Subject: [PATCH] Add support for TLS config command-line options Signed-off-by: Joffrey F --- compose/cli/command.py | 15 +++++++++---- compose/cli/docker_client.py | 41 +++++++++++++++++++++++++++++++++++- compose/cli/main.py | 7 ++++++ 3 files changed, 58 insertions(+), 5 deletions(-) diff --git a/compose/cli/command.py b/compose/cli/command.py index 55f6df01a..730cd1153 100644 --- a/compose/cli/command.py +++ b/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) diff --git a/compose/cli/docker_client.py b/compose/cli/docker_client.py index 9e79fe777..cff28f8c7 100644 --- a/compose/cli/docker_client.py +++ b/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 diff --git a/compose/cli/main.py b/compose/cli/main.py index a978579c0..17c2ac45f 100644 --- a/compose/cli/main.py +++ b/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