Files
computer-playbook/tests/unit/python/roles/web-app-matrix/test_ca_trust_passthrough.py
T
kevinveenbirkenbachandClaude Opus 5 98707e06f4 test(matrix): hold the CA passthrough guard to the repo's own conventions
The guard landed in 2acf91e18 breaking two rules it should have followed from
the start, and `make quality-high` caught both:

    test_ca_trust_passthrough.py:23: `parents[N]` index expression
    test_ca_trust_passthrough.py:23: `PROJECT_ROOT` assignment outside `__init__.py`
    test_ca_trust_passthrough.py:44: .read_text(...) uncached

So `PROJECT_ROOT` moves into the package `__init__.py`, where every other role
test suite keeps it, and both template reads go through `read_text` from
`utils.cache.files` so a second reader of the same file pays one open.

Verified with the flags the suite actually runs under. scripts/tests/code/run.sh
passes `--import-mode=importlib` and `consider_namespace_packages=true`, which
is what makes a hyphenated `roles/<role>/` directory importable at all; a plain
`pytest <path>` fails the relative import here and does so for the existing
sys-svc-mail-msmtp suite too, which is the control that says the pattern is
right and the invocation was wrong. Under those flags both suites pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-10 02:01:19 +02:00

73 lines
2.7 KiB
Python

"""Every CA path synapse binds must reach the matrix container at that path.
The mdad stack runs its own Docker daemon inside the matrix container, so a
bind source in ``matrix_synapse_container_extra_arguments`` is resolved in that
container's mount namespace rather than on the host. A path the compose service
never passes through therefore does not exist where synapse looks for it, and
``docker create`` refuses the unit before anything is logged about Matrix.
Run 34348821577 lost a job to exactly that: ``vars.yml.j2`` mounted
``CA_TRUST.bundle_host`` while ``services.yml.j2`` passed only
``CA_TRUST.cert_host``, and synapse crash-looped on "bind source path does not
exist". The templates are read as text because rendering them needs a full
Ansible context, and the invariant is about what the two files say to each
other, not about the values.
"""
from __future__ import annotations
import re
import unittest
from utils.cache.files import read_text
from . import PROJECT_ROOT
_MATRIX = PROJECT_ROOT / "roles/web-app-matrix/templates/flavor/ansible"
_BOUND_BY_SYNAPSE = re.compile(r"src='?\s*~?\s*CA_TRUST\.(\w+)")
_PASSED_THROUGH = re.compile(
r"\{\{\s*CA_TRUST\.(\w+)\s*\}\}\s*:\s*\{\{\s*CA_TRUST\.(\w+)\s*\}\}"
)
class TestCaTrustPassthrough(unittest.TestCase):
def test_every_ca_path_synapse_mounts_is_passed_through_at_the_same_path(
self,
) -> None:
wanted = set(_BOUND_BY_SYNAPSE.findall(read_text(str(_MATRIX / "vars.yml.j2"))))
self.assertTrue(
wanted,
"no CA_TRUST bind source found in vars.yml.j2 — the regex no longer "
"matches how synapse's extra arguments are built, so this test has "
"stopped guarding anything",
)
services = read_text(str(_MATRIX / "services.yml.j2"))
same_path = {
source
for source, target in _PASSED_THROUGH.findall(services)
if source == target
}
missing = sorted(wanted - same_path)
self.assertFalse(
missing,
"synapse binds CA_TRUST."
+ ", CA_TRUST.".join(missing)
+ " inside the nested daemon, but services.yml.j2 does not pass "
"it into the matrix container at the same absolute path. The "
"nested daemon resolves the source in the container's namespace, "
"so docker create fails with 'bind source path does not exist' "
"and matrix-synapse never starts. Add "
+ " and ".join(
f"`- {{{{ CA_TRUST.{name} }}}}:{{{{ CA_TRUST.{name} }}}}:ro`"
for name in missing
)
+ " to the self_signed block.",
)
if __name__ == "__main__": # pragma: no cover
unittest.main()