diff --git a/compose/utils.py b/compose/utils.py index 4c7f94c576..61d6d80243 100644 --- a/compose/utils.py +++ b/compose/utils.py @@ -32,6 +32,10 @@ def parallel_execute(objects, obj_callable, msg_index, msg): except APIError as e: errors[msg_index] = e.explanation result = "error" + except Exception as e: + errors[msg_index] = e + result = 'unexpected_exception' + q.put((msg_index, result)) for an_object in objects: @@ -48,6 +52,9 @@ def parallel_execute(objects, obj_callable, msg_index, msg): while done < total_to_execute: try: msg_index, result = q.get(timeout=1) + + if result == 'unexpected_exception': + raise errors[msg_index] if result == 'error': write_out_msg(stream, lines, msg_index, msg, status='error') else: diff --git a/tests/integration/service_test.py b/tests/integration/service_test.py index 8856d0245f..70ca758a56 100644 --- a/tests/integration/service_test.py +++ b/tests/integration/service_test.py @@ -672,6 +672,25 @@ class ServiceTest(DockerClientTestCase): self.assertTrue(service.containers()[0].is_running) self.assertIn("ERROR: for 2 Boom", mock_stdout.getvalue()) + @patch('sys.stdout', new_callable=StringIO) + def test_scale_with_api_returns_unexpected_exception(self, mock_stdout): + """ + Test that when scaling if the API returns an error, that is not of type + APIError, that error is re-raised. + """ + service = self.create_service('web') + next_number = service._next_container_number() + service.create_container(number=next_number, quiet=True) + + with patch( + 'compose.container.Container.create', + side_effect=ValueError("BOOM")): + with self.assertRaises(ValueError): + service.scale(3) + + self.assertEqual(len(service.containers()), 1) + self.assertTrue(service.containers()[0].is_running) + @patch('compose.service.log') def test_scale_with_desired_number_already_achieved(self, mock_log): """