mirror of
				https://github.com/kevinveenbirkenbach/computer-playbook.git
				synced 2025-11-04 04:08:15 +00:00 
			
		
		
		
	Adapted discourse version to new code after the big refactoring
This commit is contained in:
		@@ -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)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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.
 | 
				
			||||||
@@ -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
 | 
				
			||||||
@@ -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
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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 }}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
@@ -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') }}/"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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:
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										36
									
								
								tests/integration/test_handlers_no_vars_in_name.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								tests/integration/test_handlers_no_vars_in_name.py
									
									
									
									
									
										Normal 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()
 | 
				
			||||||
		Reference in New Issue
	
	Block a user