From e71180039441e3c7d49467298ef0f498fe786149 Mon Sep 17 00:00:00 2001 From: aksel Date: Thu, 27 Jun 2024 15:01:51 +0100 Subject: [PATCH] feat(core): DockerCompose.stop now stops only services that it starts (does not stop the other services) (#620) The command would otherwise stop/down all services, not just the services the instance itself started. Useful for e.g. one fixture per service, and you want different scopes for the services. --- core/testcontainers/compose/compose.py | 4 ++ .../basic_multiple/docker-compose.yaml | 15 ++++++ core/tests/test_compose.py | 49 +++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 core/tests/compose_fixtures/basic_multiple/docker-compose.yaml diff --git a/core/testcontainers/compose/compose.py b/core/testcontainers/compose/compose.py index 951aee6d..08dd313a 100644 --- a/core/testcontainers/compose/compose.py +++ b/core/testcontainers/compose/compose.py @@ -236,6 +236,10 @@ def stop(self, down=True) -> None: down_cmd += ["down", "--volumes"] else: down_cmd += ["stop"] + + if self.services: + down_cmd.extend(self.services) + self._run_command(cmd=down_cmd) def get_logs(self, *services: str) -> tuple[str, str]: diff --git a/core/tests/compose_fixtures/basic_multiple/docker-compose.yaml b/core/tests/compose_fixtures/basic_multiple/docker-compose.yaml new file mode 100644 index 00000000..38bd92b9 --- /dev/null +++ b/core/tests/compose_fixtures/basic_multiple/docker-compose.yaml @@ -0,0 +1,15 @@ +services: + alpine1: + image: alpine:latest + init: true + command: + - sh + - -c + - 'while true; do sleep 0.1 ; date -Ins; done' + alpine2: + image: alpine:latest + init: true + command: + - sh + - -c + - 'while true; do sleep 0.1 ; date -Ins; done' diff --git a/core/tests/test_compose.py b/core/tests/test_compose.py index 0a244220..e1a42655 100644 --- a/core/tests/test_compose.py +++ b/core/tests/test_compose.py @@ -37,6 +37,55 @@ def test_compose_start_stop(): basic.stop() +def test_start_stop_multiple(): + """Start and stop multiple containers individually.""" + + # Create two DockerCompose instances from the same file, one service each. + dc_a = DockerCompose(context=FIXTURES / "basic_multiple", services=["alpine1"]) + dc_b = DockerCompose(context=FIXTURES / "basic_multiple", services=["alpine2"]) + + # After starting the first instance, alpine1 should be running + dc_a.start() + dc_a.get_container("alpine1") # Raises if it isn't running + dc_b.get_container("alpine1") # Raises if it isn't running + + # Both instances report the same number of containers + assert len(dc_a.get_containers()) == 1 + assert len(dc_b.get_containers()) == 1 + + # Although alpine1 is running, alpine2 has not started yet. + with pytest.raises(ContainerIsNotRunning): + dc_a.get_container("alpine2") + with pytest.raises(ContainerIsNotRunning): + dc_b.get_container("alpine2") + + # After starting the second instance, alpine2 should also be running + dc_b.start() + dc_a.get_container("alpine2") # No longer raises + dc_b.get_container("alpine2") # No longer raises + assert len(dc_a.get_containers()) == 2 + assert len(dc_b.get_containers()) == 2 + + # After stopping the first instance, alpine1 should no longer be running + dc_a.stop() + dc_a.get_container("alpine2") + dc_b.get_container("alpine2") + assert len(dc_a.get_containers()) == 1 + assert len(dc_b.get_containers()) == 1 + + # alpine1 no longer running + with pytest.raises(ContainerIsNotRunning): + dc_a.get_container("alpine1") + with pytest.raises(ContainerIsNotRunning): + dc_b.get_container("alpine1") + + # Stop the second instance + dc_b.stop() + + assert len(dc_a.get_containers()) == 0 + assert len(dc_b.get_containers()) == 0 + + def test_compose(): """stream-of-consciousness e2e test""" basic = DockerCompose(context=FIXTURES / "basic")