mirror of
https://github.com/spantaleev/matrix-docker-ansible-deploy.git
synced 2026-09-25 01:00:12 +00:00
Test the Molecule scenarios against Postgres rather than sqlite
`group_vars/matrix_servers` selects postgres whenever postgres is enabled, which is the default, so postgres is what essentially every deployment runs. The scenarios were testing sqlite - a path almost nobody is on. How little that path is used is not a guess: the mautrix-meta bridges could not start at all under sqlite, and nobody reported it. Testing the engine users are actually on is worth more than keeping coverage of the one they are not, so no scenario is left behind on sqlite. Four of the eight scenarios have a database and are converted; the other four have none and are untouched. molecule-shared/tasks/postgres.yml stands Postgres up on the scenario's network, with the data directory on a tmpfs since it is thrown away with the container. The image is pinned at the major the postgres role deploys to new installations and left to Renovate: when a new major lands, the PR bumping that pin runs every scenario against it, which is the earliest warning we get that a component does not cope. Each scenario gives its database and user names that differ from the role's defaults, so the component reaching the database proves the role built its connection string out of them. The assertions moved from "a file appeared at the path we configured" to "these tables exist", which is strictly stronger: tables can only appear once the component has resolved the hostname, authenticated with the credentials the role rendered, and run its migrations to completion. Costs about 10 seconds per affected scenario (115s to 125s locally for mautrix-whatsapp), on jobs that run in parallel. Gotcha worth recording: since Postgres 18 the image puts PGDATA in a versioned subdirectory and refuses to start if it finds a mount at the old /var/lib/postgresql/data, so the tmpfs is mounted at /var/lib/postgresql. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SEH3vxYSQ5SV4N5z61eyGT
This commit is contained in:
co-authored by
Claude Opus 5
parent
c447e1528b
commit
85f80a3c7e
@@ -61,10 +61,15 @@ provisioner:
|
||||
matrix:
|
||||
device_name: Molecule Reminder Bot
|
||||
|
||||
# Moved off the role's default name so verify.yml can assert the bot opened the path
|
||||
# the role gave it, with the default name as a negative control.
|
||||
matrix_bot_matrix_reminder_bot_sqlite_database_path_local: /matrix/matrix-reminder-bot/data/molecule-reminders.db
|
||||
matrix_bot_matrix_reminder_bot_sqlite_database_path_in_container: /data/molecule-reminders.db
|
||||
# Postgres, because that is what `group_vars/matrix_servers` selects whenever postgres
|
||||
# is enabled - which is the default, so it is what essentially every real deployment
|
||||
# runs. prepare.yml stands one up. Name and user differ from the role's defaults, so
|
||||
# reaching the database proves the role built its connection string out of these.
|
||||
matrix_bot_matrix_reminder_bot_database_engine: postgres
|
||||
matrix_bot_matrix_reminder_bot_database_hostname: matrix-postgres-molecule
|
||||
matrix_bot_matrix_reminder_bot_database_name: molecule_reminder_bot
|
||||
matrix_bot_matrix_reminder_bot_database_username: molecule_reminder_bot
|
||||
matrix_bot_matrix_reminder_bot_database_password: molecule_pg_password_3c9b02
|
||||
|
||||
# verify.yml runs as its own play, where the role's defaults are out of scope,
|
||||
# so the paths it reads are pinned here to match what the role derives.
|
||||
|
||||
@@ -74,6 +74,15 @@
|
||||
# Not an appservice: it logs in with the username and password the role rendered, retrying
|
||||
# every 15 seconds until that succeeds. The stub answers with an access token, which is
|
||||
# enough to reach the sync loop. Nothing is asserted about the stub itself.
|
||||
- name: Ensure Postgres is running
|
||||
ansible.builtin.include_tasks:
|
||||
file: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../molecule-shared/tasks/postgres.yml"
|
||||
vars:
|
||||
molecule_shared_postgres_network: "{{ matrix_bot_matrix_reminder_bot_container_network }}"
|
||||
molecule_shared_postgres_database: "{{ matrix_bot_matrix_reminder_bot_database_name }}"
|
||||
molecule_shared_postgres_username: "{{ matrix_bot_matrix_reminder_bot_database_username }}"
|
||||
molecule_shared_postgres_password: "{{ matrix_bot_matrix_reminder_bot_database_password }}"
|
||||
|
||||
- name: Ensure the homeserver stub is running
|
||||
ansible.builtin.include_tasks:
|
||||
file: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../molecule-shared/tasks/homeserver-stub.yml"
|
||||
|
||||
@@ -97,9 +97,9 @@
|
||||
- name: Assert the bot opened the database engine the role selected
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- "\"Database initialization of type 'sqlite' complete\" in matrix_bot_matrix_reminder_bot_journal.stdout"
|
||||
fail_msg: "The bot did not report a completed SQLite database initialization"
|
||||
success_msg: "The bot initialized the SQLite database the role pointed it at"
|
||||
- "\"Database initialization of type 'postgres' complete\" in matrix_bot_matrix_reminder_bot_journal.stdout"
|
||||
fail_msg: "The bot did not report a completed Postgres database initialization"
|
||||
success_msg: "The bot initialized the Postgres database the role pointed it at"
|
||||
|
||||
- name: Read the configuration file the role rendered
|
||||
ansible.builtin.slurp:
|
||||
@@ -116,7 +116,9 @@
|
||||
- matrix_bot_matrix_reminder_bot_matrix_homeserver_url in matrix_bot_matrix_reminder_bot_config_rendered
|
||||
- matrix_bot_matrix_reminder_bot_reminders_timezone in matrix_bot_matrix_reminder_bot_config_rendered
|
||||
- matrix_bot_matrix_reminder_bot_command_prefix in matrix_bot_matrix_reminder_bot_config_rendered
|
||||
- "'sqlite://' + matrix_bot_matrix_reminder_bot_sqlite_database_path_in_container in matrix_bot_matrix_reminder_bot_config_rendered"
|
||||
- matrix_bot_matrix_reminder_bot_database_username in matrix_bot_matrix_reminder_bot_config_rendered
|
||||
- matrix_bot_matrix_reminder_bot_database_name in matrix_bot_matrix_reminder_bot_config_rendered
|
||||
- matrix_bot_matrix_reminder_bot_database_hostname in matrix_bot_matrix_reminder_bot_config_rendered
|
||||
- "'@molecule-allowed:molecule.local' in matrix_bot_matrix_reminder_bot_config_rendered"
|
||||
- "'.*:blocked.molecule.local' in matrix_bot_matrix_reminder_bot_config_rendered"
|
||||
fail_msg: "The rendered configuration does not carry the scenario's settings"
|
||||
@@ -138,41 +140,35 @@
|
||||
vars:
|
||||
matrix_bot_matrix_reminder_bot_config_rendered: "{{ matrix_bot_matrix_reminder_bot_config_file.content | b64decode }}"
|
||||
|
||||
# With no HTTP surface, where the database landed is the evidence that the storage
|
||||
# configuration reached the running process and not merely the file on disk.
|
||||
- name: Stat the database at the path the scenario configured
|
||||
ansible.builtin.stat:
|
||||
path: "{{ matrix_bot_matrix_reminder_bot_sqlite_database_path_local }}"
|
||||
register: matrix_bot_matrix_reminder_bot_database
|
||||
# With no HTTP surface, the schema in Postgres is the evidence that the storage
|
||||
# configuration reached the running process rather than only the file on disk. The bot can
|
||||
# only have created tables by resolving the hostname, authenticating with the credentials
|
||||
# the role rendered, and running its migrations.
|
||||
- name: List the tables the bot created in Postgres
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- docker
|
||||
- exec
|
||||
- matrix-postgres-molecule
|
||||
- psql
|
||||
- --username={{ matrix_bot_matrix_reminder_bot_database_username }}
|
||||
- --dbname={{ matrix_bot_matrix_reminder_bot_database_name }}
|
||||
- --tuples-only
|
||||
- --no-align
|
||||
- --command=SELECT tablename FROM pg_tables WHERE schemaname = 'public'
|
||||
register: matrix_bot_matrix_reminder_bot_tables
|
||||
changed_when: false
|
||||
|
||||
- name: Assert the database landed under the role's data path, owned by the role's user
|
||||
- name: Assert the bot created its schema in the database the role pointed it at
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- matrix_bot_matrix_reminder_bot_database.stat.exists
|
||||
- matrix_bot_matrix_reminder_bot_database.stat.uid == matrix_user_uid
|
||||
- matrix_bot_matrix_reminder_bot_database.stat.gid == matrix_user_gid
|
||||
- matrix_bot_matrix_reminder_bot_tables.rc == 0
|
||||
- matrix_bot_matrix_reminder_bot_table_names | length > 0
|
||||
fail_msg: >-
|
||||
{{ matrix_bot_matrix_reminder_bot_sqlite_database_path_local }} is missing or is not
|
||||
owned by {{ matrix_user_uid }}:{{ matrix_user_gid }}
|
||||
success_msg: >-
|
||||
The database is at the configured path, owned by {{ matrix_user_uid }}:{{ matrix_user_gid }}
|
||||
|
||||
# Negative control for the assertion above: the role's own default database name must NOT
|
||||
# appear, or a file at the configured path would prove nothing.
|
||||
- name: Stat the database name the role would have used by default
|
||||
ansible.builtin.stat:
|
||||
path: "{{ matrix_bot_matrix_reminder_bot_data_path }}/bot.db"
|
||||
register: matrix_bot_matrix_reminder_bot_default_database
|
||||
|
||||
- name: Assert the role's default database name was not used
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- not matrix_bot_matrix_reminder_bot_default_database.stat.exists
|
||||
fail_msg: >-
|
||||
{{ matrix_bot_matrix_reminder_bot_data_path }}/bot.db exists as well, so the
|
||||
database at the configured path does not prove the role's storage
|
||||
configuration reached the bot
|
||||
success_msg: "Only the configured database path was used"
|
||||
The bot created no tables in {{ matrix_bot_matrix_reminder_bot_database_name }}
|
||||
success_msg: "The bot created its schema in the database the role pointed it at"
|
||||
vars:
|
||||
matrix_bot_matrix_reminder_bot_table_names: "{{ matrix_bot_matrix_reminder_bot_tables.stdout_lines | select | list }}"
|
||||
|
||||
# matrix-nio writes its encryption store here once login succeeds, so a populated directory
|
||||
# means the bot could use the store path the role created inside a read-only container.
|
||||
|
||||
Reference in New Issue
Block a user