Skip to content

Commit 1ea9ed1

Browse files
feat(reuse): do not create Ryuk cleanup instance
do not create Ryuk cleanup instance if reuse enabled and container has been start with `with_reuse`
1 parent d4445d6 commit 1ea9ed1

File tree

2 files changed

+49
-34
lines changed

2 files changed

+49
-34
lines changed

core/testcontainers/core/container.py

+7-5
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,11 @@ def maybe_emulate_amd64(self) -> Self:
8989
return self
9090

9191
def start(self) -> Self:
92-
if not c.ryuk_disabled and self.image != c.ryuk_image:
92+
if (
93+
not c.ryuk_disabled
94+
and self.image != c.ryuk_image
95+
and not (self._reuse and c.tc_properties_testcontainers_reuse_enable)
96+
):
9397
logger.debug("Creating Ryuk container")
9498
Reaper.get_instance()
9599
logger.info("Pulling image %s", self.image)
@@ -107,13 +111,11 @@ def start(self) -> Self:
107111
)
108112
hash_ = hashlib.sha256(bytes(str(args), encoding="utf-8")).hexdigest()
109113

110-
if self._reuse and (not c.tc_properties_testcontainers_reuse_enable or not c.ryuk_disabled):
114+
if self._reuse and not c.tc_properties_testcontainers_reuse_enable:
111115
logging.warning(
112116
"Reuse was requested (`with_reuse`) but the environment does not "
113117
+ "support the reuse of containers. To enable container reuse, add "
114-
+ "the 'testcontainers.reuse.enable=true' to "
115-
+ "'~/.testcontainers.properties' and disable ryuk by setting the "
116-
+ "environment variable 'TESTCONTAINERS_RYUK_DISABLED=true'"
118+
+ "'testcontainers.reuse.enable=true' to '~/.testcontainers.properties'."
117119
)
118120

119121
if self._reuse and c.tc_properties_testcontainers_reuse_enable:

core/tests/test_reusable_containers.py

+42-29
Original file line numberDiff line numberDiff line change
@@ -10,62 +10,75 @@
1010

1111

1212
def test_docker_container_reuse_default():
13-
with DockerContainer("hello-world") as container:
14-
assert container._reuse == False
15-
id = container._container.id
16-
wait_for_logs(container, "Hello from Docker!")
13+
# Make sure Ryuk cleanup is not active from previous test runs
14+
Reaper.delete_instance()
15+
16+
container = DockerContainer("hello-world").start()
17+
wait_for_logs(container, "Hello from Docker!")
18+
19+
assert container._reuse == False
20+
assert testcontainers_config.tc_properties_testcontainers_reuse_enable == False
21+
assert Reaper._socket is not None
22+
23+
container.stop()
1724
containers = DockerClient().client.containers.list(all=True)
18-
assert id not in [container.id for container in containers]
25+
assert container._container.id not in [container.id for container in containers]
1926

2027

21-
def test_docker_container_with_reuse_reuse_disabled():
22-
with DockerContainer("hello-world").with_reuse() as container:
23-
assert container._reuse == True
24-
assert testcontainers_config.tc_properties_testcontainers_reuse_enable == False
25-
id = container._container.id
26-
wait_for_logs(container, "Hello from Docker!")
28+
def test_docker_container_with_reuse_reuse_disabled(caplog):
29+
# Make sure Ryuk cleanup is not active from previous test runs
30+
Reaper.delete_instance()
31+
32+
container = DockerContainer("hello-world").with_reuse().start()
33+
wait_for_logs(container, "Hello from Docker!")
34+
35+
assert container._reuse == True
36+
assert testcontainers_config.tc_properties_testcontainers_reuse_enable == False
37+
assert (
38+
"Reuse was requested (`with_reuse`) but the environment does not support the "
39+
+ "reuse of containers. To enable container reuse, add "
40+
+ "'testcontainers.reuse.enable=true' to '~/.testcontainers.properties'."
41+
) in caplog.text
42+
assert Reaper._socket is not None
43+
44+
container.stop()
2745
containers = DockerClient().client.containers.list(all=True)
28-
assert id not in [container.id for container in containers]
46+
assert container._container.id not in [container.id for container in containers]
2947

3048

31-
def test_docker_container_with_reuse_reuse_enabled_ryuk_enabled(monkeypatch):
49+
def test_docker_container_without_reuse_reuse_enabled(monkeypatch):
3250
# Make sure Ryuk cleanup is not active from previous test runs
3351
Reaper.delete_instance()
3452

3553
tc_properties_mock = testcontainers_config.tc_properties | {"testcontainers.reuse.enable": "true"}
3654
monkeypatch.setattr(testcontainers_config, "tc_properties", tc_properties_mock)
37-
monkeypatch.setattr(testcontainers_config, "ryuk_reconnection_timeout", "0.1s")
3855

39-
container = DockerContainer("hello-world").with_reuse().start()
40-
id = container._container.id
56+
container = DockerContainer("hello-world").start()
4157
wait_for_logs(container, "Hello from Docker!")
4258

43-
Reaper._socket.close()
44-
# Sleep until Ryuk reaps all dangling containers
45-
sleep(0.6)
59+
assert container._reuse == False
60+
assert testcontainers_config.tc_properties_testcontainers_reuse_enable == True
61+
assert Reaper._socket is not None
4662

63+
container.stop()
4764
containers = DockerClient().client.containers.list(all=True)
48-
assert id not in [container.id for container in containers]
49-
50-
# Cleanup Ryuk class fields after manual Ryuk shutdown
51-
Reaper.delete_instance()
65+
assert container._container.id not in [container.id for container in containers]
5266

5367

54-
def test_docker_container_with_reuse_reuse_enabled_ryuk_disabled(monkeypatch):
68+
def test_docker_container_with_reuse_reuse_enabled(monkeypatch):
5569
# Make sure Ryuk cleanup is not active from previous test runs
5670
Reaper.delete_instance()
5771

5872
tc_properties_mock = testcontainers_config.tc_properties | {"testcontainers.reuse.enable": "true"}
5973
monkeypatch.setattr(testcontainers_config, "tc_properties", tc_properties_mock)
60-
monkeypatch.setattr(testcontainers_config, "ryuk_disabled", True)
6174

6275
container = DockerContainer("hello-world").with_reuse().start()
63-
id = container._container.id
6476
wait_for_logs(container, "Hello from Docker!")
6577

66-
containers = DockerClient().client.containers.list(all=True)
67-
assert id in [container.id for container in containers]
78+
assert Reaper._socket is None
6879

80+
containers = DockerClient().client.containers.list(all=True)
81+
assert container._container.id in [container.id for container in containers]
6982
# Cleanup after keeping container alive (with_reuse)
7083
container.stop()
7184

@@ -82,8 +95,8 @@ def test_docker_container_with_reuse_reuse_enabled_ryuk_disabled_same_id(monkeyp
8295
id_1 = container_1._container.id
8396
container_2 = DockerContainer("hello-world").with_reuse().start()
8497
id_2 = container_2._container.id
98+
assert Reaper._socket is None
8599
assert id_1 == id_2
86-
87100
# Cleanup after keeping container alive (with_reuse)
88101
container_1.stop()
89102
# container_2.stop() is not needed since it is the same as container_1

0 commit comments

Comments
 (0)