From d9e05f262fd98880b3809fe3b45c998b325ad6cf Mon Sep 17 00:00:00 2001 From: Ulysses Souza Date: Thu, 22 Nov 2018 11:34:34 +0100 Subject: [PATCH 1/2] Avoids pushing the same image more than once. Signed-off-by: Ulysses Souza --- compose/project.py | 10 +++++++++- tests/integration/project_test.py | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/compose/project.py b/compose/project.py index 92c352050..8fab09e54 100644 --- a/compose/project.py +++ b/compose/project.py @@ -29,6 +29,7 @@ from .service import ContainerNetworkMode from .service import ContainerPidMode from .service import ConvergenceStrategy from .service import NetworkMode +from .service import parse_repository_tag from .service import PidMode from .service import Service from .service import ServiceNetworkMode @@ -592,8 +593,15 @@ class Project(object): service.pull(ignore_pull_failures, silent=silent) def push(self, service_names=None, ignore_push_failures=False): + unique_images = set() for service in self.get_services(service_names, include_deps=False): - service.push(ignore_push_failures) + # Considering and as the same + repo, tag, sep = parse_repository_tag(service.image_name) + service_image_name = sep.join((repo, tag)) if tag else sep.join((repo, 'latest')) + + if service_image_name not in unique_images: + service.push(ignore_push_failures) + unique_images.add(service_image_name) def _labeled_containers(self, stopped=False, one_off=OneOffFilter.exclude): ctnrs = list(filter(None, [ diff --git a/tests/integration/project_test.py b/tests/integration/project_test.py index 57f3b7074..203b7bb3d 100644 --- a/tests/integration/project_test.py +++ b/tests/integration/project_test.py @@ -1995,3 +1995,21 @@ class ProjectTest(DockerClientTestCase): net_data = self.client.inspect_network(full_net_name) assert net_data assert net_data['Labels'][LABEL_PROJECT] == '-dashtest' + + def test_avoid_multiple_push(self): + service_config_latest = {'image': 'busybox:latest', 'build': '.'} + service_config_default = {'image': 'busybox', 'build': '.'} + service_config_sha = { + 'image': 'busybox@sha256:38a203e1986cf79639cfb9b2e1d6e773de84002feea2d4eb006b52004ee8502d', + 'build': '.' + } + svc1 = self.create_service('busy1', **service_config_latest) + svc1_1 = self.create_service('busy11', **service_config_latest) + svc2 = self.create_service('busy2', **service_config_default) + svc2_1 = self.create_service('busy21', **service_config_default) + svc3 = self.create_service('busy3', **service_config_sha) + svc3_1 = self.create_service('busy31', **service_config_sha) + project = Project('composetest', [svc1, svc1_1, svc2, svc2_1, svc3, svc3_1], self.client) + with mock.patch('compose.service.Service.push') as fake_push: + project.push(ignore_push_failures=True) + assert fake_push.call_count == 2 From d3933cd34a88e811b9612d728569fc9be6d560d4 Mon Sep 17 00:00:00 2001 From: Joffrey F Date: Tue, 4 Dec 2018 17:13:40 -0800 Subject: [PATCH 2/2] Move multi-push test to unit tests Signed-off-by: Joffrey F --- tests/integration/project_test.py | 18 ------------------ tests/unit/project_test.py | 20 ++++++++++++++++++++ 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/tests/integration/project_test.py b/tests/integration/project_test.py index 203b7bb3d..57f3b7074 100644 --- a/tests/integration/project_test.py +++ b/tests/integration/project_test.py @@ -1995,21 +1995,3 @@ class ProjectTest(DockerClientTestCase): net_data = self.client.inspect_network(full_net_name) assert net_data assert net_data['Labels'][LABEL_PROJECT] == '-dashtest' - - def test_avoid_multiple_push(self): - service_config_latest = {'image': 'busybox:latest', 'build': '.'} - service_config_default = {'image': 'busybox', 'build': '.'} - service_config_sha = { - 'image': 'busybox@sha256:38a203e1986cf79639cfb9b2e1d6e773de84002feea2d4eb006b52004ee8502d', - 'build': '.' - } - svc1 = self.create_service('busy1', **service_config_latest) - svc1_1 = self.create_service('busy11', **service_config_latest) - svc2 = self.create_service('busy2', **service_config_default) - svc2_1 = self.create_service('busy21', **service_config_default) - svc3 = self.create_service('busy3', **service_config_sha) - svc3_1 = self.create_service('busy31', **service_config_sha) - project = Project('composetest', [svc1, svc1_1, svc2, svc2_1, svc3, svc3_1], self.client) - with mock.patch('compose.service.Service.push') as fake_push: - project.push(ignore_push_failures=True) - assert fake_push.call_count == 2 diff --git a/tests/unit/project_test.py b/tests/unit/project_test.py index 1cc841814..f17bc571e 100644 --- a/tests/unit/project_test.py +++ b/tests/unit/project_test.py @@ -620,3 +620,23 @@ class ProjectTest(unittest.TestCase): self.mock_client.pull.side_effect = OperationFailedError(b'pull error') with pytest.raises(ProjectError): project.pull(parallel_pull=True) + + def test_avoid_multiple_push(self): + service_config_latest = {'image': 'busybox:latest', 'build': '.'} + service_config_default = {'image': 'busybox', 'build': '.'} + service_config_sha = { + 'image': 'busybox@sha256:38a203e1986cf79639cfb9b2e1d6e773de84002feea2d4eb006b52004ee8502d', + 'build': '.' + } + svc1 = Service('busy1', **service_config_latest) + svc1_1 = Service('busy11', **service_config_latest) + svc2 = Service('busy2', **service_config_default) + svc2_1 = Service('busy21', **service_config_default) + svc3 = Service('busy3', **service_config_sha) + svc3_1 = Service('busy31', **service_config_sha) + project = Project( + 'composetest', [svc1, svc1_1, svc2, svc2_1, svc3, svc3_1], self.mock_client + ) + with mock.patch('compose.service.Service.push') as fake_push: + project.push() + assert fake_push.call_count == 2