Skip to content

Commit adbd066

Browse files
Merge pull request #861 from jiridanek/jd_reduce_need_for_TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE
NO-JIRA: chore(tests/containers): improve docker socket detection, reducing the need for `TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE`
2 parents 6628be4 + e87244e commit adbd066

File tree

1 file changed

+33
-2
lines changed

1 file changed

+33
-2
lines changed

tests/containers/conftest.py

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import annotations
22

3-
from typing import TYPE_CHECKING
3+
import os
4+
from typing import Iterable, TYPE_CHECKING
45

56
import testcontainers.core.config
67
import testcontainers.core.container
@@ -11,6 +12,9 @@
1112
if TYPE_CHECKING:
1213
from pytest import ExitCode, Session, Parser, Metafunc
1314

15+
SECURITY_OPTION_ROOTLESS = "name=rootless"
16+
TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE = "TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE"
17+
1418
SHUTDOWN_RYUK = False
1519

1620
# NOTE: Configure Testcontainers through `testcontainers.core.config` and not through env variables.
@@ -26,11 +30,13 @@
2630
testcontainers.core.config.testcontainers_config.ryuk_privileged = True
2731

2832

33+
# https://docs.pytest.org/en/latest/reference/reference.html#pytest.hookspec.pytest_addoption
2934
def pytest_addoption(parser: Parser) -> None:
3035
parser.addoption("--image", action="append", default=[],
3136
help="Image to use, can be specified multiple times")
3237

3338

39+
# https://docs.pytest.org/en/latest/reference/reference.html#pytest.hookspec.pytest_generate_tests
3440
def pytest_generate_tests(metafunc: Metafunc) -> None:
3541
if image.__name__ in metafunc.fixturenames:
3642
metafunc.parametrize(image.__name__, metafunc.config.getoption("--image"))
@@ -43,17 +49,42 @@ def image(request):
4349
yield request.param
4450

4551

52+
# https://docs.pytest.org/en/latest/reference/reference.html#pytest.hookspec.pytest_sessionstart
4653
def pytest_sessionstart(session: Session) -> None:
4754
# first preflight check: ping the Docker API
4855
client = testcontainers.core.docker_client.DockerClient()
4956
assert client.client.ping(), "Failed to connect to Docker"
5057

58+
# determine the local socket path
59+
# NOTE: this will not work for remote docker, but we will cross the bridge when we come to it
60+
socket_path = the_one(adapter.socket_path for adapter in client.client.api.adapters.values())
61+
62+
# set that socket path for ryuk's use, unless user overrode that
63+
if TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE not in os.environ:
64+
testcontainers.core.config.testcontainers_config.ryuk_docker_socket = socket_path
65+
5166
# second preflight check: start the Reaper container
52-
assert testcontainers.core.container.Reaper.get_instance() is not None, "Failed to start Reaper container"
67+
if not testcontainers.core.config.testcontainers_config.ryuk_disabled:
68+
assert testcontainers.core.container.Reaper.get_instance() is not None, "Failed to start Reaper container"
5369

5470

5571
# https://docs.pytest.org/en/latest/reference/reference.html#pytest.hookspec.pytest_sessionfinish
5672
def pytest_sessionfinish(session: Session, exitstatus: int | ExitCode) -> None:
5773
# resolves a shutdown resource leak warning that would be otherwise reported
5874
if SHUTDOWN_RYUK:
5975
testcontainers.core.container.Reaper.delete_instance()
76+
77+
78+
# https://docs.python.org/3/library/functions.html#iter
79+
def the_one[T](iterable: Iterable[T]) -> T:
80+
"""Checks that there is exactly one element in the iterable, and returns it."""
81+
it = iter(iterable)
82+
try:
83+
v = next(it)
84+
except StopIteration:
85+
raise ValueError("No elements in iterable")
86+
try:
87+
next(it)
88+
except StopIteration:
89+
return v
90+
raise ValueError("More than one element in iterable")

0 commit comments

Comments
 (0)