From 22249add84831a02976f6c98020f05eb7418b287 Mon Sep 17 00:00:00 2001 From: Joffrey F Date: Mon, 6 Jun 2016 15:48:47 -0700 Subject: [PATCH 01/17] Use newer version of PyInstaller to fix prelinking issues Signed-off-by: Joffrey F --- requirements-build.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-build.txt b/requirements-build.txt index 3f1dbd75..27f610ca 100644 --- a/requirements-build.txt +++ b/requirements-build.txt @@ -1 +1 @@ -pyinstaller==3.1.1 +pyinstaller==3.2.1 From 84774cacd210bb176c2daf73106c7dc849a6a0d7 Mon Sep 17 00:00:00 2001 From: Joffrey F Date: Mon, 30 Jan 2017 15:16:09 -0800 Subject: [PATCH 02/17] Upgrade python and pip versions in Dockerfile Add libbz2 dependency Signed-off-by: Joffrey F --- Dockerfile | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/Dockerfile b/Dockerfile index 63fac3eb..a03e1510 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,6 +13,7 @@ RUN set -ex; \ ca-certificates \ curl \ libsqlite3-dev \ + libbz2-dev \ ; \ rm -rf /var/lib/apt/lists/* @@ -20,40 +21,32 @@ RUN curl https://get.docker.com/builds/Linux/x86_64/docker-1.8.3 \ -o /usr/local/bin/docker && \ chmod +x /usr/local/bin/docker -# Build Python 2.7.9 from source +# Build Python 2.7.13 from source RUN set -ex; \ - curl -L https://www.python.org/ftp/python/2.7.9/Python-2.7.9.tgz | tar -xz; \ - cd Python-2.7.9; \ + curl -L https://www.python.org/ftp/python/2.7.13/Python-2.7.13.tgz | tar -xz; \ + cd Python-2.7.13; \ ./configure --enable-shared; \ make; \ make install; \ cd ..; \ - rm -rf /Python-2.7.9 + rm -rf /Python-2.7.13 # Build python 3.4 from source RUN set -ex; \ - curl -L https://www.python.org/ftp/python/3.4.3/Python-3.4.3.tgz | tar -xz; \ - cd Python-3.4.3; \ + curl -L https://www.python.org/ftp/python/3.4.6/Python-3.4.6.tgz | tar -xz; \ + cd Python-3.4.6; \ ./configure --enable-shared; \ make; \ make install; \ cd ..; \ - rm -rf /Python-3.4.3 + rm -rf /Python-3.4.6 # Make libpython findable ENV LD_LIBRARY_PATH /usr/local/lib -# Install setuptools -RUN set -ex; \ - curl -L https://bootstrap.pypa.io/ez_setup.py | python - # Install pip RUN set -ex; \ - curl -L https://pypi.python.org/packages/source/p/pip/pip-8.1.1.tar.gz | tar -xz; \ - cd pip-8.1.1; \ - python setup.py install; \ - cd ..; \ - rm -rf pip-8.1.1 + curl -L https://bootstrap.pypa.io/get-pip.py | python # Python3 requires a valid locale RUN echo "en_US.UTF-8 UTF-8" > /etc/locale.gen && locale-gen From a3a9d8944a413897ae1f0305d16d6d1071487ad6 Mon Sep 17 00:00:00 2001 From: Kevin Jing Qiu Date: Thu, 26 Jan 2017 14:23:12 -0500 Subject: [PATCH 03/17] Close the open file handle using context manager Signed-off-by: Kevin Jing Qiu --- compose/config/environment.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/compose/config/environment.py b/compose/config/environment.py index 7b926930..4ba228c8 100644 --- a/compose/config/environment.py +++ b/compose/config/environment.py @@ -2,6 +2,7 @@ from __future__ import absolute_import from __future__ import unicode_literals import codecs +import contextlib import logging import os @@ -31,11 +32,12 @@ def env_vars_from_file(filename): elif not os.path.isfile(filename): raise ConfigurationError("%s is not a file." % (filename)) env = {} - for line in codecs.open(filename, 'r', 'utf-8'): - line = line.strip() - if line and not line.startswith('#'): - k, v = split_env(line) - env[k] = v + with contextlib.closing(codecs.open(filename, 'r', 'utf-8')) as fileobj: + for line in fileobj: + line = line.strip() + if line and not line.startswith('#'): + k, v = split_env(line) + env[k] = v return env From b392b6e12ed724ce39e0e65fd5582b70c47803af Mon Sep 17 00:00:00 2001 From: fate-grand-order Date: Tue, 7 Feb 2017 15:59:34 +0800 Subject: [PATCH 04/17] fix typo in CHANGELOG.md Signed-off-by: fate-grand-order --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c645ca2..e969b453 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -525,7 +525,7 @@ Bug Fixes: if at least one container is using the network. - When printings logs during `up` or `logs`, flush the output buffer after - each line to prevent buffering issues from hideing logs. + each line to prevent buffering issues from hiding logs. - Recreate a container if one of its dependencies is being created. Previously a container was only recreated if it's dependencies already From f0835268296111cac54faa8701b7aba751c0a239 Mon Sep 17 00:00:00 2001 From: "Aaron.L.Xu" Date: Wed, 8 Feb 2017 18:50:14 +0800 Subject: [PATCH 05/17] referencing right segment of code Signed-off-by: Aaron.L.Xu --- compose/bundle.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compose/bundle.py b/compose/bundle.py index 854cc799..505ce91f 100644 --- a/compose/bundle.py +++ b/compose/bundle.py @@ -202,7 +202,7 @@ def convert_service_to_bundle(name, service_dict, image_digest): return container_config -# See https://github.com/docker/swarmkit/blob//agent/exec/container/container.go#L95 +# See https://github.com/docker/swarmkit/blob/agent/exec/container/container.go#L95 def set_command_and_args(config, entrypoint, command): if isinstance(entrypoint, six.string_types): entrypoint = split_command(entrypoint) From 979a0d53f7e989f13dc77865c7d1f4775f97319e Mon Sep 17 00:00:00 2001 From: Joffrey F Date: Fri, 3 Feb 2017 15:26:34 -0800 Subject: [PATCH 06/17] Bump 1.11.0-rc1 Signed-off-by: Joffrey F --- compose/__init__.py | 2 +- script/run/run.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compose/__init__.py b/compose/__init__.py index 38417836..ae8d759d 100644 --- a/compose/__init__.py +++ b/compose/__init__.py @@ -1,4 +1,4 @@ from __future__ import absolute_import from __future__ import unicode_literals -__version__ = '1.11.0dev' +__version__ = '1.11.0-rc1' diff --git a/script/run/run.sh b/script/run/run.sh index 5872b081..9de11d5f 100755 --- a/script/run/run.sh +++ b/script/run/run.sh @@ -15,7 +15,7 @@ set -e -VERSION="1.8.0" +VERSION="1.11.0-rc1" IMAGE="docker/compose:$VERSION" From 01d1895a350c445eab9deb37d1cd8b6fe3328b47 Mon Sep 17 00:00:00 2001 From: Joffrey F Date: Wed, 8 Feb 2017 11:30:29 -0800 Subject: [PATCH 07/17] Bump 1.11.0 Signed-off-by: Joffrey F --- compose/__init__.py | 2 +- script/run/run.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compose/__init__.py b/compose/__init__.py index ae8d759d..d7468af2 100644 --- a/compose/__init__.py +++ b/compose/__init__.py @@ -1,4 +1,4 @@ from __future__ import absolute_import from __future__ import unicode_literals -__version__ = '1.11.0-rc1' +__version__ = '1.11.0' diff --git a/script/run/run.sh b/script/run/run.sh index 9de11d5f..b45630f0 100755 --- a/script/run/run.sh +++ b/script/run/run.sh @@ -15,7 +15,7 @@ set -e -VERSION="1.11.0-rc1" +VERSION="1.11.0" IMAGE="docker/compose:$VERSION" From 2cd6cb9a47b2d00cfad7d49a26641020f7f8a66a Mon Sep 17 00:00:00 2001 From: Joffrey F Date: Mon, 30 Jan 2017 16:20:59 -0800 Subject: [PATCH 08/17] Bump 1.10.1 Signed-off-by: Joffrey F --- CHANGELOG.md | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6699f880..d0681e8a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,53 @@ Change log ========== +1.11.0 (2017-02-08) +------------------- + +### New Features + +#### Compose file version 3.1 + +- Introduced version 3.1 of the `docker-compose.yml` specification. This + version requires Docker Engine 1.13.0 or above. It introduces support + for secrets. See the documentation for more information + +#### Compose file version 2.0 and up + +- Introduced the `docker-compose top` command that displays processes running + for the different services managed by Compose. + +### Bugfixes + +- Fixed a bug where extending a service defining a healthcheck dictionary + would cause `docker-compose` to error out. + +- Fixed an issue where the `pid` entry in a service definition was being + ignored when using multiple Compose files. + +1.10.1 (2017-02-01) +------------------ + +### Bugfixes + +- Fixed an issue where presence of older versions of the docker-py + package would cause unexpected crashes while running Compose + +- Fixed an issue where healthcheck dependencies would be lost when + using multiple compose files for a project + +- Fixed a few issues that made the output of the `config` command + invalid + +- Fixed an issue where adding volume labels to v3 Compose files would + result in an error + +- Fixed an issue on Windows where build context paths containing unicode + characters were being improperly encoded + +- Fixed a bug where Compose would occasionally crash while streaming logs + when containers would stop or restart + 1.10.0 (2017-01-18) ------------------- From fc7b74d7f900d6e94ebd46a05cdcadcfd1f7d407 Mon Sep 17 00:00:00 2001 From: Joffrey F Date: Wed, 8 Feb 2017 13:47:08 -0800 Subject: [PATCH 09/17] Bump to next dev version Signed-off-by: Joffrey F --- compose/__init__.py | 2 +- script/run/run.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compose/__init__.py b/compose/__init__.py index d7468af2..b2ca86f8 100644 --- a/compose/__init__.py +++ b/compose/__init__.py @@ -1,4 +1,4 @@ from __future__ import absolute_import from __future__ import unicode_literals -__version__ = '1.11.0' +__version__ = '1.12.0dev' diff --git a/script/run/run.sh b/script/run/run.sh index b45630f0..4e173894 100755 --- a/script/run/run.sh +++ b/script/run/run.sh @@ -15,7 +15,7 @@ set -e -VERSION="1.11.0" +VERSION="1.12.0dev" IMAGE="docker/compose:$VERSION" From 47e4442722373ce43f7878ee98fe9aceb1b9f177 Mon Sep 17 00:00:00 2001 From: kevinetc123 Date: Thu, 9 Feb 2017 19:10:26 +0800 Subject: [PATCH 10/17] fix typo in project.py Signed-off-by: kevinetc123 --- compose/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compose/project.py b/compose/project.py index 0330ab80..133071e7 100644 --- a/compose/project.py +++ b/compose/project.py @@ -365,7 +365,7 @@ class Project(object): # TODO: get labels from the API v1.22 , see github issue 2618 try: - # this can fail if the conatiner has been removed + # this can fail if the container has been removed container = Container.from_id(self.client, event['id']) except APIError: continue From c092fa37de820e7d6dd20b30d2c4dec28f214dd3 Mon Sep 17 00:00:00 2001 From: Daniel Nephin Date: Thu, 9 Feb 2017 10:27:06 -0500 Subject: [PATCH 11/17] Fix version 3.1 Signed-off-by: Daniel Nephin --- compose/config/config.py | 11 ++++------- docker-compose.spec | 5 +++++ tests/unit/config/config_test.py | 4 ++++ 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/compose/config/config.py b/compose/config/config.py index ae85674b..09a717be 100644 --- a/compose/config/config.py +++ b/compose/config/config.py @@ -186,11 +186,6 @@ class ConfigFile(namedtuple('_ConfigFile', 'filename config')): if version == '3': version = V3_0 - if version not in (V2_0, V2_1, V3_0): - raise ConfigurationError( - 'Version in "{}" is unsupported. {}' - .format(self.filename, VERSION_EXPLANATION)) - return version def get_service(self, name): @@ -479,7 +474,7 @@ def process_config_file(config_file, environment, service_name=None): 'service', environment) - if config_file.version in (V2_0, V2_1, V3_0): + if config_file.version in (V2_0, V2_1, V3_0, V3_1): processed_config = dict(config_file.config) processed_config['services'] = services processed_config['volumes'] = interpolate_config_section( @@ -495,7 +490,9 @@ def process_config_file(config_file, environment, service_name=None): elif config_file.version == V1: processed_config = services else: - raise Exception("Unsupported version: {}".format(repr(config_file.version))) + raise ConfigurationError( + 'Version in "{}" is unsupported. {}' + .format(config_file.filename, VERSION_EXPLANATION)) config_file = config_file._replace(config=processed_config) validate_against_config_schema(config_file) diff --git a/docker-compose.spec b/docker-compose.spec index ec5a2039..ef0e2593 100644 --- a/docker-compose.spec +++ b/docker-compose.spec @@ -37,6 +37,11 @@ exe = EXE(pyz, 'compose/config/config_schema_v3.0.json', 'DATA' ), + ( + 'compose/config/config_schema_v3.1.json', + 'compose/config/config_schema_v3.1.json', + 'DATA' + ), ( 'compose/GITSHA', 'compose/GITSHA', diff --git a/tests/unit/config/config_test.py b/tests/unit/config/config_test.py index 666b21f2..ef57bb57 100644 --- a/tests/unit/config/config_test.py +++ b/tests/unit/config/config_test.py @@ -19,6 +19,7 @@ from compose.config.config import V1 from compose.config.config import V2_0 from compose.config.config import V2_1 from compose.config.config import V3_0 +from compose.config.config import V3_1 from compose.config.environment import Environment from compose.config.errors import ConfigurationError from compose.config.errors import VERSION_EXPLANATION @@ -168,6 +169,9 @@ class ConfigTest(unittest.TestCase): cfg = config.load(build_config_details({'version': version})) assert cfg.version == V3_0 + cfg = config.load(build_config_details({'version': '3.1'})) + assert cfg.version == V3_1 + def test_v1_file_version(self): cfg = config.load(build_config_details({'web': {'image': 'busybox'}})) assert cfg.version == V1 From dc5b3f3b3eb53ce747003089c8ae5ff21f4b1f70 Mon Sep 17 00:00:00 2001 From: Daniel Nephin Date: Fri, 10 Feb 2017 17:05:33 -0500 Subject: [PATCH 12/17] Fix secrets config. Signed-off-by: Daniel Nephin --- compose/config/config.py | 5 ++ compose/config/types.py | 8 +++ setup.py | 10 ++-- tests/unit/config/config_test.py | 86 ++++++++++++++++++++++++++++++++ 4 files changed, 103 insertions(+), 6 deletions(-) diff --git a/compose/config/config.py b/compose/config/config.py index 09a717be..4c9cf423 100644 --- a/compose/config/config.py +++ b/compose/config/config.py @@ -763,6 +763,11 @@ def finalize_service(service_config, service_names, version, environment): if 'restart' in service_dict: service_dict['restart'] = parse_restart_spec(service_dict['restart']) + if 'secrets' in service_dict: + service_dict['secrets'] = [ + types.ServiceSecret.parse(s) for s in service_dict['secrets'] + ] + normalize_build(service_dict, service_config.working_dir, environment) service_dict['name'] = service_config.name diff --git a/compose/config/types.py b/compose/config/types.py index 17d5c8b3..f86c0319 100644 --- a/compose/config/types.py +++ b/compose/config/types.py @@ -253,3 +253,11 @@ class ServiceSecret(namedtuple('_ServiceSecret', 'source target uid gid mode')): @property def merge_field(self): return self.source + + def repr(self): + return dict( + source=self.source, + target=self.target, + uid=self.uid, + gid=self.gid, + mode=self.mode) diff --git a/setup.py b/setup.py index 0b1d4e08..eafbc356 100644 --- a/setup.py +++ b/setup.py @@ -1,10 +1,10 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- from __future__ import absolute_import +from __future__ import print_function from __future__ import unicode_literals import codecs -import logging import os import re import sys @@ -64,11 +64,9 @@ try: for key, value in extras_require.items(): if key.startswith(':') and pkg_resources.evaluate_marker(key[1:]): install_requires.extend(value) -except Exception: - logging.getLogger(__name__).exception( - 'Failed to compute platform dependencies. All dependencies will be ' - 'installed as a result.' - ) +except Exception as e: + print("Failed to compute platform dependencies: {}. ".format(e) + + "All dependencies will be installed as a result.", file=sys.stderr) for key, value in extras_require.items(): if key.startswith(':'): install_requires.extend(value) diff --git a/tests/unit/config/config_test.py b/tests/unit/config/config_test.py index ef57bb57..d4d1ad2c 100644 --- a/tests/unit/config/config_test.py +++ b/tests/unit/config/config_test.py @@ -13,6 +13,7 @@ import pytest from ...helpers import build_config_details from compose.config import config +from compose.config import types from compose.config.config import resolve_build_args from compose.config.config import resolve_environment from compose.config.config import V1 @@ -1849,6 +1850,91 @@ class ConfigTest(unittest.TestCase): config.load(config_details) assert 'has neither an image nor a build context' in exc.exconly() + def test_load_secrets(self): + base_file = config.ConfigFile( + 'base.yaml', + { + 'version': '3.1', + 'services': { + 'web': { + 'image': 'example/web', + 'secrets': [ + 'one', + { + 'source': 'source', + 'target': 'target', + 'uid': '100', + 'gid': '200', + 'mode': 0o777, + }, + ], + }, + }, + 'secrets': { + 'one': {'file': 'secret.txt'}, + }, + }) + details = config.ConfigDetails('.', [base_file]) + service_dicts = config.load(details).services + expected = [ + { + 'name': 'web', + 'image': 'example/web', + 'secrets': [ + types.ServiceSecret('one', None, None, None, None), + types.ServiceSecret('source', 'target', '100', '200', 0o777), + ], + }, + ] + assert service_sort(service_dicts) == service_sort(expected) + + def test_load_secrets_multi_file(self): + base_file = config.ConfigFile( + 'base.yaml', + { + 'version': '3.1', + 'services': { + 'web': { + 'image': 'example/web', + 'secrets': ['one'], + }, + }, + 'secrets': { + 'one': {'file': 'secret.txt'}, + }, + }) + override_file = config.ConfigFile( + 'base.yaml', + { + 'version': '3.1', + 'services': { + 'web': { + 'secrets': [ + { + 'source': 'source', + 'target': 'target', + 'uid': '100', + 'gid': '200', + 'mode': 0o777, + }, + ], + }, + }, + }) + details = config.ConfigDetails('.', [base_file, override_file]) + service_dicts = config.load(details).services + expected = [ + { + 'name': 'web', + 'image': 'example/web', + 'secrets': [ + types.ServiceSecret('one', None, None, None, None), + types.ServiceSecret('source', 'target', '100', '200', 0o777), + ], + }, + ] + assert service_sort(service_dicts) == service_sort(expected) + class NetworkModeTest(unittest.TestCase): def test_network_mode_standard(self): From 252699c1d124ba365e4b9078f4a44f3acbcb08be Mon Sep 17 00:00:00 2001 From: Petr Karmashev Date: Sun, 12 Feb 2017 02:03:04 +0300 Subject: [PATCH 13/17] Compose file reference link fix in README.md Signed-off-by: Petr Karmashev --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5cf69b05..35a10b90 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ A `docker-compose.yml` looks like this: image: redis For more information about the Compose file, see the -[Compose file reference](https://github.com/docker/docker.github.io/blob/master/compose/compose-file.md) +[Compose file reference](https://github.com/docker/docker.github.io/blob/master/compose/compose-file/compose-versioning.md) Compose has commands for managing the whole lifecycle of your application: From abce83ef25528fb36979208888ba0033c89f47a3 Mon Sep 17 00:00:00 2001 From: Joffrey F Date: Mon, 13 Feb 2017 16:04:06 -0800 Subject: [PATCH 14/17] Fix `config` command output with service.secrets section Signed-off-by: Joffrey F --- compose/config/serialize.py | 3 ++ compose/config/types.py | 7 ++-- tests/unit/config/config_test.py | 57 ++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 5 deletions(-) diff --git a/compose/config/serialize.py b/compose/config/serialize.py index 3745de82..46d283f0 100644 --- a/compose/config/serialize.py +++ b/compose/config/serialize.py @@ -102,4 +102,7 @@ def denormalize_service_dict(service_dict, version): service_dict['healthcheck']['timeout'] ) + if 'secrets' in service_dict: + service_dict['secrets'] = map(lambda s: s.repr(), service_dict['secrets']) + return service_dict diff --git a/compose/config/types.py b/compose/config/types.py index f86c0319..811e6c1f 100644 --- a/compose/config/types.py +++ b/compose/config/types.py @@ -256,8 +256,5 @@ class ServiceSecret(namedtuple('_ServiceSecret', 'source target uid gid mode')): def repr(self): return dict( - source=self.source, - target=self.target, - uid=self.uid, - gid=self.gid, - mode=self.mode) + [(k, v) for k, v in self._asdict().items() if v is not None] + ) diff --git a/tests/unit/config/config_test.py b/tests/unit/config/config_test.py index d4d1ad2c..c26272d9 100644 --- a/tests/unit/config/config_test.py +++ b/tests/unit/config/config_test.py @@ -54,6 +54,10 @@ def service_sort(services): return sorted(services, key=itemgetter('name')) +def secret_sort(secrets): + return sorted(secrets, key=itemgetter('source')) + + class ConfigTest(unittest.TestCase): def test_load(self): service_dicts = config.load( @@ -1771,6 +1775,38 @@ class ConfigTest(unittest.TestCase): 'labels': {'com.docker.compose.test': 'yes'} } + def test_merge_different_secrets(self): + base = { + 'image': 'busybox', + 'secrets': [ + {'source': 'src.txt'} + ] + } + override = {'secrets': ['other-src.txt']} + + actual = config.merge_service_dicts(base, override, V3_1) + assert secret_sort(actual['secrets']) == secret_sort([ + {'source': 'src.txt'}, + {'source': 'other-src.txt'} + ]) + + def test_merge_secrets_override(self): + base = { + 'image': 'busybox', + 'secrets': ['src.txt'], + } + override = { + 'secrets': [ + { + 'source': 'src.txt', + 'target': 'data.txt', + 'mode': 0o400 + } + ] + } + actual = config.merge_service_dicts(base, override, V3_1) + assert actual['secrets'] == override['secrets'] + def test_external_volume_config(self): config_details = build_config_details({ 'version': '2', @@ -3491,3 +3527,24 @@ class SerializeTest(unittest.TestCase): denormalized_service = denormalize_service_dict(processed_service, V2_1) assert denormalized_service['healthcheck']['interval'] == '100s' assert denormalized_service['healthcheck']['timeout'] == '30s' + + def test_denormalize_secrets(self): + service_dict = { + 'name': 'web', + 'image': 'example/web', + 'secrets': [ + types.ServiceSecret('one', None, None, None, None), + types.ServiceSecret('source', 'target', '100', '200', 0o777), + ], + } + denormalized_service = denormalize_service_dict(service_dict, V3_1) + assert secret_sort(denormalized_service['secrets']) == secret_sort([ + {'source': 'one'}, + { + 'source': 'source', + 'target': 'target', + 'uid': '100', + 'gid': '200', + 'mode': 0o777, + }, + ]) From 66f4a795a2ded1a26b6cf8474edb423727dd585d Mon Sep 17 00:00:00 2001 From: Joffrey F Date: Wed, 15 Feb 2017 16:07:08 -0800 Subject: [PATCH 15/17] Don't import pip inside Compose Signed-off-by: Joffrey F --- compose/cli/__init__.py | 37 +++++++++++++++++++++++++++++++++++++ compose/cli/main.py | 24 ------------------------ 2 files changed, 37 insertions(+), 24 deletions(-) diff --git a/compose/cli/__init__.py b/compose/cli/__init__.py index e69de29b..c5db4455 100644 --- a/compose/cli/__init__.py +++ b/compose/cli/__init__.py @@ -0,0 +1,37 @@ +from __future__ import absolute_import +from __future__ import print_function +from __future__ import unicode_literals + +import subprocess +import sys + +# Attempt to detect https://github.com/docker/compose/issues/4344 +try: + # We don't try importing pip because it messes with package imports + # on some Linux distros (Ubuntu, Fedora) + # https://github.com/docker/compose/issues/4425 + # https://github.com/docker/compose/issues/4481 + # https://github.com/pypa/pip/blob/master/pip/_vendor/__init__.py + s_cmd = subprocess.Popen( + ['pip', 'freeze'], stderr=subprocess.PIPE, stdout=subprocess.PIPE + ) + packages = s_cmd.communicate()[0].splitlines() + dockerpy_installed = len( + list(filter(lambda p: p.startswith(b'docker-py=='), packages)) + ) > 0 + if dockerpy_installed: + from .colors import red + print( + red('ERROR:'), + "Dependency conflict: an older version of the 'docker-py' package " + "is polluting the namespace. " + "Run the following command to remedy the issue:\n" + "pip uninstall docker docker-py; pip install docker", + file=sys.stderr + ) + sys.exit(1) + +except OSError: + # pip command is not available, which indicates it's probably the binary + # distribution of Compose which is not affected + pass diff --git a/compose/cli/main.py b/compose/cli/main.py index e2ebce48..51ba36a0 100644 --- a/compose/cli/main.py +++ b/compose/cli/main.py @@ -14,30 +14,6 @@ from distutils.spawn import find_executable from inspect import getdoc from operator import attrgetter - -# Attempt to detect https://github.com/docker/compose/issues/4344 -try: - # A regular import statement causes PyInstaller to freak out while - # trying to load pip. This way it is simply ignored. - pip = __import__('pip') - pip_packages = pip.get_installed_distributions() - if 'docker-py' in [pkg.project_name for pkg in pip_packages]: - from .colors import red - print( - red('ERROR:'), - "Dependency conflict: an older version of the 'docker-py' package " - "is polluting the namespace. " - "Run the following command to remedy the issue:\n" - "pip uninstall docker docker-py; pip install docker", - file=sys.stderr - ) - sys.exit(1) -except ImportError: - # pip is not available, which indicates it's probably the binary - # distribution of Compose which is not affected - pass - - from . import errors from . import signals from .. import __version__ From 27297fd1af64aae4e48fce254bace122014977fd Mon Sep 17 00:00:00 2001 From: "Aaron.L.Xu" Date: Thu, 16 Feb 2017 11:14:25 +0800 Subject: [PATCH 16/17] fix a typo in script/release/utils.sh Signed-off-by: Aaron.L.Xu --- script/release/utils.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/release/utils.sh b/script/release/utils.sh index b4e5a2e6..321c1fb7 100644 --- a/script/release/utils.sh +++ b/script/release/utils.sh @@ -1,6 +1,6 @@ #!/bin/bash # -# Util functions for release scritps +# Util functions for release scripts # set -e From d20e3f334215a55cbebc27d8dde82108a58a0bae Mon Sep 17 00:00:00 2001 From: "Aaron.L.Xu" Date: Thu, 16 Feb 2017 15:25:04 +0800 Subject: [PATCH 17/17] function-name-modification for tests/* Signed-off-by: Aaron.L.Xu --- tests/acceptance/cli_test.py | 10 +++++----- tests/unit/cli_test.py | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/acceptance/cli_test.py b/tests/acceptance/cli_test.py index 160e1913..8366ca75 100644 --- a/tests/acceptance/cli_test.py +++ b/tests/acceptance/cli_test.py @@ -1234,7 +1234,7 @@ class CLITestCase(DockerClientTestCase): container = service.containers(stopped=True, one_off=OneOffFilter.only)[0] self.assertEqual(user, container.get('Config.User')) - def test_run_service_with_environement_overridden(self): + def test_run_service_with_environment_overridden(self): name = 'service' self.base_dir = 'tests/fixtures/environment-composefile' self.dispatch([ @@ -1246,9 +1246,9 @@ class CLITestCase(DockerClientTestCase): ]) service = self.project.get_service(name) container = service.containers(stopped=True, one_off=OneOffFilter.only)[0] - # env overriden + # env overridden self.assertEqual('notbar', container.environment['foo']) - # keep environement from yaml + # keep environment from yaml self.assertEqual('world', container.environment['hello']) # added option from command line self.assertEqual('beta', container.environment['alpha']) @@ -1293,7 +1293,7 @@ class CLITestCase(DockerClientTestCase): self.assertEqual(port_range[0], "0.0.0.0:49153") self.assertEqual(port_range[1], "0.0.0.0:49154") - def test_run_service_with_explicitly_maped_ports(self): + def test_run_service_with_explicitly_mapped_ports(self): # create one off container self.base_dir = 'tests/fixtures/ports-composefile' self.dispatch(['run', '-d', '-p', '30000:3000', '--publish', '30001:3001', 'simple']) @@ -1310,7 +1310,7 @@ class CLITestCase(DockerClientTestCase): self.assertEqual(port_short, "0.0.0.0:30000") self.assertEqual(port_full, "0.0.0.0:30001") - def test_run_service_with_explicitly_maped_ip_ports(self): + def test_run_service_with_explicitly_mapped_ip_ports(self): # create one off container self.base_dir = 'tests/fixtures/ports-composefile' self.dispatch([ diff --git a/tests/unit/cli_test.py b/tests/unit/cli_test.py index f9b60bff..317650cb 100644 --- a/tests/unit/cli_test.py +++ b/tests/unit/cli_test.py @@ -184,7 +184,7 @@ class CLITestCase(unittest.TestCase): mock_client.create_host_config.call_args[1].get('restart_policy') ) - def test_command_manula_and_service_ports_together(self): + def test_command_manual_and_service_ports_together(self): project = Project.from_config( name='composetest', client=None,