Matrix Docker Ansible eploy
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

592 lines
30 KiB

  1. # SPDX-FileCopyrightText: 2026 Slavi Pantaleev
  2. #
  3. # SPDX-License-Identifier: AGPL-3.0-or-later
  4. ---
  5. # Proves the role drives the real compressor against a genuinely migrated Synapse
  6. # Postgres database, and observes the otherwise-transient container while it runs.
  7. - name: Verify matrix-synapse-auto-compressor
  8. hosts: all
  9. become: true
  10. vars_files:
  11. - "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../molecule-shared/vars.yml"
  12. - "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../molecule-shared/playbook-context.yml"
  13. gather_facts: false
  14. vars:
  15. matrix_synapse_auto_compressor_expected_postgres_location: >-
  16. postgres://molecule_compressor:molecule_compressor_pg_password_9b742d@matrix-postgres-molecule:5432/molecule_compressor
  17. matrix_synapse_auto_compressor_expected_command: >-
  18. synapse_auto_compressor -p $POSTGRES_LOCATION -c 128 -n 2 && sleep 45
  19. matrix_synapse_auto_compressor_seed_username: compressor-admin
  20. matrix_synapse_auto_compressor_seed_password: molecule_compressor_admin_password_1d3b
  21. tasks:
  22. - name: Load the role's defaults under a separate name
  23. ansible.builtin.include_vars:
  24. file: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/defaults/main.yml"
  25. name: matrix_synapse_auto_compressor_role_defaults
  26. - name: Wait for the Synapse fixture to become active
  27. ansible.builtin.systemd_service:
  28. name: matrix-synapse.service
  29. register: matrix_synapse_auto_compressor_synapse_service
  30. until: matrix_synapse_auto_compressor_synapse_service.status.ActiveState == 'active'
  31. retries: 30
  32. delay: 5
  33. failed_when: false
  34. - name: Request the real Synapse health endpoint
  35. ansible.builtin.command:
  36. argv:
  37. - docker
  38. - run
  39. - --rm
  40. - --network={{ matrix_synapse_auto_compressor_container_network }}
  41. - "{{ molecule_shared_image_curl }}"
  42. - --silent
  43. - --show-error
  44. - --write-out
  45. - "\nHTTP_STATUS=%{http_code}"
  46. - http://matrix-synapse:{{ matrix_synapse_container_client_api_port }}/health
  47. register: matrix_synapse_auto_compressor_synapse_health
  48. changed_when: false
  49. until: "'HTTP_STATUS=200' in matrix_synapse_auto_compressor_synapse_health.stdout"
  50. retries: 24
  51. delay: 5
  52. failed_when: false
  53. - name: Assert the real Synapse fixture is healthy and stable
  54. ansible.builtin.assert:
  55. that:
  56. - matrix_synapse_auto_compressor_synapse_service.status.ActiveState == 'active'
  57. - matrix_synapse_auto_compressor_synapse_service.status.NRestarts is defined
  58. - matrix_synapse_auto_compressor_synapse_service.status.NRestarts | int == 0
  59. - matrix_synapse_auto_compressor_synapse_health.rc == 0
  60. - "'HTTP_STATUS=200' in matrix_synapse_auto_compressor_synapse_health.stdout"
  61. - matrix_synapse_auto_compressor_synapse_health.stdout.startswith('OK')
  62. fail_msg: "The real Synapse fixture is not healthy and stable"
  63. success_msg: "The real Synapse fixture is healthy and stable"
  64. # These tables can only be present after Synapse resolved the configured hostname,
  65. # authenticated to Postgres, and performed its own migrations.
  66. - name: List the tables Synapse created in Postgres
  67. ansible.builtin.command:
  68. argv:
  69. - docker
  70. - exec
  71. - matrix-postgres-molecule
  72. - psql
  73. - --username={{ matrix_synapse_database_user }}
  74. - --dbname={{ matrix_synapse_database_database }}
  75. - --tuples-only
  76. - --no-align
  77. - --command=SELECT tablename FROM pg_tables WHERE schemaname = 'public'
  78. register: matrix_synapse_auto_compressor_synapse_tables
  79. changed_when: false
  80. - name: Assert Synapse genuinely migrated the compressor database
  81. ansible.builtin.assert:
  82. that:
  83. - matrix_synapse_auto_compressor_synapse_tables.rc == 0
  84. - "'schema_version' in matrix_synapse_auto_compressor_synapse_table_names"
  85. - "'rooms' in matrix_synapse_auto_compressor_synapse_table_names"
  86. - "'events' in matrix_synapse_auto_compressor_synapse_table_names"
  87. - "'state_groups' in matrix_synapse_auto_compressor_synapse_table_names"
  88. - "'state_groups_state' in matrix_synapse_auto_compressor_synapse_table_names"
  89. - matrix_synapse_auto_compressor_synapse_table_names | length > 50
  90. fail_msg: "Synapse did not genuinely migrate the configured Postgres database"
  91. success_msg: "Synapse genuinely migrated the configured Postgres database"
  92. vars:
  93. matrix_synapse_auto_compressor_synapse_table_names: >-
  94. {{ matrix_synapse_auto_compressor_synapse_tables.stdout_lines | select | list }}
  95. - name: Register the local compressor fixture administrator
  96. ansible.builtin.command:
  97. argv:
  98. - docker
  99. - exec
  100. - matrix-synapse
  101. - register_new_matrix_user
  102. - --config
  103. - /data/homeserver.yaml
  104. - --user
  105. - "{{ matrix_synapse_auto_compressor_seed_username }}"
  106. - --password
  107. - "{{ matrix_synapse_auto_compressor_seed_password }}"
  108. - --admin
  109. - http://localhost:{{ matrix_synapse_container_client_api_port }}
  110. register: matrix_synapse_auto_compressor_registration
  111. changed_when: matrix_synapse_auto_compressor_registration.rc == 0
  112. failed_when:
  113. - matrix_synapse_auto_compressor_registration.rc != 0
  114. - "'User ID already taken' not in matrix_synapse_auto_compressor_registration.stdout"
  115. no_log: true
  116. - name: Log the local fixture administrator in to Synapse
  117. ansible.builtin.command:
  118. argv:
  119. - docker
  120. - run
  121. - --rm
  122. - --network={{ matrix_synapse_auto_compressor_container_network }}
  123. - "{{ molecule_shared_image_curl }}"
  124. - --fail-with-body
  125. - --silent
  126. - --show-error
  127. - --request
  128. - POST
  129. - --header
  130. - 'Content-Type: application/json'
  131. - --data
  132. - >-
  133. {"type":"m.login.password","identifier":{"type":"m.id.user","user":"{{ matrix_synapse_auto_compressor_seed_username }}"},"password":"{{ matrix_synapse_auto_compressor_seed_password }}"}
  134. - http://matrix-synapse:{{ matrix_synapse_container_client_api_port }}/_matrix/client/v3/login
  135. register: matrix_synapse_auto_compressor_login_response
  136. changed_when: false
  137. no_log: true
  138. - name: Parse the local fixture login response
  139. ansible.builtin.set_fact:
  140. matrix_synapse_auto_compressor_login: "{{ matrix_synapse_auto_compressor_login_response.stdout | from_json }}"
  141. no_log: true
  142. - name: Assert Synapse authenticated the local fixture administrator
  143. ansible.builtin.assert:
  144. that:
  145. - matrix_synapse_auto_compressor_login.access_token is string
  146. - matrix_synapse_auto_compressor_login.access_token | length > 20
  147. - matrix_synapse_auto_compressor_login.user_id == '@' + matrix_synapse_auto_compressor_seed_username + ':' + matrix_domain
  148. fail_msg: "Synapse did not authenticate the local compressor fixture administrator"
  149. success_msg: "Synapse authenticated the local compressor fixture administrator"
  150. no_log: true
  151. - name: Create a real Matrix room for compressor state
  152. ansible.builtin.command:
  153. argv:
  154. - docker
  155. - run
  156. - --rm
  157. - --network={{ matrix_synapse_auto_compressor_container_network }}
  158. - "{{ molecule_shared_image_curl }}"
  159. - --fail-with-body
  160. - --silent
  161. - --show-error
  162. - --request
  163. - POST
  164. - --header
  165. - 'Content-Type: application/json'
  166. - --header
  167. - 'Authorization: Bearer {{ matrix_synapse_auto_compressor_login.access_token }}'
  168. - --data
  169. - '{"preset":"private_chat","name":"Compressor Molecule State"}'
  170. - http://matrix-synapse:{{ matrix_synapse_container_client_api_port }}/_matrix/client/v3/createRoom
  171. register: matrix_synapse_auto_compressor_room_response
  172. changed_when: true
  173. no_log: true
  174. - name: Parse the real Matrix room response
  175. ansible.builtin.set_fact:
  176. matrix_synapse_auto_compressor_room: "{{ matrix_synapse_auto_compressor_room_response.stdout | from_json }}"
  177. no_log: true
  178. # A unique state key per request creates enough genuine Synapse state groups for the
  179. # non-default chunk size to consume a complete chunk, without manufacturing database rows.
  180. - name: Populate the room with genuine state transitions through Synapse
  181. ansible.builtin.command:
  182. argv:
  183. - docker
  184. - run
  185. - --rm
  186. - --network={{ matrix_synapse_auto_compressor_container_network }}
  187. - --env=ACCESS_TOKEN={{ matrix_synapse_auto_compressor_login.access_token }}
  188. - --env=ROOM_ID={{ matrix_synapse_auto_compressor_room.room_id }}
  189. - --entrypoint=/bin/sh
  190. - "{{ molecule_shared_image_curl }}"
  191. - -c
  192. - |-
  193. set -eu;
  194. i=1;
  195. while [ "$i" -le 140 ]; do
  196. curl --fail-with-body --silent --show-error \
  197. --request PUT \
  198. --header "Authorization: Bearer $ACCESS_TOKEN" \
  199. --header 'Content-Type: application/json' \
  200. --data "{\"sequence\":$i}" \
  201. "http://matrix-synapse:{{ matrix_synapse_container_client_api_port }}/_matrix/client/v3/rooms/$ROOM_ID/state/com.example.molecule/$i" \
  202. >/dev/null;
  203. i=$((i + 1));
  204. done
  205. register: matrix_synapse_auto_compressor_seed_result
  206. changed_when: matrix_synapse_auto_compressor_seed_result.rc == 0
  207. failed_when: false
  208. no_log: true
  209. - name: Report a sanitized state-seeding failure
  210. ansible.builtin.debug:
  211. msg: "{{ matrix_synapse_auto_compressor_seed_result.stderr }}"
  212. when: matrix_synapse_auto_compressor_seed_result.rc != 0
  213. - name: Assert Synapse accepted every real state transition
  214. ansible.builtin.assert:
  215. that:
  216. - matrix_synapse_auto_compressor_seed_result.rc == 0
  217. fail_msg: "Synapse rejected one of the real Matrix state transitions"
  218. success_msg: "Synapse accepted every real Matrix state transition"
  219. - name: Count genuine state groups for the Matrix room
  220. ansible.builtin.command:
  221. argv:
  222. - docker
  223. - exec
  224. - matrix-postgres-molecule
  225. - psql
  226. - --username={{ matrix_synapse_database_user }}
  227. - --dbname={{ matrix_synapse_database_database }}
  228. - --tuples-only
  229. - --no-align
  230. - >-
  231. --command=SELECT COUNT(*) FROM state_groups
  232. WHERE room_id = '{{ matrix_synapse_auto_compressor_room.room_id }}'
  233. register: matrix_synapse_auto_compressor_state_group_count
  234. changed_when: false
  235. - name: Assert Synapse created enough genuine state groups for a complete chunk
  236. ansible.builtin.assert:
  237. that:
  238. - matrix_synapse_auto_compressor_state_group_count.rc == 0
  239. - matrix_synapse_auto_compressor_state_group_count.stdout | trim | int >= matrix_synapse_auto_compressor_chunk_size | int
  240. fail_msg: "The Matrix API fixture did not create a complete real compressor chunk"
  241. success_msg: "The Matrix API fixture created a complete real compressor chunk"
  242. - name: Read the rendered compressor files
  243. ansible.builtin.slurp:
  244. src: "{{ item }}"
  245. loop:
  246. - "{{ matrix_synapse_auto_compressor_base_path }}/env"
  247. - "{{ matrix_synapse_auto_compressor_base_path }}/matrix-synapse-auto-compressor-fix.sh"
  248. - /etc/systemd/system/matrix-synapse-auto-compressor.service
  249. - /etc/systemd/system/matrix-synapse-auto-compressor.timer
  250. register: matrix_synapse_auto_compressor_rendered_files
  251. - name: Inspect the rendered compressor file identities
  252. ansible.builtin.stat:
  253. path: "{{ item }}"
  254. loop:
  255. - "{{ matrix_synapse_auto_compressor_base_path }}"
  256. - "{{ matrix_synapse_auto_compressor_base_path }}/env"
  257. - "{{ matrix_synapse_auto_compressor_base_path }}/matrix-synapse-auto-compressor-fix.sh"
  258. - /etc/systemd/system/matrix-synapse-auto-compressor.service
  259. - /etc/systemd/system/matrix-synapse-auto-compressor.timer
  260. register: matrix_synapse_auto_compressor_rendered_stats
  261. - name: Parse the rendered compressor files
  262. ansible.builtin.set_fact:
  263. matrix_synapse_auto_compressor_rendered_env: "{{ matrix_synapse_auto_compressor_rendered_files.results[0].content | b64decode }}"
  264. matrix_synapse_auto_compressor_rendered_script: "{{ matrix_synapse_auto_compressor_rendered_files.results[1].content | b64decode }}"
  265. matrix_synapse_auto_compressor_rendered_service: "{{ matrix_synapse_auto_compressor_rendered_files.results[2].content | b64decode }}"
  266. matrix_synapse_auto_compressor_rendered_timer: "{{ matrix_synapse_auto_compressor_rendered_files.results[3].content | b64decode }}"
  267. - name: Check the workaround script syntax
  268. ansible.builtin.command:
  269. argv:
  270. - bash
  271. - -n
  272. - "{{ matrix_synapse_auto_compressor_base_path }}/matrix-synapse-auto-compressor-fix.sh"
  273. register: matrix_synapse_auto_compressor_script_syntax
  274. changed_when: false
  275. - name: Verify systemd parsed the rendered units
  276. ansible.builtin.command:
  277. argv:
  278. - systemd-analyze
  279. - verify
  280. - matrix-synapse-auto-compressor.service
  281. - matrix-synapse-auto-compressor.timer
  282. register: matrix_synapse_auto_compressor_unit_syntax
  283. changed_when: false
  284. - name: Verify systemd parsed the non-default calendar
  285. ansible.builtin.command:
  286. argv:
  287. - systemd-analyze
  288. - calendar
  289. - "{{ matrix_synapse_auto_compressor_schedule }}"
  290. register: matrix_synapse_auto_compressor_calendar_syntax
  291. changed_when: false
  292. - name: Assert the rendered environment carries the exact Postgres connection
  293. ansible.builtin.assert:
  294. that:
  295. - "'POSTGRES_LOCATION=' + matrix_synapse_auto_compressor_expected_postgres_location in matrix_synapse_auto_compressor_rendered_env.splitlines()"
  296. - "'PGHOST=' + matrix_synapse_auto_compressor_database_hostname in matrix_synapse_auto_compressor_rendered_env.splitlines()"
  297. - "'PGDATABASE=' + matrix_synapse_auto_compressor_database_name in matrix_synapse_auto_compressor_rendered_env.splitlines()"
  298. - "'PGUSER=' + matrix_synapse_auto_compressor_database_username in matrix_synapse_auto_compressor_rendered_env.splitlines()"
  299. - "'PGPASSWORD=' + matrix_synapse_auto_compressor_database_password in matrix_synapse_auto_compressor_rendered_env.splitlines()"
  300. fail_msg: "The rendered environment does not carry the exact scenario Postgres connection"
  301. success_msg: "The rendered environment carries the exact scenario Postgres connection"
  302. no_log: true
  303. - name: Assert the rendered workaround script contract
  304. ansible.builtin.assert:
  305. that:
  306. - matrix_synapse_auto_compressor_script_syntax.rc == 0
  307. - "'--user=1234:1234' in matrix_synapse_auto_compressor_rendered_script"
  308. - "'--cap-drop=ALL' in matrix_synapse_auto_compressor_rendered_script"
  309. - "'--network=' + matrix_synapse_auto_compressor_container_network in matrix_synapse_auto_compressor_rendered_script"
  310. - molecule_shared_image_postgres in matrix_synapse_auto_compressor_rendered_script
  311. - "'psql -h ' + matrix_synapse_auto_compressor_database_hostname in matrix_synapse_auto_compressor_rendered_script"
  312. - "'DELETE\nFROM state_compressor_state' in matrix_synapse_auto_compressor_rendered_script"
  313. - "'DELETE\nFROM state_compressor_progress' in matrix_synapse_auto_compressor_rendered_script"
  314. fail_msg: "The rendered workaround script does not carry its runtime and cleanup contract"
  315. success_msg: "The rendered workaround script carries its runtime and cleanup contract"
  316. - name: Assert the rendered oneshot service contract
  317. ansible.builtin.assert:
  318. that:
  319. - matrix_synapse_auto_compressor_unit_syntax.rc == 0
  320. - "'Type=oneshot' in matrix_synapse_auto_compressor_rendered_service"
  321. - "'--rm' in matrix_synapse_auto_compressor_rendered_service"
  322. - "'--log-driver=none' in matrix_synapse_auto_compressor_rendered_service"
  323. - "'--cap-drop=ALL' in matrix_synapse_auto_compressor_rendered_service"
  324. - "'--read-only' in matrix_synapse_auto_compressor_rendered_service"
  325. - "'--user=1234:1234' in matrix_synapse_auto_compressor_rendered_service"
  326. - "'--network=' + matrix_synapse_auto_compressor_container_network in matrix_synapse_auto_compressor_rendered_service"
  327. - "'--label=molecule.contract=synapse-auto-compressor' in matrix_synapse_auto_compressor_rendered_service"
  328. - matrix_synapse_auto_compressor_expected_command in matrix_synapse_auto_compressor_rendered_service
  329. - "'network connect synapse-auto-compressor-extra-molecule matrix-synapse-auto-compressor' in matrix_synapse_auto_compressor_rendered_service"
  330. fail_msg: "The rendered service does not carry the exact oneshot runtime contract"
  331. success_msg: "The rendered service carries the exact oneshot runtime contract"
  332. - name: Assert the rendered non-default timer contract
  333. ansible.builtin.assert:
  334. that:
  335. - matrix_synapse_auto_compressor_calendar_syntax.rc == 0
  336. - "'Unit=matrix-synapse-auto-compressor.service' in matrix_synapse_auto_compressor_rendered_timer"
  337. - "'OnCalendar=Mon..Fri *-*-* 03:17:00' in matrix_synapse_auto_compressor_rendered_timer"
  338. - "'RandomizedDelaySec=47min' in matrix_synapse_auto_compressor_rendered_timer"
  339. fail_msg: "The rendered timer does not carry the non-default schedule"
  340. success_msg: "The rendered timer carries the non-default schedule"
  341. - name: Assert the rendered file identities
  342. ansible.builtin.assert:
  343. that:
  344. - matrix_synapse_auto_compressor_rendered_stats.results[0].stat.uid | int == matrix_user_uid | int
  345. - matrix_synapse_auto_compressor_rendered_stats.results[0].stat.gid | int == matrix_user_gid | int
  346. - matrix_synapse_auto_compressor_rendered_stats.results[0].stat.mode == '0750'
  347. - matrix_synapse_auto_compressor_rendered_stats.results[1].stat.uid | int == matrix_user_uid | int
  348. - matrix_synapse_auto_compressor_rendered_stats.results[1].stat.gid | int == matrix_user_gid | int
  349. - matrix_synapse_auto_compressor_rendered_stats.results[1].stat.mode == '0640'
  350. - matrix_synapse_auto_compressor_rendered_stats.results[2].stat.uid | int == matrix_user_uid | int
  351. - matrix_synapse_auto_compressor_rendered_stats.results[2].stat.gid | int == matrix_user_gid | int
  352. - matrix_synapse_auto_compressor_rendered_stats.results[2].stat.mode == '0750'
  353. - matrix_synapse_auto_compressor_rendered_stats.results[3].stat.uid | int == 0
  354. - matrix_synapse_auto_compressor_rendered_stats.results[3].stat.gid | int == 0
  355. - matrix_synapse_auto_compressor_rendered_stats.results[3].stat.mode == '0644'
  356. - matrix_synapse_auto_compressor_rendered_stats.results[4].stat.uid | int == 0
  357. - matrix_synapse_auto_compressor_rendered_stats.results[4].stat.gid | int == 0
  358. - matrix_synapse_auto_compressor_rendered_stats.results[4].stat.mode == '0644'
  359. fail_msg: "The compressor paths and rendered files have the wrong identity or mode"
  360. success_msg: "The compressor paths and rendered files have the expected identities and modes"
  361. - name: Inspect the enabled compressor timer
  362. ansible.builtin.systemd_service:
  363. name: matrix-synapse-auto-compressor.timer
  364. register: matrix_synapse_auto_compressor_timer
  365. - name: Assert the compressor timer is enabled and active
  366. ansible.builtin.assert:
  367. that:
  368. - matrix_synapse_auto_compressor_timer.status.ActiveState == 'active'
  369. - matrix_synapse_auto_compressor_timer.status.SubState == 'waiting'
  370. - matrix_synapse_auto_compressor_timer.status.UnitFileState == 'enabled'
  371. - matrix_synapse_auto_compressor_timer.status.NextElapseUSecRealtime is defined
  372. - matrix_synapse_auto_compressor_timer.status.NextElapseUSecRealtime != 'infinity'
  373. fail_msg: "The compressor timer is not enabled and waiting on its parsed schedule"
  374. success_msg: "The compressor timer is enabled and waiting on its parsed schedule"
  375. # no_block gives the test a window to inspect this otherwise-transient container. The
  376. # command has already performed genuine compression before its final short sleep.
  377. - name: Start the real compressor asynchronously
  378. ansible.builtin.systemd_service:
  379. name: matrix-synapse-auto-compressor.service
  380. state: started
  381. no_block: true
  382. changed_when: true
  383. - name: Wait for the transient compressor container to become inspectable
  384. ansible.builtin.command:
  385. argv:
  386. - docker
  387. - container
  388. - inspect
  389. - matrix-synapse-auto-compressor
  390. register: matrix_synapse_auto_compressor_container_inspect
  391. changed_when: false
  392. until: matrix_synapse_auto_compressor_container_inspect.rc == 0
  393. retries: 30
  394. delay: 1
  395. failed_when: false
  396. - name: Parse the transient compressor container inspection
  397. ansible.builtin.set_fact:
  398. matrix_synapse_auto_compressor_container: >-
  399. {{ (matrix_synapse_auto_compressor_container_inspect.stdout | from_json) | first }}
  400. - name: Assert the live container uses the exact pinned image
  401. ansible.builtin.assert:
  402. that:
  403. - >-
  404. matrix_synapse_auto_compressor_container.Config.Image ==
  405. 'registry.gitlab.com/mb-saces/rust-synapse-tools:' + matrix_synapse_auto_compressor_role_defaults.matrix_synapse_auto_compressor_version
  406. fail_msg: "The live compressor container does not use the image defaults/main.yml pins"
  407. success_msg: "The live compressor container uses the image defaults/main.yml pins"
  408. - name: Assert the live container process and environment contract
  409. ansible.builtin.assert:
  410. that:
  411. - matrix_synapse_auto_compressor_container.Config.User == '1234:1234'
  412. - matrix_synapse_auto_compressor_container.Config.Entrypoint == ['/bin/sh']
  413. - matrix_synapse_auto_compressor_container.Config.Cmd == ['-c', matrix_synapse_auto_compressor_expected_command]
  414. - "'POSTGRES_LOCATION=' + matrix_synapse_auto_compressor_expected_postgres_location in matrix_synapse_auto_compressor_container.Config.Env"
  415. - "'PGHOST=' + matrix_synapse_auto_compressor_database_hostname in matrix_synapse_auto_compressor_container.Config.Env"
  416. - "'PGDATABASE=' + matrix_synapse_auto_compressor_database_name in matrix_synapse_auto_compressor_container.Config.Env"
  417. - "'PGUSER=' + matrix_synapse_auto_compressor_database_username in matrix_synapse_auto_compressor_container.Config.Env"
  418. - "'PGPASSWORD=' + matrix_synapse_auto_compressor_database_password in matrix_synapse_auto_compressor_container.Config.Env"
  419. fail_msg: "The live compressor process does not carry the exact identity, command, and environment"
  420. success_msg: "The live compressor process carries the exact identity, command, and environment"
  421. no_log: true
  422. - name: Assert the live container security contract
  423. ansible.builtin.assert:
  424. that:
  425. - matrix_synapse_auto_compressor_container.HostConfig.AutoRemove
  426. - matrix_synapse_auto_compressor_container.HostConfig.ReadonlyRootfs
  427. - "'ALL' in matrix_synapse_auto_compressor_container.HostConfig.CapDrop"
  428. - matrix_synapse_auto_compressor_container.HostConfig.LogConfig.Type == 'none'
  429. - matrix_synapse_auto_compressor_container.Mounts | length == 0
  430. fail_msg: "The live compressor container does not carry its ephemeral security isolation"
  431. success_msg: "The live compressor container carries its ephemeral security isolation"
  432. - name: Assert the live container network contract
  433. ansible.builtin.assert:
  434. that:
  435. - matrix_synapse_auto_compressor_container_network in matrix_synapse_auto_compressor_container.NetworkSettings.Networks
  436. - "'synapse-auto-compressor-extra-molecule' in matrix_synapse_auto_compressor_container.NetworkSettings.Networks"
  437. - matrix_synapse_auto_compressor_container.NetworkSettings.Networks | length == 2
  438. fail_msg: "The live compressor container does not have exactly its two configured networks"
  439. success_msg: "The live compressor container has exactly its two configured networks"
  440. - name: Assert the live container publishes no host ports
  441. ansible.builtin.assert:
  442. that:
  443. - matrix_synapse_auto_compressor_container.HostConfig.PortBindings | default({}, true) | length == 0
  444. - matrix_synapse_auto_compressor_container.Config.ExposedPorts | default({}, true) | length == 0
  445. fail_msg: "The live compressor container unexpectedly publishes a host port"
  446. success_msg: "The live compressor container publishes no host ports"
  447. - name: Assert the live container carries the scenario label
  448. ansible.builtin.assert:
  449. that:
  450. - matrix_synapse_auto_compressor_container.Config.Labels['molecule.contract'] == 'synapse-auto-compressor'
  451. fail_msg: "The live compressor container does not carry its configured label"
  452. success_msg: "The live compressor container carries its configured label"
  453. - name: Wait for the oneshot compressor to finish
  454. ansible.builtin.systemd_service:
  455. name: matrix-synapse-auto-compressor.service
  456. register: matrix_synapse_auto_compressor_service
  457. until: matrix_synapse_auto_compressor_service.status.ActiveState in ['inactive', 'failed']
  458. retries: 60
  459. delay: 1
  460. failed_when: false
  461. - name: Assert the real compressor oneshot completed cleanly
  462. ansible.builtin.assert:
  463. that:
  464. - matrix_synapse_auto_compressor_service.status.ActiveState == 'inactive'
  465. - matrix_synapse_auto_compressor_service.status.Result == 'success'
  466. - matrix_synapse_auto_compressor_service.status.ExecMainCode == '1'
  467. - matrix_synapse_auto_compressor_service.status.ExecMainStatus | int == 0
  468. - matrix_synapse_auto_compressor_service.status.NRestarts is defined
  469. - matrix_synapse_auto_compressor_service.status.NRestarts | int == 0
  470. fail_msg: "The real compressor oneshot did not complete cleanly"
  471. success_msg: "The real compressor oneshot completed cleanly"
  472. - name: List the compressor-owned Postgres tables
  473. ansible.builtin.command:
  474. argv:
  475. - docker
  476. - exec
  477. - matrix-postgres-molecule
  478. - psql
  479. - --username={{ matrix_synapse_database_user }}
  480. - --dbname={{ matrix_synapse_database_database }}
  481. - --tuples-only
  482. - --no-align
  483. - --command=SELECT tablename FROM pg_tables WHERE schemaname = 'public' AND tablename LIKE 'state_compressor_%'
  484. register: matrix_synapse_auto_compressor_owned_tables
  485. changed_when: false
  486. - name: Count rows in the compressor-owned progress tables
  487. ansible.builtin.command:
  488. argv:
  489. - docker
  490. - exec
  491. - matrix-postgres-molecule
  492. - psql
  493. - --username={{ matrix_synapse_database_user }}
  494. - --dbname={{ matrix_synapse_database_database }}
  495. - --tuples-only
  496. - --no-align
  497. - >-
  498. --command=SELECT
  499. (SELECT COUNT(*) FROM state_compressor_state) || '|' ||
  500. (SELECT COUNT(*) FROM state_compressor_progress) || '|' ||
  501. (SELECT COUNT(*) FROM state_compressor_total_progress) || '|' ||
  502. (SELECT COUNT(*) FROM state_compressor_state
  503. WHERE room_id = '{{ matrix_synapse_auto_compressor_room.room_id }}') || '|' ||
  504. (SELECT COUNT(*) FROM state_compressor_progress
  505. WHERE room_id = '{{ matrix_synapse_auto_compressor_room.room_id }}')
  506. register: matrix_synapse_auto_compressor_progress_counts
  507. changed_when: false
  508. - name: Assert the real compressor created durable database-side progress
  509. ansible.builtin.assert:
  510. that:
  511. - matrix_synapse_auto_compressor_owned_tables.rc == 0
  512. - "'state_compressor_state' in matrix_synapse_auto_compressor_owned_table_names"
  513. - "'state_compressor_progress' in matrix_synapse_auto_compressor_owned_table_names"
  514. - "'state_compressor_total_progress' in matrix_synapse_auto_compressor_owned_table_names"
  515. - matrix_synapse_auto_compressor_progress_counts.rc == 0
  516. - matrix_synapse_auto_compressor_progress_count_values | length == 5
  517. - matrix_synapse_auto_compressor_progress_count_values[0] | int > 0
  518. - matrix_synapse_auto_compressor_progress_count_values[1] | int > 0
  519. - matrix_synapse_auto_compressor_progress_count_values[2] | int > 0
  520. - matrix_synapse_auto_compressor_progress_count_values[3] | int > 0
  521. - matrix_synapse_auto_compressor_progress_count_values[4] | int > 0
  522. fail_msg: "The real compressor did not leave durable progress for the API-created room"
  523. success_msg: "The real compressor left durable progress for the API-created room and globally"
  524. vars:
  525. matrix_synapse_auto_compressor_owned_table_names: >-
  526. {{ matrix_synapse_auto_compressor_owned_tables.stdout_lines | select | list }}
  527. matrix_synapse_auto_compressor_progress_count_values: >-
  528. {{ matrix_synapse_auto_compressor_progress_counts.stdout | trim | split('|') }}
  529. - name: Confirm the ephemeral compressor container was removed
  530. ansible.builtin.command:
  531. argv:
  532. - docker
  533. - container
  534. - inspect
  535. - matrix-synapse-auto-compressor
  536. register: matrix_synapse_auto_compressor_removed_container
  537. changed_when: false
  538. failed_when: false
  539. - name: Assert the completed compressor container was removed
  540. ansible.builtin.assert:
  541. that:
  542. - matrix_synapse_auto_compressor_removed_container.rc != 0
  543. fail_msg: "The completed ephemeral compressor container was not removed"
  544. success_msg: "The completed ephemeral compressor container was removed"