From 557069583d2728d3a7dff3d4706812bd4e4b4c42 Mon Sep 17 00:00:00 2001 From: Niek <100143256+SchoNie@users.noreply.github.com> Date: Thu, 27 Feb 2025 13:37:28 +0100 Subject: [PATCH] tests: DockerComposer contextmanager improvements -Improve the DockerComposer contextmanager to make sure teardown happens by using try except block. -Move the self. declarations up so we are sure they are set even if an exception occurs. -set self._networks --- test/conftest.py | 39 +++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/test/conftest.py b/test/conftest.py index 2b1ab44..5c1c7e4 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -471,34 +471,57 @@ def connect_to_all_networks() -> List[Network]: class DockerComposer(contextlib.AbstractContextManager): def __init__(self): + logging.debug("DockerComposer __init__") self._networks = None self._docker_compose_files = None self._project_name = None def __exit__(self, *exc_info): + logging.debug("DockerComposer __exit__") self._down() def _down(self): + logging.debug(f"DockerComposer _down {self._docker_compose_files} {self._project_name} {self._networks}") if self._docker_compose_files is None: + logging.debug("docker_compose_files is None, nothing to cleanup") return - for network in self._networks: - disconnect_from_network(network) + if self._networks: + for network in self._networks: + disconnect_from_network(network) docker_compose_down(self._docker_compose_files, self._project_name) self._docker_compose_file = None self._project_name = None + self._networks = [] def compose(self, docker_compose_files: List[str], project_name: str): if docker_compose_files == self._docker_compose_files and project_name == self._project_name: + logging.info(f"Skipping compose: {docker_compose_files} (already running under project {project_name})") + return + if docker_compose_files is None or project_name is None: + logging.info(f"Skipping compose: no compose file specified") return self._down() - if docker_compose_files is None or project_name is None: - return - docker_compose_up(docker_compose_files, project_name) - self._networks = connect_to_all_networks() - wait_for_nginxproxy_to_be_ready() - time.sleep(3) # give time to containers to be ready self._docker_compose_files = docker_compose_files self._project_name = project_name + logging.debug(f"DockerComposer compose {self._docker_compose_files} {self._project_name} {self._networks}") + + try: + docker_compose_up(docker_compose_files, project_name) + self._networks = connect_to_all_networks() + wait_for_nginxproxy_to_be_ready() + time.sleep(3) # give time to containers to be ready + + except docker.errors.APIError as e: + logging.error(f"Docker API error ({e.status_code}): {e.explanation}") + logging.debug(f"Full error message: {str(e)}") + self._down() # Ensure proper cleanup even on failure + pytest.fail(f"Docker Compose setup failed due to Docker API error: {e.explanation}") + + except RuntimeError as e: + logging.error(f"RuntimeEror encountered in: {project_name}") + logging.debug(f"Full error message: {str(e)}") + self._down() # Ensure proper cleanup even on failure + pytest.fail(f"Docker Compose setup failed due to RuntimeError in: {project_name}") ###############################################################################