Matrix Docker Ansible eploy
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 

178 строки
8.3 KiB

  1. # SPDX-FileCopyrightText: 2026 Slavi Pantaleev
  2. #
  3. # SPDX-License-Identifier: AGPL-3.0-or-later
  4. ---
  5. # What this proves: the bridge starts, reads the configuration and registration
  6. # the role rendered, opens its appservice port, and is the version the role
  7. # pins. It does NOT bridge anything - there is no WhatsApp on the other side and
  8. # there is deliberately never going to be one. See docs/molecule-testing.md.
  9. - name: Verify mautrix-whatsapp
  10. hosts: all
  11. become: true
  12. vars_files:
  13. - "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../molecule-shared/vars.yml"
  14. - "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../molecule-shared/playbook-context.yml"
  15. gather_facts: false
  16. tasks:
  17. # Read from the role's own defaults rather than pinned in molecule.yml, so
  18. # the version assertion below compares the running image against what the
  19. # role ships instead of against the scenario itself.
  20. - name: Load the role's defaults under a separate name
  21. ansible.builtin.include_vars:
  22. file: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/defaults/main.yml"
  23. name: mautrix_whatsapp_role_defaults
  24. - name: Wait for the mautrix-whatsapp service to become active
  25. ansible.builtin.systemd_service:
  26. name: matrix-mautrix-whatsapp.service
  27. register: mautrix_whatsapp_service
  28. until: mautrix_whatsapp_service.status.ActiveState == 'active'
  29. retries: 30
  30. delay: 5
  31. failed_when: false
  32. # `Restart=always` means a bridge crash-looping on a configuration it cannot
  33. # read still reports `active`, so the restart counter is checked too. It is
  34. # asserted `is defined` because `| int` turns a missing property into 0 and
  35. # would pass vacuously.
  36. - name: Assert the service is active and has not been restarting
  37. ansible.builtin.assert:
  38. that:
  39. - mautrix_whatsapp_service.status.ActiveState == 'active'
  40. - mautrix_whatsapp_service.status.NRestarts is defined
  41. - mautrix_whatsapp_service.status.NRestarts | int == 0
  42. fail_msg: >-
  43. matrix-mautrix-whatsapp.service is
  44. {{ mautrix_whatsapp_service.status.ActiveState | default('unknown') }}
  45. after {{ mautrix_whatsapp_service.status.NRestarts | default('?') }}
  46. automatic restart(s)
  47. success_msg: "matrix-mautrix-whatsapp.service is active and has not restarted"
  48. # The appservice port is the bridge's own listener, the one a homeserver
  49. # would push transactions to. It opening at all means the bridge got through
  50. # reading its configuration and setting itself up.
  51. - name: Wait for the bridge to open its appservice port
  52. ansible.builtin.command:
  53. argv:
  54. - docker
  55. - run
  56. - --rm
  57. - --network={{ matrix_bridge_mautrix_whatsapp_container_network }}
  58. - "{{ molecule_shared_image_curl }}"
  59. - --silent
  60. - --output
  61. - /dev/null
  62. - --write-out
  63. - "HTTP_STATUS=%{http_code}"
  64. - "http://matrix-mautrix-whatsapp:8080/_matrix/mau/live"
  65. register: mautrix_whatsapp_live
  66. changed_when: false
  67. until: "'HTTP_STATUS=000' not in mautrix_whatsapp_live.stdout"
  68. retries: 24
  69. delay: 5
  70. failed_when: false
  71. - name: Assert the bridge answers on its appservice port
  72. ansible.builtin.assert:
  73. that:
  74. - "'HTTP_STATUS=000' not in mautrix_whatsapp_live.stdout"
  75. fail_msg: >-
  76. The bridge did not answer on its appservice port
  77. ({{ mautrix_whatsapp_live.stdout | default('no output') }})
  78. success_msg: "The bridge answers on its appservice port"
  79. - name: Read the configuration the role rendered
  80. ansible.builtin.slurp:
  81. src: "{{ matrix_bridge_mautrix_whatsapp_config_path }}/config.yaml"
  82. register: mautrix_whatsapp_config_file
  83. # Each of these differs from what the bridge would use on its own, so their
  84. # presence means the role's configuration is what the bridge is running on
  85. # rather than something that happened to agree with it.
  86. - name: Assert the rendered configuration carries this scenario's values
  87. ansible.builtin.assert:
  88. that:
  89. - matrix_bridge_mautrix_whatsapp_homeserver_address in mautrix_whatsapp_config_rendered
  90. - matrix_bridge_mautrix_whatsapp_appservice_bot_username in mautrix_whatsapp_config_rendered
  91. - matrix_bridge_mautrix_whatsapp_appservice_token in mautrix_whatsapp_config_rendered
  92. fail_msg: "The rendered configuration does not carry the scenario's values"
  93. success_msg: "The rendered configuration carries the scenario's values"
  94. vars:
  95. mautrix_whatsapp_config_rendered: "{{ mautrix_whatsapp_config_file.content | b64decode }}"
  96. # The registration file is the half of the appservice handshake the
  97. # homeserver reads, and it is generated by the role rather than by the
  98. # bridge, so it is worth checking on its own.
  99. - name: Read the appservice registration the role rendered
  100. ansible.builtin.slurp:
  101. src: "{{ matrix_bridge_mautrix_whatsapp_config_path }}/registration.yaml"
  102. register: mautrix_whatsapp_registration_file
  103. - name: Assert the registration carries the scenario's tokens and bot user
  104. ansible.builtin.assert:
  105. that:
  106. - matrix_bridge_mautrix_whatsapp_appservice_token in mautrix_whatsapp_registration_rendered
  107. - matrix_bridge_mautrix_whatsapp_homeserver_token in mautrix_whatsapp_registration_rendered
  108. - matrix_bridge_mautrix_whatsapp_appservice_bot_username in mautrix_whatsapp_registration_rendered
  109. fail_msg: "The appservice registration does not carry the scenario's tokens and bot user"
  110. success_msg: "The appservice registration carries the scenario's tokens and bot user"
  111. vars:
  112. mautrix_whatsapp_registration_rendered: "{{ mautrix_whatsapp_registration_file.content | b64decode }}"
  113. # sqlite was chosen in molecule.yml, so the bridge should have created its
  114. # database under the role's data path. This is the cheap proof that the data
  115. # path reached the process and is writable by the uid the role runs it as.
  116. - name: Look for the bridge's sqlite database under the role's data path
  117. ansible.builtin.stat:
  118. path: "{{ matrix_bridge_mautrix_whatsapp_data_path }}/mautrix-whatsapp.db"
  119. register: mautrix_whatsapp_database
  120. - name: Assert the bridge created its database where the role put its data path
  121. ansible.builtin.assert:
  122. that:
  123. - mautrix_whatsapp_database.stat.exists
  124. - mautrix_whatsapp_database.stat.uid | int == matrix_user_uid | int
  125. fail_msg: >-
  126. The bridge did not create its database under
  127. {{ matrix_bridge_mautrix_whatsapp_data_path }}, or it is not owned by
  128. uid {{ matrix_user_uid }}
  129. success_msg: "The bridge created its database under the role's data path, as the role's uid"
  130. - name: Read the image of the running container
  131. ansible.builtin.command:
  132. argv:
  133. - docker
  134. - container
  135. - inspect
  136. - matrix-mautrix-whatsapp
  137. - --format
  138. - "{{ '{{' }} .Config.Image {{ '}}' }}"
  139. register: mautrix_whatsapp_image
  140. changed_when: false
  141. - name: Assert the running container is the version defaults/main.yml pins
  142. ansible.builtin.assert:
  143. that:
  144. - mautrix_whatsapp_role_defaults.matrix_bridge_mautrix_whatsapp_version in mautrix_whatsapp_image.stdout
  145. fail_msg: >-
  146. The running container is {{ mautrix_whatsapp_image.stdout }}, which does
  147. not carry the pinned version
  148. {{ mautrix_whatsapp_role_defaults.matrix_bridge_mautrix_whatsapp_version }}
  149. success_msg: "The running container is the version defaults/main.yml pins"
  150. - name: Read the labels the role rendered
  151. ansible.builtin.slurp:
  152. src: "{{ matrix_bridge_mautrix_whatsapp_base_path }}/labels"
  153. register: mautrix_whatsapp_labels
  154. - name: Assert no Traefik labels are emitted while Traefik support is disabled
  155. ansible.builtin.assert:
  156. that:
  157. - "'traefik.' not in (mautrix_whatsapp_labels.content | b64decode)"
  158. fail_msg: >-
  159. Traefik labels were emitted even though
  160. matrix_bridge_mautrix_whatsapp_container_labels_traefik_enabled is false
  161. success_msg: "No Traefik labels are emitted while Traefik support is disabled"