Skip to content

Commit c8e5709

Browse files
committed
Fix vault test container name collision and startup failures
Monkey-patch Container.terminate() to poll Docker until the container name is fully released before returning. The upstream implementation calls container.remove(force=True) + container.wait(), but wait() returns as soon as the process stops — Docker may not have released the name yet. When parameterized vault fixtures reuse the same name across versions, the next containers.run() gets a 409 "name already in use" error. Also add SKIP_SETCAP=1 to the vault container environment so that vault v2.0+ does not attempt setcap (which requires CAP_SETFCAP). Workaround for saltstack/pytest-salt-factories#198
1 parent 6f4e504 commit c8e5709

2 files changed

Lines changed: 63 additions & 0 deletions

File tree

tests/pytests/functional/modules/test_vault.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import time
44

55
import pytest
6+
from saltfactories.daemons.container import Container
67

78
import salt.utils.path
89
from tests.support.runtests import RUNTIME_VARS
@@ -16,6 +17,35 @@
1617

1718
log = logging.getLogger(__name__)
1819

20+
# Workaround for https://github.com/saltstack/pytest-salt-factories/issues/198
21+
# Container.terminate() does not wait for Docker to fully release the container
22+
# name, causing 409 "name already in use" errors when parameterized fixtures
23+
# recreate a container immediately after termination.
24+
_original_terminate = Container.terminate
25+
26+
27+
def _terminate_and_wait(self):
28+
"""
29+
Call the original terminate and then poll Docker until the container
30+
name is fully released. This prevents 409 "name already in use"
31+
errors when a new container is created immediately after termination.
32+
"""
33+
if self._terminate_result is not None:
34+
return self._terminate_result
35+
name = self.name
36+
client = self.docker_client
37+
result = _original_terminate(self)
38+
for _ in range(30):
39+
try:
40+
client.containers.get(name)
41+
time.sleep(1)
42+
except Exception: # pylint: disable=broad-except
43+
break
44+
return result
45+
46+
47+
Container.terminate = _terminate_and_wait # pylint: disable=E9502
48+
1949

2050
@pytest.fixture(scope="module")
2151
def minion_config_overrides(vault_port):
@@ -61,6 +91,7 @@ def vault_container_version(request, salt_factories, vault_port, shell):
6191
"environment": {
6292
"VAULT_DEV_ROOT_TOKEN_ID": "testsecret",
6393
"VAULT_LOCAL_CONFIG": json.dumps(config),
94+
"SKIP_SETCAP": "1",
6495
},
6596
"cap_add": ["IPC_LOCK"],
6697
},

tests/pytests/integration/sdb/test_vault.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,43 @@
99

1010
import pytest
1111
from pytestshellutils.utils.processes import ProcessResult
12+
from saltfactories.daemons.container import Container
1213

1314
import salt.utils.path
1415
from tests.support.helpers import PatchedEnviron
1516
from tests.support.runtests import RUNTIME_VARS
1617

1718
log = logging.getLogger(__name__)
1819

20+
# Workaround for https://github.com/saltstack/pytest-salt-factories/issues/198
21+
# Container.terminate() does not wait for Docker to fully release the container
22+
# name, causing 409 "name already in use" errors when parameterized fixtures
23+
# recreate a container immediately after termination.
24+
_original_terminate = Container.terminate
25+
26+
27+
def _terminate_and_wait(self):
28+
"""
29+
Call the original terminate and then poll Docker until the container
30+
name is fully released. This prevents 409 "name already in use"
31+
errors when a new container is created immediately after termination.
32+
"""
33+
if self._terminate_result is not None:
34+
return self._terminate_result
35+
name = self.name
36+
client = self.docker_client
37+
result = _original_terminate(self)
38+
for _ in range(30):
39+
try:
40+
client.containers.get(name)
41+
time.sleep(1)
42+
except Exception: # pylint: disable=broad-except
43+
break
44+
return result
45+
46+
47+
Container.terminate = _terminate_and_wait # pylint: disable=E9502
48+
1949

2050
pytestmark = [
2151
pytest.mark.slow_test,
@@ -47,6 +77,7 @@ def vault_container_version(request, salt_factories, vault_port, patched_environ
4777
"default_lease_ttl": "168h",
4878
"max_lease_ttl": "720h",
4979
}
80+
5081
factory = salt_factories.get_container(
5182
"vault",
5283
f"ghcr.io/saltstack/salt-ci-containers/vault:{vault_version}",
@@ -56,6 +87,7 @@ def vault_container_version(request, salt_factories, vault_port, patched_environ
5687
"environment": {
5788
"VAULT_DEV_ROOT_TOKEN_ID": "testsecret",
5889
"VAULT_LOCAL_CONFIG": json.dumps(config),
90+
"SKIP_SETCAP": "1",
5991
},
6092
"cap_add": ["IPC_LOCK"],
6193
},

0 commit comments

Comments
 (0)