mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-08 11:46:35 +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>
53 lines
1.9 KiB
Python
53 lines
1.9 KiB
Python
"""Build the Matrix identifiers whose shape several templates repeat.
|
|
|
|
A Matrix user id is ``@<localpart>:<server_name>``. Six templates of
|
|
web-app-matrix assembled it by hand, which is how the MDAD flavor came to use a
|
|
different server name than the compose flavor. The shape lives here and the
|
|
server name stays in ``MATRIX_SERVER_NAME``, so a caller supplies only the
|
|
localpart and the homeserver it belongs to.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from ansible.errors import AnsibleFilterError
|
|
|
|
SIGIL = "@"
|
|
SEPARATOR = ":"
|
|
FORBIDDEN = (SIGIL, SEPARATOR, "/")
|
|
|
|
|
|
def mxid(localpart: str, server_name: str) -> str:
|
|
"""Return the Matrix user id of ``localpart`` on ``server_name``.
|
|
|
|
Args:
|
|
localpart: the user's name without sigil or server, e.g. ``alice``. A
|
|
leading ``@`` is accepted and dropped so a caller may pass either.
|
|
server_name: the homeserver's name, normally ``MATRIX_SERVER_NAME``.
|
|
|
|
Returns:
|
|
``@<localpart>:<server_name>``, lowercased: Synapse rejects a user id
|
|
that is not, and the callers read usernames from inventory.
|
|
|
|
Raises:
|
|
AnsibleFilterError: either part is empty, or the localpart still
|
|
carries a sigil, a separator or a slash after the leading ``@``.
|
|
"""
|
|
name = str(localpart or "").strip().removeprefix(SIGIL)
|
|
server = str(server_name or "").strip()
|
|
if not name:
|
|
raise AnsibleFilterError("mxid: the localpart is empty")
|
|
if not server:
|
|
raise AnsibleFilterError(f"mxid: no server name for localpart '{name}'")
|
|
bad = [character for character in FORBIDDEN if character in name]
|
|
if bad:
|
|
raise AnsibleFilterError(
|
|
f"mxid: localpart '{name}' carries {' and '.join(bad)}; "
|
|
"pass the bare name, not a user id"
|
|
)
|
|
return f"{SIGIL}{name}{SEPARATOR}{server}".lower()
|
|
|
|
|
|
class FilterModule:
|
|
def filters(self):
|
|
return {"mxid": mxid}
|