mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-08 19:56:53 +00:00
The variant-3 bootstrap aborts on an upstream guard:
TASK [custom/matrix-bot-baibot : Fail if admin patterns list is empty]
You need to define a required configuration setting
(`matrix_bot_baibot_config_access_admin_patterns`)
which takes the whole playbook down and surfaces only as the generic
"matrix-mdad bootstrap failed inside the container". Nothing asks for that
setting directly: at the pinned MDAD ref 40179e6d4a it is derived from
matrix_admin, which matrix-base defaults to the empty string. The template
rendered every other baibot setting and never set the one they hang off.
matrix_admin could not simply be written out, because "@localpart:server" was
assembled by hand in nine places and the two flavors had already drifted apart
over it: the compose flavor built it from MATRIX_SERVER_NAME while the MDAD
template computed its own onion conditional off DOMAIN_PRIMARY, skipping the
services.matrix.server_name key the role declares. group_vars/all/14_about.yml
had drifted further still and used the raw clearnet name, so on an onion
deployment it published a contact handle that resolves nowhere.
The shape now lives in the mxid filter, which rejects an empty part or a
localpart that already carries a sigil and lowercases the result because
Synapse refuses anything else. The homeserver name lives in the
matrix_server_name lookup, which answers the Tor node when the role is
published under .onion and the declared name otherwise. mxid joins the two, so
every caller names only an account, needs no role variable in scope, and gets
an id that matches whichever network is published. MATRIX_SERVER_NAME now reads
that lookup rather than repeating the conditional, which leaves MATRIX_ONION_NODE
without a consumer, and it goes.
Rendering the replaced Jinja against the new resolver over eighteen input
combinations disagrees three times, each on input no inventory produces - a
whitespace-only Tor node, an uppercase .ONION domain, one with a trailing space -
and each time the new answer is the correct one.
Separately, Nextcloud#12 dies in the same role with
/bin/sh: 1: sudo: not found
because matrix-synapse-usage-exporter pins self_build: true upstream and its
clone task becomes, which the runner image could not do. sudo joins its package
list; the container is already privileged, so this grants nothing new.
Static throughout: the baibot bootstrap had reached ok=196 of roughly 540 tasks
and the usage-exporter self-build never got to its docker build, so both fixes
clear the task that failed and nothing behind it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
81 lines
2.4 KiB
Python
81 lines
2.4 KiB
Python
"""Unit tests for the matrix_server_name lookup plugin.
|
|
|
|
Pins the one choice every Matrix user id depends on: which network's name the
|
|
homeserver answers to. An onion deployment runs Synapse under the Tor node, so
|
|
a user id built on the clearnet name matches no account there, and the reverse
|
|
publishes an unreachable contact handle on a clearnet deployment.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import importlib.util
|
|
import unittest
|
|
import unittest.mock as mock
|
|
|
|
from . import PROJECT_ROOT
|
|
|
|
MODULE = "lookup_matrix_server_name"
|
|
CLEARNET = "matrix.example.com"
|
|
ONION = "jq3cxczghznig7mzqbfy7jlznvi4pv7q53xul2ptvrnsosnfamkhjrid.onion"
|
|
TOR_NODE = "matrix." + ONION
|
|
|
|
|
|
def _load_lookup():
|
|
spec = importlib.util.spec_from_file_location(
|
|
MODULE, str(PROJECT_ROOT / "plugins/lookup/matrix_server_name.py")
|
|
)
|
|
mod = importlib.util.module_from_spec(spec)
|
|
assert spec and spec.loader
|
|
spec.loader.exec_module(mod)
|
|
return mod
|
|
|
|
|
|
class _StubLookup:
|
|
def __init__(self, result):
|
|
self._result = result
|
|
|
|
def run(self, terms, variables=None):
|
|
return [self._result]
|
|
|
|
|
|
class TestResolveServerName(unittest.TestCase):
|
|
def _resolve(self, module, domain, tor_node, server_name):
|
|
def get(name, loader=None, templar=None):
|
|
if name == "domain":
|
|
return _StubLookup(domain)
|
|
|
|
class _Config:
|
|
def run(self, terms, variables=None):
|
|
role = terms[0]
|
|
return [tor_node if role == module.TOR_ROLE else server_name]
|
|
|
|
return _Config()
|
|
|
|
with mock.patch.object(module, "lookup_loader", mock.Mock(get=get)):
|
|
return module.resolve_server_name({}, None, None)
|
|
|
|
def test_an_onion_deployment_answers_under_the_tor_node(self) -> None:
|
|
module = _load_lookup()
|
|
|
|
self.assertEqual(
|
|
self._resolve(module, "matrix." + ONION, TOR_NODE, CLEARNET), TOR_NODE
|
|
)
|
|
|
|
def test_a_clearnet_deployment_keeps_the_declared_name(self) -> None:
|
|
module = _load_lookup()
|
|
|
|
self.assertEqual(self._resolve(module, CLEARNET, TOR_NODE, CLEARNET), CLEARNET)
|
|
|
|
def test_an_onion_domain_without_a_tor_node_falls_back_rather_than_empty(
|
|
self,
|
|
) -> None:
|
|
module = _load_lookup()
|
|
|
|
self.assertEqual(
|
|
self._resolve(module, "matrix." + ONION, "", CLEARNET), CLEARNET
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|