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

220 строки
10 KiB

  1. # SPDX-FileCopyrightText: 2026 Slavi Pantaleev
  2. #
  3. # SPDX-License-Identifier: AGPL-3.0-or-later
  4. ---
  5. - name: Verify Tuwunel
  6. hosts: all
  7. become: true
  8. vars_files:
  9. - "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../molecule-shared/vars.yml"
  10. - "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../molecule-shared/playbook-context.yml"
  11. gather_facts: false
  12. vars:
  13. matrix_tuwunel_molecule_config: "{{ (matrix_tuwunel_molecule_config_result.stdout | from_json).global }}"
  14. matrix_tuwunel_molecule_probe: "{{ matrix_tuwunel_molecule_probe_result.stdout | from_json }}"
  15. matrix_tuwunel_molecule_container: "{{ (matrix_tuwunel_molecule_inspect.stdout | from_json) | first }}"
  16. tasks:
  17. - name: Load the role's defaults under a separate name
  18. ansible.builtin.include_vars:
  19. file: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/defaults/main.yml"
  20. name: matrix_tuwunel_role_defaults
  21. # No host ports: a helper reaches the service over its own container network.
  22. - name: Wait for the Matrix versions endpoint on the configured listener
  23. ansible.builtin.command:
  24. argv:
  25. - docker
  26. - run
  27. - --rm
  28. - --network={{ matrix_tuwunel_container_network }}
  29. - "{{ molecule_shared_image_curl }}"
  30. - --fail
  31. - --silent
  32. - --show-error
  33. - --max-time
  34. - '10'
  35. - http://matrix-tuwunel:{{ matrix_tuwunel_config_port_number }}/_matrix/client/versions
  36. register: matrix_tuwunel_molecule_versions
  37. changed_when: false
  38. until: matrix_tuwunel_molecule_versions.rc == 0
  39. retries: 24
  40. delay: 5
  41. - name: Assert the non-default listener serves the Matrix API
  42. ansible.builtin.assert:
  43. that:
  44. - "'v1.1' in (matrix_tuwunel_molecule_versions.stdout | from_json).versions"
  45. - name: Request the default listener which the scenario moved away from
  46. ansible.builtin.command:
  47. argv:
  48. - docker
  49. - run
  50. - --rm
  51. - --network={{ matrix_tuwunel_container_network }}
  52. - "{{ molecule_shared_image_curl }}"
  53. - --silent
  54. - --output
  55. - /dev/null
  56. - --connect-timeout
  57. - '2'
  58. - --max-time
  59. - '3'
  60. - http://matrix-tuwunel:6167/_matrix/client/versions
  61. register: matrix_tuwunel_molecule_default_listener
  62. changed_when: false
  63. failed_when: false
  64. - name: Assert the default listener refuses connections
  65. ansible.builtin.assert:
  66. that:
  67. - matrix_tuwunel_molecule_default_listener.rc == 7
  68. # This uses the real homeserver and its embedded RocksDB database. The helper
  69. # only makes requests and records responses; the assertions remain below.
  70. - name: Exercise token-protected registration and authenticated Matrix APIs
  71. ansible.builtin.command:
  72. argv:
  73. - docker
  74. - run
  75. - --rm
  76. - --interactive
  77. - --network={{ matrix_tuwunel_container_network }}
  78. - "{{ molecule_shared_image_python }}"
  79. - python
  80. - '-'
  81. - http://matrix-tuwunel:{{ matrix_tuwunel_config_port_number }}
  82. - "{{ matrix_tuwunel_config_registration_token }}"
  83. stdin: "{{ lookup('file', 'probe.py') }}"
  84. register: matrix_tuwunel_molecule_probe_result
  85. changed_when: false
  86. - name: Assert registration requires the configured token
  87. ansible.builtin.assert:
  88. that:
  89. - matrix_tuwunel_molecule_probe.challenge.status == 401
  90. - "matrix_tuwunel_molecule_probe.challenge.body.flows == [{'stages': ['m.login.registration_token']}]"
  91. - matrix_tuwunel_molecule_probe.bad_token.status == 401
  92. - matrix_tuwunel_molecule_probe.bad_token.body.errcode == 'M_FORBIDDEN'
  93. - name: Assert the configured token registers a user on the configured server
  94. ansible.builtin.assert:
  95. that:
  96. - matrix_tuwunel_molecule_probe.registration.status == 200
  97. - matrix_tuwunel_molecule_probe.registration.body.user_id == '@' + matrix_tuwunel_molecule_probe.username + ':' + matrix_tuwunel_config_server_name
  98. - matrix_tuwunel_molecule_probe.whoami.status == 200
  99. - matrix_tuwunel_molecule_probe.whoami.body.user_id == matrix_tuwunel_molecule_probe.registration.body.user_id
  100. - name: Assert the configured display-name suffix reaches new users
  101. ansible.builtin.assert:
  102. that:
  103. - matrix_tuwunel_molecule_probe.profile.status == 200
  104. - matrix_tuwunel_molecule_probe.profile.body.displayname == matrix_tuwunel_molecule_probe.username + ' ' + matrix_tuwunel_config_new_user_displayname_suffix
  105. - name: Assert the authenticated media API advertises the configured upload limit
  106. ansible.builtin.assert:
  107. that:
  108. - matrix_tuwunel_molecule_probe.media.status == 200
  109. - matrix_tuwunel_molecule_probe.media.body['m.upload.size'] == matrix_tuwunel_config_max_request_size
  110. - name: Assert client discovery serves the configured URL
  111. ansible.builtin.assert:
  112. that:
  113. - matrix_tuwunel_molecule_probe.well_known.status == 200
  114. # Tuwunel normalizes the configured origin to a URL with a trailing slash.
  115. - matrix_tuwunel_molecule_probe.well_known.body['m.homeserver'].base_url == matrix_tuwunel_config_well_known_client.rstrip('/') + '/'
  116. - name: Parse the rendered TOML configuration
  117. ansible.builtin.command:
  118. argv:
  119. - python3
  120. - '-c'
  121. - "import json, sys, tomllib; print(json.dumps(tomllib.load(open(sys.argv[1], 'rb'))))"
  122. - "{{ matrix_tuwunel_config_path }}/tuwunel.toml"
  123. register: matrix_tuwunel_molecule_config_result
  124. changed_when: false
  125. - name: Assert the parsed TOML carries the scenario's settings
  126. ansible.builtin.assert:
  127. that:
  128. - matrix_tuwunel_molecule_config.server_name == matrix_tuwunel_config_server_name
  129. - matrix_tuwunel_molecule_config.port == matrix_tuwunel_config_port_number
  130. - matrix_tuwunel_molecule_config.allow_registration
  131. - matrix_tuwunel_molecule_config.registration_token == matrix_tuwunel_config_registration_token
  132. - matrix_tuwunel_molecule_config.new_user_displayname_suffix == matrix_tuwunel_config_new_user_displayname_suffix
  133. - matrix_tuwunel_molecule_config.max_request_size == matrix_tuwunel_config_max_request_size
  134. - matrix_tuwunel_molecule_config.well_known.client == matrix_tuwunel_config_well_known_client
  135. - not matrix_tuwunel_molecule_config.allow_federation
  136. - matrix_tuwunel_molecule_config.trusted_servers == []
  137. - not matrix_tuwunel_molecule_config.grant_admin_to_first_user
  138. - name: Inspect the running Tuwunel container
  139. ansible.builtin.command:
  140. argv: [docker, container, inspect, matrix-tuwunel]
  141. register: matrix_tuwunel_molecule_inspect
  142. changed_when: false
  143. - name: Assert the running container uses the exact image pinned by the role
  144. ansible.builtin.assert:
  145. that:
  146. - matrix_tuwunel_molecule_container.Config.Image == 'ghcr.io/matrix-construct/tuwunel:' + matrix_tuwunel_role_defaults.matrix_tuwunel_version
  147. - name: Assert the running container uses the playbook identity and isolation
  148. ansible.builtin.assert:
  149. that:
  150. - matrix_tuwunel_molecule_container.Config.User == (matrix_user_uid | string) + ':' + (matrix_user_gid | string)
  151. - matrix_tuwunel_molecule_container.HostConfig.ReadonlyRootfs
  152. - "'ALL' in matrix_tuwunel_molecule_container.HostConfig.CapDrop"
  153. - name: Assert the role's configuration is mounted read-only and selected at runtime
  154. ansible.builtin.assert:
  155. that:
  156. - "'TUWUNEL_CONFIG=/etc/tuwunel/tuwunel.toml' in matrix_tuwunel_molecule_container.Config.Env"
  157. - matrix_tuwunel_molecule_mount.Source == matrix_tuwunel_config_path
  158. - not matrix_tuwunel_molecule_mount.RW
  159. vars:
  160. matrix_tuwunel_molecule_mount: >-
  161. {{ matrix_tuwunel_molecule_container.Mounts
  162. | selectattr('Destination', 'equalto', '/etc/tuwunel') | first }}
  163. - name: Assert the embedded database has the configured writable data mount
  164. ansible.builtin.assert:
  165. that:
  166. - matrix_tuwunel_molecule_mount.Source == matrix_tuwunel_data_path
  167. - matrix_tuwunel_molecule_mount.RW
  168. vars:
  169. matrix_tuwunel_molecule_mount: >-
  170. {{ matrix_tuwunel_molecule_container.Mounts
  171. | selectattr('Destination', 'equalto', '/var/lib/tuwunel') | first }}
  172. - name: Assert the container uses only the scenario network and publishes no ports
  173. ansible.builtin.assert:
  174. that:
  175. - matrix_tuwunel_molecule_container.NetworkSettings.Networks.keys() | list == [matrix_tuwunel_container_network]
  176. - matrix_tuwunel_molecule_container.HostConfig.PortBindings | default({}, true) == {}
  177. - name: Assert Traefik targets the configured listener and public hostname
  178. ansible.builtin.assert:
  179. that:
  180. - matrix_tuwunel_molecule_labels['traefik.http.services.matrix-tuwunel.loadbalancer.server.port'] == matrix_tuwunel_config_port_number | string
  181. - matrix_tuwunel_molecule_labels['traefik.http.routers.matrix-tuwunel-public-client-api.rule'] == 'Host(`' + matrix_tuwunel_hostname + '`) && PathPrefix(`/_matrix`)'
  182. - matrix_tuwunel_molecule_labels['traefik.http.routers.matrix-tuwunel-public-tuwunel-api.rule'] == 'Host(`' + matrix_tuwunel_hostname + '`) && PathPrefix(`/_tuwunel`)'
  183. - matrix_tuwunel_molecule_labels['traefik.http.routers.matrix-tuwunel-public-client-api.entrypoints'] == matrix_tuwunel_container_labels_traefik_entrypoints
  184. vars:
  185. matrix_tuwunel_molecule_labels: "{{ matrix_tuwunel_molecule_container.Config.Labels }}"
  186. # Check after the API probes: Restart=always alone can hide a crash loop.
  187. - name: Read the Tuwunel service state after the probes
  188. ansible.builtin.systemd_service:
  189. name: matrix-tuwunel.service
  190. register: matrix_tuwunel_molecule_service
  191. - name: Assert the service is active without automatic restarts
  192. ansible.builtin.assert:
  193. that:
  194. - matrix_tuwunel_molecule_service.status.ActiveState == 'active'
  195. - matrix_tuwunel_molecule_service.status.NRestarts is defined
  196. - matrix_tuwunel_molecule_service.status.NRestarts | int == 0