Adapted discourse version to new code after the big refactoring

This commit is contained in:
Kevin Veen-Birkenbach 2025-07-20 09:29:56 +02:00
parent 1b9775ccb5
commit d86ca6cc0e
No known key found for this signature in database
GPG Key ID: 44D8F11FD62F878E
11 changed files with 81 additions and 21 deletions

View File

@ -13,6 +13,12 @@ class FilterModule(object):
seen_domains = {} seen_domains = {}
for app_id, cfg in apps.items(): for app_id, cfg in apps.items():
if not isinstance(cfg, dict):
raise AnsibleFilterError(
f"Invalid configuration for application '{app_id}': "
f"expected a dict, got {cfg!r}"
)
domains_cfg = cfg.get('domains') domains_cfg = cfg.get('domains')
if not domains_cfg or 'canonical' not in domains_cfg: if not domains_cfg or 'canonical' not in domains_cfg:
self._add_default_domain(app_id, primary_domain, seen_domains, result) self._add_default_domain(app_id, primary_domain, seen_domains, result)

View File

@ -2,6 +2,7 @@ import os
import re import re
import yaml import yaml
from ansible.errors import AnsibleFilterError from ansible.errors import AnsibleFilterError
from collections.abc import Mapping
from ansible.errors import AnsibleUndefinedVariable from ansible.errors import AnsibleUndefinedVariable
try: try:
@ -62,12 +63,15 @@ def get_app_conf(applications, application_id, config_path, strict=True, default
return default if default is not None else False return default if default is not None else False
raise AppConfigKeyError( raise AppConfigKeyError(
f"Key '{k}' is undefined at '{'.'.join(path_trace)}'\n" f"Key '{k}' is undefined at '{'.'.join(path_trace)}'\n"
f" actual type: {type(obj).__name__}\n"
f" repr(obj): {obj!r}\n"
f" repr(applications): {applications!r}\n"
f"application_id: {application_id}\n" f"application_id: {application_id}\n"
f"config_path: {config_path}" f"config_path: {config_path}"
) )
# Access dict key # Access dict key
if isinstance(obj, dict): if isinstance(obj, Mapping):
if k not in obj: if k not in obj:
# Non-strict mode: always return default on missing key # Non-strict mode: always return default on missing key
if not strict: if not strict:

View File

@ -1,2 +1,3 @@
# Todo # Todo
- Finish LDAP implementation - Finish LDAP implementation
- Check if this current network setting makes sense. Seems a bit unneccessary complicated. Could be that a more straight foreword approach makes more sense.

View File

@ -32,3 +32,16 @@ docker:
volumes: volumes:
data: discourse_data data: discourse_data
network: discourse network: discourse
plugins:
docker_manager:
enabled: true
discourse-activity-pub:
enabled: true
discourse-akismet:
enabled: true
discourse-cakeday:
enabled: true
discourse-solved:
enabled: true
discourse-voting:
enabled: true

View File

@ -7,7 +7,7 @@
failed_when: container_action.failed and 'No such container' not in container_action.msg failed_when: container_action.failed and 'No such container' not in container_action.msg
listen: recreate discourse listen: recreate discourse
- name: "add central database temporary to {{ discourse_network }}" - name: "add central database temporary to discourse network"
command: "docker network connect {{ discourse_network }} {{ database_host }}" command: "docker network connect {{ discourse_network }} {{ database_host }}"
failed_when: > failed_when: >
result.rc != 0 and result.rc != 0 and

View File

@ -35,9 +35,10 @@
template: template:
src: config.yml.j2 src: config.yml.j2
dest: "{{ discourse_application_yml_destination }}" dest: "{{ discourse_application_yml_destination }}"
mode: '0640'
notify: recreate discourse notify: recreate discourse
- name: "Verify that {{ discourse_container }} is running" - name: "Verify that '{{ discourse_container }}' is running"
command: docker compose ps --filter status=running --format '{{"{{"}}.Name{{"}}"}}' | grep -x {{ discourse_container }} command: docker compose ps --filter status=running --format '{{"{{"}}.Name{{"}}"}}' | grep -x {{ discourse_container }}
register: docker_ps register: docker_ps
changed_when: docker_ps.rc == 1 changed_when: docker_ps.rc == 1
@ -62,13 +63,17 @@
when: when:
- applications | get_app_conf(application_id, 'features.central_database', False) - applications | get_app_conf(application_id, 'features.central_database', False)
- name: Set error string for network not connected
set_fact:
docker_discourse_not_connected: 'is not connected to network {{ discourse_network }}'
- name: "Remove {{ discourse_network }} from {{ database_host }}" - name: "Remove {{ discourse_network }} from {{ database_host }}"
command: > command: >
docker network disconnect {{ discourse_network }} {{ database_host }} docker network disconnect {{ discourse_network }} {{ database_host }}
register: network_disconnect register: network_disconnect
failed_when: > failed_when: >
network_disconnect.rc != 0 and network_disconnect.rc != 0 and
'is not connected to network {{ discourse_network }}' not in network_disconnect.stderr docker_discourse_not_connected not in network_disconnect.stderr
changed_when: network_disconnect.rc == 0 changed_when: network_disconnect.rc == 0
when: when:
- applications | get_app_conf(application_id, 'features.central_database', False) - applications | get_app_conf(application_id, 'features.central_database', False)

View File

@ -74,7 +74,7 @@ env:
DISCOURSE_DB_NAME: {{ database_name }} DISCOURSE_DB_NAME: {{ database_name }}
# Redis Configuration # Redis Configuration
DISCOURSE_REDIS_HOST: {{application_id}}-redis DISCOURSE_REDIS_HOST: {{ discourse_redis_host }}
## If you added the Lets Encrypt template, uncomment below to get a free SSL certificate ## If you added the Lets Encrypt template, uncomment below to get a free SSL certificate
#LETSENCRYPT_ACCOUNT_EMAIL: administrator@veen.world #LETSENCRYPT_ACCOUNT_EMAIL: administrator@veen.world
@ -103,18 +103,11 @@ hooks:
- exec: - exec:
cd: $home/plugins cd: $home/plugins
cmd: cmd:
- git clone --depth=1 https://github.com/discourse/docker_manager.git {% for plugin_name, plugin_config in discourse_plugins.items() %}
- git clone --depth=1 https://github.com/discourse/discourse-activity-pub.git {% if plugin_config.enabled %}
- git clone --depth=1 https://github.com/discourse/discourse-calendar.git - git clone --depth=1 https://github.com/discourse/{{ plugin_name }}.git
- git clone --depth=1 https://github.com/discourse/discourse-akismet.git
- git clone --depth=1 https://github.com/discourse/discourse-cakeday.git
- git clone --depth=1 https://github.com/discourse/discourse-solved.git
- git clone --depth=1 https://github.com/discourse/discourse-voting.git
- git clone --depth=1 https://github.com/discourse/discourse-oauth2-basic.git
{% if applications | get_app_conf(application_id, 'features.oidc', False) %}
- git clone --depth=1 https://github.com/discourse/discourse-openid-connect.git
{% endif %} {% endif %}
{% endfor %}
{% if applications | get_app_conf(application_id, 'features.ldap', False) %} {% if applications | get_app_conf(application_id, 'features.ldap', False) %}
- git clone --depth=1 https://github.com/jonmbake/discourse-ldap-auth.git - git clone --depth=1 https://github.com/jonmbake/discourse-ldap-auth.git
@ -177,5 +170,5 @@ run:
- exec: echo "End of custom commands" - exec: echo "End of custom commands"
docker_args: docker_args:
- --network={{application_id}}_default - --network={{ discourse_network }}
- --name={{ discourse_container }} - --name={{ discourse_container }}

View File

@ -4,5 +4,5 @@
redis: redis:
{% include 'roles/docker-compose/templates/networks.yml.j2' %} {% include 'roles/docker-compose/templates/networks.yml.j2' %}
discourse_default: {{ discourse_network }}:
external: true external: true

View File

@ -6,10 +6,12 @@ database_type: "postgres"
# Discourse # Discourse
discourse_container: "{{ applications | get_app_conf(application_id, 'docker.services.discourse.name') }}" discourse_container: "{{ applications | get_app_conf(application_id, 'docker.services.discourse.name') }}"
discourse_application_yml_destination: "{{ docker_repository_directory }}containers/{{ discourse_container }}.yml"
discourse_network: "{{ applications | get_app_conf(application_id, 'docker.network') }}" discourse_network: "{{ applications | get_app_conf(application_id, 'docker.network') }}"
discourse_volume: "{{ applications | get_app_conf(application_id, 'docker.volumes.data') }}" discourse_volume: "{{ applications | get_app_conf(application_id, 'docker.volumes.data') }}"
discourse_plugins: "{{ applications | get_app_conf(application_id, 'plugins') }}"
discourse_pg_network: "{{ applications | get_app_conf('svc-db-postgres', 'docker.network' ) }}" discourse_pg_network: "{{ applications | get_app_conf('svc-db-postgres', 'docker.network' ) }}"
discourse_application_yml_destination: "{{ docker_repository_directory }}containers/{{ discourse_container }}.yml"
discourse_redis_host: "{{ application_id |get_entity_name }}-redis"
# General Docker Configuration # General Docker Configuration
docker_repository_directory : "{{ docker_compose.directories.services}}{{applications | get_app_conf( application_id, 'repository') }}/" docker_repository_directory : "{{ docker_compose.directories.services}}{{applications | get_app_conf( application_id, 'repository') }}/"

View File

@ -16,7 +16,7 @@
- name: Merge application definitions - name: Merge application definitions
set_fact: set_fact:
applications: "{{ defaults_applications | combine(applications | default({}, true), recursive=True) }}" applications: "{{ defaults_applications | merge_with_defaults(applications | default({}, true)) }}"
- name: Merge current play applications - name: Merge current play applications
set_fact: set_fact:

View File

@ -0,0 +1,36 @@
import unittest
import yaml
from pathlib import Path
class HandlerNameIntegrationTest(unittest.TestCase):
"""
Integration test to ensure that handler definitions in Ansible roles
do not include Jinja variable interpolations in their 'name' attribute.
"""
def test_handlers_have_no_variables_in_name(self):
# Locate all handler YAML files under roles/*/handlers/
handler_files = Path('roles').glob('*/handlers/*.yml')
for handler_file in handler_files:
with self.subTest(handler_file=str(handler_file)):
content = handler_file.read_text(encoding='utf-8')
# Load all documents in the YAML file
documents = list(yaml.safe_load_all(content))
for index, doc in enumerate(documents):
if not isinstance(doc, dict):
continue
# Only consider entries that are handlers (they have a 'listen' key)
if 'listen' in doc:
name = doc.get('name', '')
# Assert that no Jinja interpolation is present in the name
self.assertNotRegex(
name,
r"{{.*}}",
msg=(
f"Handler 'name' in file {handler_file} document #{index} "
f"contains a Jinja variable: {name}"
)
)
if __name__ == '__main__':
unittest.main()