From e69b9a21ca4fd0f36f111f9a6968a3d854e0f28c Mon Sep 17 00:00:00 2001 From: Joffrey F Date: Fri, 30 Mar 2018 18:02:06 -0700 Subject: [PATCH 1/4] Fix port serialization with external IP Signed-off-by: Joffrey F --- compose/config/serialize.py | 5 +++-- tests/unit/config/config_test.py | 12 ++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/compose/config/serialize.py b/compose/config/serialize.py index 7de7f41e8..c0cf35c1b 100644 --- a/compose/config/serialize.py +++ b/compose/config/serialize.py @@ -151,9 +151,10 @@ def denormalize_service_dict(service_dict, version, image_digest=None): service_dict['healthcheck']['start_period'] = serialize_ns_time_value( service_dict['healthcheck']['start_period'] ) - if 'ports' in service_dict and version < V3_2: + + if 'ports' in service_dict: service_dict['ports'] = [ - p.legacy_repr() if isinstance(p, types.ServicePort) else p + p.legacy_repr() if p.external_ip or version < V3_2 else p for p in service_dict['ports'] ] if 'volumes' in service_dict and (version < V2_3 or (version > V3_0 and version < V3_2)): diff --git a/tests/unit/config/config_test.py b/tests/unit/config/config_test.py index 0574b215c..8a75648ac 100644 --- a/tests/unit/config/config_test.py +++ b/tests/unit/config/config_test.py @@ -4943,6 +4943,18 @@ class SerializeTest(unittest.TestCase): serialized_config = yaml.load(serialize_config(config_dict)) assert '8080:80/tcp' in serialized_config['services']['web']['ports'] + def test_serialize_ports_with_ext_ip(self): + config_dict = config.Config(version=V3_5, services=[ + { + 'ports': [types.ServicePort('80', '8080', None, None, '127.0.0.1')], + 'image': 'alpine', + 'name': 'web' + } + ], volumes={}, networks={}, secrets={}, configs={}) + + serialized_config = yaml.load(serialize_config(config_dict)) + assert '127.0.0.1:8080:80/tcp' in serialized_config['services']['web']['ports'] + def test_serialize_configs(self): service_dict = { 'image': 'example/web', From 1d329808cc5c8b6f97a7fd23503f0a48c432f302 Mon Sep 17 00:00:00 2001 From: Joffrey F Date: Fri, 30 Mar 2018 16:04:48 -0700 Subject: [PATCH 2/4] Bump 1.21.0-rc1 Signed-off-by: Joffrey F --- CHANGELOG.md | 74 ++++++++++++++++++++++++++++++++++++++++++++- compose/__init__.py | 2 +- script/run/run.sh | 2 +- 3 files changed, 75 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25e04d1b2..a8e0b8df5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,78 @@ Change log ========== +1.21.0 (2018-04-11) +------------------- + +### New features + +#### Compose file version 2.4 + +- Introduced version 2.4 of the `docker-compose.yml` specification. + This version requires Docker Engine 17.12.0 or above. + +- Added support for the `platform` parameter in service definitions. + If supplied, the parameter is also used when performing build for the + service. + +#### Compose file version 2.2 and up + +- Added support for the `cpu_rt_period` and `cpu_rt_runtime` parameters + in service definitions (2.x only). + +#### Compose file version 2.1 and up + +- Added support for the `cpu_period` parameter in service definitions + (2.x only). + +- Added support for the `isolation` parameter in service build configurations. + Additionally, the `isolation` parameter is used for builds as well if no + `build.isolation` parameter is defined. (2.x only) + +#### All formats + +- Added support for the `--workdir` flag in `docker-compose exec`. + +- Added support for the `--compress` flag in `docker-compose build`. + +- `docker-compose pull` is now performed in parallel by default. You can + opt out using the `--no-parallel` flag. The `--parallel` flag is now + deprecated and will be removed in a future version. + +- Dashes and underscores in project names are no longer stripped out. + +- `docker-compose build` now supports the use of Dockerfile from outside + the build context. + +### Bugfixes + +- Compose now checks that the volume's configuration matches the remote + volume, and errors out if a mismatch is detected. + +- Fixed a bug that caused Compose to raise unexpected errors when attempting + to create several one-off containers in parallel. + +- Fixed a bug with argument parsing when using `docker-machine config` to + generate TLS flags for `exec` and `run` commands. + +- Fixed a bug where variable substitution with an empty default value + (e.g. `${VAR:-}`) would print an incorrect warning. + +- Improved resilience when encoding of the Compose file doesn't match the + system's. Users are encouraged to use UTF-8 when possible. + +- Fixed a bug where external overlay networks in Swarm would be incorrectly + recognized as inexistent by Compose, interrupting otherwise valid + operations. + +1.20.1 (2018-03-21) +------------------- + +### Bugfixes + +- Fixed an issue where `docker-compose build` would error out if the + build context contained directory symlinks + 1.20.0 (2018-03-20) ------------------- @@ -9,7 +81,7 @@ Change log #### Compose file version 3.6 - Introduced version 3.6 of the `docker-compose.yml` specification. - This version requires to be used with Docker Engine 18.02.0 or above. + This version requires Docker Engine 18.02.0 or above. - Added support for the `tmpfs.size` property in volume mappings diff --git a/compose/__init__.py b/compose/__init__.py index a5c1364a6..d7ed9198c 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.21.0dev' +__version__ = '1.21.0-rc1' diff --git a/script/run/run.sh b/script/run/run.sh index a739edb35..fb4cb8b4b 100755 --- a/script/run/run.sh +++ b/script/run/run.sh @@ -15,7 +15,7 @@ set -e -VERSION="1.20.0" +VERSION="1.21.0-rc1" IMAGE="docker/compose:$VERSION" From 614bfd6fb04888f5e376b7249bf791d7e39672e7 Mon Sep 17 00:00:00 2001 From: Joffrey F Date: Fri, 6 Apr 2018 17:46:23 -0700 Subject: [PATCH 3/4] Make sure error messages are unicode strings before combining Signed-off-by: Joffrey F --- compose/parallel.py | 11 ++++++----- compose/project.py | 6 +++++- tests/unit/project_test.py | 29 +++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/compose/parallel.py b/compose/parallel.py index 5d4791f97..a2eb160e5 100644 --- a/compose/parallel.py +++ b/compose/parallel.py @@ -279,9 +279,7 @@ class ParallelStreamWriter(object): def write_initial(self, msg, obj_index): if msg is None: return - self.stream.write("{:<{width}} ... \r\n".format( - msg + ' ' + obj_index, width=self.width)) - self.stream.flush() + return self._write_noansi(msg, obj_index, '') def _write_ansi(self, msg, obj_index, status): self.lock.acquire() @@ -299,8 +297,11 @@ class ParallelStreamWriter(object): self.lock.release() def _write_noansi(self, msg, obj_index, status): - self.stream.write("{:<{width}} ... {}\r\n".format(msg + ' ' + obj_index, - status, width=self.width)) + self.stream.write( + "{:<{width}} ... {}\r\n".format( + msg + ' ' + obj_index, status, width=self.width + ) + ) self.stream.flush() def write(self, msg, obj_index, status, color_func): diff --git a/compose/project.py b/compose/project.py index afbec183f..924390b4e 100644 --- a/compose/project.py +++ b/compose/project.py @@ -556,7 +556,11 @@ class Project(object): limit=5, ) if len(errors): - raise ProjectError(b"\n".join(errors.values())) + combined_errors = '\n'.join([ + e.decode('utf-8') if isinstance(e, six.binary_type) else e for e in errors.values() + ]) + raise ProjectError(combined_errors) + else: for service in services: service.pull(ignore_pull_failures, silent=silent) diff --git a/tests/unit/project_test.py b/tests/unit/project_test.py index eb6209723..83a014758 100644 --- a/tests/unit/project_test.py +++ b/tests/unit/project_test.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals import datetime import docker +import pytest from docker.errors import NotFound from .. import mock @@ -16,8 +17,10 @@ from compose.const import COMPOSEFILE_V2_0 as V2_0 from compose.const import COMPOSEFILE_V2_4 as V2_4 from compose.const import LABEL_SERVICE from compose.container import Container +from compose.errors import OperationFailedError from compose.project import NoSuchService from compose.project import Project +from compose.project import ProjectError from compose.service import ImageType from compose.service import Service @@ -588,3 +591,29 @@ class ProjectTest(unittest.TestCase): name='test', client=self.mock_client, config_data=config_data, default_platform='windows' ) assert project.get_service('web').options.get('platform') == 'linux/s390x' + + @mock.patch('compose.parallel.ParallelStreamWriter._write_noansi') + def test_error_parallel_pull(self, mock_write): + project = Project.from_config( + name='test', + client=self.mock_client, + config_data=Config( + version=V2_0, + services=[{ + 'name': 'web', + 'image': 'busybox:latest', + }], + networks=None, + volumes=None, + secrets=None, + configs=None, + ), + ) + + self.mock_client.pull.side_effect = OperationFailedError('pull error') + with pytest.raises(ProjectError): + project.pull(parallel_pull=True) + + self.mock_client.pull.side_effect = OperationFailedError(b'pull error') + with pytest.raises(ProjectError): + project.pull(parallel_pull=True) From 5920eb082ca60c5e66fdd856b28807b0c97a33dc Mon Sep 17 00:00:00 2001 From: Joffrey F Date: Mon, 9 Apr 2018 13:54:15 -0700 Subject: [PATCH 4/4] Bump 1.21.0 Signed-off-by: Joffrey F --- CHANGELOG.md | 2 +- compose/__init__.py | 2 +- script/run/run.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a8e0b8df5..3709e263d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ Change log ========== -1.21.0 (2018-04-11) +1.21.0 (2018-04-10) ------------------- ### New features diff --git a/compose/__init__.py b/compose/__init__.py index d7ed9198c..693a1ab18 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.21.0-rc1' +__version__ = '1.21.0' diff --git a/script/run/run.sh b/script/run/run.sh index fb4cb8b4b..1e4bd9853 100755 --- a/script/run/run.sh +++ b/script/run/run.sh @@ -15,7 +15,7 @@ set -e -VERSION="1.21.0-rc1" +VERSION="1.21.0" IMAGE="docker/compose:$VERSION"