mirror of
				https://github.com/kevinveenbirkenbach/computer-playbook.git
				synced 2025-10-31 18:29:21 +00:00 
			
		
		
		
	Fixed BBB stuff
This commit is contained in:
		
							
								
								
									
										0
									
								
								cli/build/inventory/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								cli/build/inventory/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -9,6 +9,7 @@ | ||||
|   listen: | ||||
|     - docker compose up | ||||
|     - docker compose restart | ||||
|     - docker compose just up | ||||
|  | ||||
| - name: Build docker  | ||||
|   command: | ||||
| @@ -19,21 +20,26 @@ | ||||
|     DOCKER_CLIENT_TIMEOUT: 600 | ||||
|   listen:  | ||||
|     - docker compose build | ||||
|     - docker compose up     # This is just here because I didn't took the time to refactor | ||||
|                             # @todo go over all docker compose up implementations and check where it makes sense to user docker compose build and where docker compose up | ||||
|  | ||||
| - name: docker compose up | ||||
|   shell: docker-compose -p {{ application_id | get_entity_name }} up -d --force-recreate --remove-orphans | ||||
|   shell: | | ||||
|     if [ -f "{{ docker_compose.files.env }}" ]; then | ||||
|       docker compose -p {{ application_id | get_entity_name }} --env-file "{{ docker_compose.files.env }} up -d --force-recreate --remove-orphans" | ||||
|     else | ||||
|       docker compose -p {{ application_id | get_entity_name }} up -d --force-recreate --remove-orphans | ||||
|     fi | ||||
|   args: | ||||
|     chdir: "{{ docker_compose.directories.instance }}" | ||||
|     executable: /bin/bash | ||||
|   environment: | ||||
|     COMPOSE_HTTP_TIMEOUT: 600 | ||||
|     DOCKER_CLIENT_TIMEOUT: 600 | ||||
|   listen: docker compose up | ||||
|   listen: | ||||
|     - docker compose up | ||||
|     - docker compose just up # @todo replace later just up by up when code is refactored, build atm is also listening to up | ||||
|  | ||||
| - name: docker compose restart | ||||
|   command: | ||||
|     cmd: "docker compose restart" | ||||
|     cmd: 'docker compose restart' | ||||
|     chdir: "{{docker_compose.directories.instance}}" | ||||
|   listen: docker compose restart | ||||
|   | ||||
							
								
								
									
										72
									
								
								roles/web-app-bigbluebutton/filter_plugins/compose_mods.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								roles/web-app-bigbluebutton/filter_plugins/compose_mods.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,72 @@ | ||||
| import re | ||||
| import yaml | ||||
|  | ||||
| def compose_mods(yml_text, docker_repository_path, env_file): | ||||
|     yml_text = re.sub(r'\./data/postgres:/var/lib/postgresql/data', 'database:/var/lib/postgresql/data', yml_text) | ||||
|     yml_text = re.sub(r'\./data/bigbluebutton:/var/bigbluebutton', 'bigbluebutton:/var/bigbluebutton', yml_text) | ||||
|     yml_text = re.sub(r'\./data/freeswitch-meetings:/var/freeswitch/meetings', 'freeswitch:/var/freeswitch/meetings', yml_text) | ||||
|     yml_text = re.sub(r'\./data/greenlight:/usr/src/app/storage', 'greenlight:/usr/src/app/storage', yml_text) | ||||
|     yml_text = re.sub(r'\./data/mediasoup:/var/mediasoup', 'mediasoup:/var/mediasoup', yml_text) | ||||
|     yml_text = re.sub(r'\./', docker_repository_path + '/', yml_text) | ||||
|     yml_text = re.sub( | ||||
|         r'(^\s*context:\s*)' + re.escape(docker_repository_path) + r'/mod/(.*)', | ||||
|         r'\1' + docker_repository_path + r'/mod/\2', | ||||
|         yml_text, flags=re.MULTILINE | ||||
|     ) | ||||
|     yml_text = re.sub( | ||||
|         r'(^\s*context:\s*)mod/(.*)', | ||||
|         r'\1' + docker_repository_path + r'/mod/\2', | ||||
|         yml_text, flags=re.MULTILINE | ||||
|     ) | ||||
|  | ||||
|     try: | ||||
|         data = yaml.safe_load(yml_text) | ||||
|         services = data.get('services', {}) | ||||
|         for name, svc in services.items(): | ||||
|             svc['env_file'] = [env_file] | ||||
|             if name == 'redis': | ||||
|                 vols = svc.get('volumes') | ||||
|                 if not vols or not isinstance(vols, list): | ||||
|                     svc['volumes'] = ['redis:/data'] | ||||
|                 elif 'redis:/data' not in vols: | ||||
|                     svc['volumes'].append('redis:/data') | ||||
|             if name == 'coturn': | ||||
|                 vols = svc.get('volumes') | ||||
|                 if not vols or not isinstance(vols, list): | ||||
|                     svc['volumes'] = ['coturn:/var/lib/coturn'] | ||||
|                 elif 'coturn:/var/lib/coturn' not in vols: | ||||
|                     svc['volumes'].append('coturn:/var/lib/coturn') | ||||
|             if name == 'bbb-graphql-server': | ||||
|                 svc['healthcheck'] = { | ||||
|                     'test': ['CMD', 'curl', '-f', 'http://localhost:8085/healthz'], | ||||
|                     'interval': '30s', | ||||
|                     'timeout': '10s', | ||||
|                     'retries': 5, | ||||
|                     'start_period': '10s' | ||||
|                 } | ||||
|         data['services'] = services | ||||
|  | ||||
|         # **ADD THIS BLOCK:** | ||||
|         # Only add volumes block if not present | ||||
|         if 'volumes' not in data: | ||||
|             data['volumes'] = { | ||||
|                 'database': None, | ||||
|                 'greenlight': None, | ||||
|                 'redis': None, | ||||
|                 'coturn': None, | ||||
|                 'freeswitch': None, | ||||
|                 'bigbluebutton': None, | ||||
|                 'mediasoup': None | ||||
|             } | ||||
|  | ||||
|         yml_text = yaml.dump(data, default_flow_style=False, sort_keys=False) | ||||
|     except Exception: | ||||
|         pass | ||||
|  | ||||
|     return yml_text | ||||
|  | ||||
| class FilterModule(object): | ||||
|     def filters(self): | ||||
|         return { | ||||
|             'compose_mods': compose_mods, | ||||
|         } | ||||
| @@ -6,107 +6,14 @@ | ||||
|     COMPOSE_HTTP_TIMEOUT: 600 | ||||
|     DOCKER_CLIENT_TIMEOUT: 600 | ||||
|  | ||||
| - name: Copy docker-compose.yml from origin to final location | ||||
| - name: Slurp docker-compose.yml from remote host | ||||
|   slurp: | ||||
|     src: "{{ docker_compose_file_origine }}" | ||||
|   register: compose_slurp | ||||
|  | ||||
| - name: Transform docker-compose.yml with compose_mods | ||||
|   copy: | ||||
|     src:  "{{ docker_compose_file_origine }}" | ||||
|     content: "{{ compose_slurp.content | b64decode | compose_mods(docker_repository_path, docker_compose.files.env) }}" | ||||
|     dest: "{{ docker_compose_file_final }}" | ||||
|     remote_src: yes | ||||
|  | ||||
| - name: Replace bind mounts by named volume mounts | ||||
|   replace: | ||||
|     path: "{{ docker_compose_file_final }}" | ||||
|     regexp: "{{ item.regexp }}" | ||||
|     replace: "{{ item.replace }}" | ||||
|   loop: | ||||
|     - { regexp: '\./data/postgres:/var/lib/postgresql/data', replace: 'database:/var/lib/postgresql/data' } | ||||
|     - { regexp: '\./data/bigbluebutton:/var/bigbluebutton', replace: 'bigbluebutton:/var/bigbluebutton' } | ||||
|     - { regexp: '\./data/freeswitch-meetings:/var/freeswitch/meetings', replace: 'freeswitch:/var/freeswitch/meetings' } | ||||
|     - { regexp: '\./data/greenlight:/usr/src/app/storage', replace: 'greenlight:/usr/src/app/storage' } | ||||
|     - { regexp: '\./data/mediasoup:/var/mediasoup', replace: 'mediasoup:/var/mediasoup' } | ||||
|  | ||||
| - name: add volume to redis | ||||
|   lineinfile: | ||||
|     path: "{{ docker_compose_file_final }}" | ||||
|     insertafter: "^\\s*redis:" | ||||
|     line: "    volumes:\n      - redis:/data" | ||||
|     firstmatch: yes | ||||
|  | ||||
| - name: add volume to coturn | ||||
|   lineinfile: | ||||
|     path: "{{ docker_compose_file_final }}" | ||||
|     insertafter: "- ./mod/coturn/turnserver.conf:/etc/coturn/turnserver.conf" | ||||
|     line: "      - coturn:/var/lib/coturn" | ||||
|  | ||||
| # Implemented due to etherpad health bug. | ||||
| # @todo Remove when health check is working fine | ||||
| # @see https://chatgpt.com/c/67a0fc7e-5104-800f-bb6b-3731e2f83b7b | ||||
| #- name: "Update docker-compose.yml for Etherpad health check" | ||||
| #  lineinfile:  | ||||
| #    line: "    healthcheck:\n      test: [\"CMD\", \"curl\", \"-f\", \"http://127.0.0.1:9001\"]\n      interval: 30s\n      timeout: 10s\n      retries: 5\n      start_period: 10s" | ||||
| #    path: "{{docker_compose_file_final}}" | ||||
| #    insertafter: "etherpad:" | ||||
| #  listen: setup bigbluebutton | ||||
|  | ||||
| - name: Add volumes block after services in docker compose | ||||
|   blockinfile: | ||||
|     path: "{{ docker_compose_file_final }}" | ||||
|     block: | | ||||
|       volumes: | ||||
|         database: | ||||
|         greenlight: | ||||
|         redis: | ||||
|         coturn: | ||||
|         freeswitch: | ||||
|         bigbluebutton: | ||||
|         mediasoup: | ||||
|     marker: "# {mark} ANSIBLE MANAGED BLOCK FOR VOLUMES" | ||||
|     insertbefore: "^services:" | ||||
|  | ||||
| - name: Replace all './' with '/services/' in docker-compose.yml | ||||
|   ansible.builtin.replace: | ||||
|     path:     "{{ docker_compose_file_final }}" | ||||
|     regexp:   '\./' | ||||
|     replace:  '{{ docker_repository_path }}/' | ||||
|  | ||||
| - name: Prefix build context with docker_repository_path | ||||
|   ansible.builtin.replace: | ||||
|     path: "{{ docker_compose_file_final }}" | ||||
|     regexp: '(^\s*context:\s*)mod/(.*)' | ||||
|     replace: '\1{{ docker_repository_path }}/mod/\2' | ||||
|  | ||||
| - name: "Update healthcheck for bbb-graphql-server" | ||||
|   # This is neccessary because the healthcheck doesn't listen to the correct port | ||||
|   lineinfile:  | ||||
|     line: "    healthcheck:\n      test: [\"CMD\", \"curl\", \"-f\", \"http://localhost:8085/healthz\"]\n      interval: 30s\n      timeout: 10s\n      retries: 5\n      start_period: 10s" | ||||
|     path: "{{docker_compose_file_final}}" | ||||
|     insertafter: "bbb-graphql-server:" | ||||
|  | ||||
| - name: Add env_file to each service in docker-compose.yml | ||||
|   blockinfile: | ||||
|     path: "{{ docker_compose_file_final }}" | ||||
|     insertafter: '^  {{ service }}:$' | ||||
|     marker: "# {mark} ANSIBLE MANAGED BLOCK FOR ENV_FILE" | ||||
|     block: | | ||||
|         env_file: | ||||
|           - "{{ docker_compose.files.env }}" | ||||
|   loop: | ||||
|     - bbb-web | ||||
|     - freeswitch | ||||
|     - nginx | ||||
|     - etherpad | ||||
|     - bbb-pads | ||||
|     - bbb-export-annotations | ||||
|     - redis | ||||
|     - webrtc-sfu | ||||
|     - fsesl-akka | ||||
|     - apps-akka | ||||
|     - bbb-graphql-server | ||||
|     - bbb-graphql-actions | ||||
|     - bbb-graphql-middleware | ||||
|     - collabora | ||||
|     - periodic | ||||
|     - coturn | ||||
|     - greenlight | ||||
|     - postgres | ||||
|   loop_control: | ||||
|     loop_var: service | ||||
|   notify: | ||||
|     - docker compose just up | ||||
|   | ||||
| @@ -35,15 +35,29 @@ | ||||
| - name: "Setup docker-compose.yml file" | ||||
|   include_tasks: "docker-compose.yml" | ||||
|  | ||||
| - name: Ensure all containers in instance are running | ||||
|   include_tasks: "{{ playbook_dir }}/roles/docker-compose/tasks/04_ensure_up.yml" | ||||
|  | ||||
| - name: flush docker service | ||||
|   meta: flush_handlers | ||||
|  | ||||
| - name: Wait for BigBlueButton | ||||
|   wait_for: | ||||
|     host: "{{ domains | get_domain('web-app-bigbluebutton') }}" | ||||
|     port: 80 | ||||
|     delay: 5 | ||||
|     timeout: 300 | ||||
| - name: "Get greenlight container name" | ||||
|   shell: | | ||||
|     docker compose ps -q greenlight | ||||
|   args: | ||||
|     chdir: "{{ docker_compose.directories.instance }}" | ||||
|   register: greenlight_id | ||||
|  | ||||
| - name: "Wait until BigBlueButton (greenlight) is running" | ||||
|   shell: | | ||||
|     docker inspect --format='{{'{{'}}.State.Status{{'}}'}}' {{ greenlight_id.stdout }} | ||||
|   args: | ||||
|     chdir: "{{ docker_compose.directories.instance }}" | ||||
|   register: bbb_state | ||||
|   until: bbb_state.stdout.strip() == "running" | ||||
|   retries: 30 | ||||
|   delay: 5 | ||||
|   changed_when: false | ||||
|  | ||||
| - name: create admin | ||||
|   command: | ||||
|   | ||||
| @@ -5,7 +5,7 @@ features: | ||||
|   # itself wouldn't be possible  | ||||
|   matomo:             false  | ||||
|   css:                false | ||||
|   port-ui-desktop:    true | ||||
|   port-ui-desktop:    false  # Didn't work in frame didn't have high priority @todo figure out pcause and solve it | ||||
|   central_database:   true | ||||
|   oauth2:             false | ||||
| csp: | ||||
|   | ||||
| @@ -15,6 +15,7 @@ | ||||
|     dest: "{{openproject_plugins_folder}}Gemfile.plugins" | ||||
|   notify: | ||||
|     - docker compose up | ||||
|     - docker compose build | ||||
|  | ||||
| - name: "create {{dummy_volume}}" | ||||
|   file: | ||||
|   | ||||
							
								
								
									
										0
									
								
								tests/unit/roles/web-app-bigbluebutton/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								tests/unit/roles/web-app-bigbluebutton/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,145 @@ | ||||
| import os | ||||
| import unittest | ||||
| import sys | ||||
| import yaml | ||||
|  | ||||
| sys.path.insert( | ||||
|     0, | ||||
|     os.path.abspath( | ||||
|         os.path.join( | ||||
|             os.path.dirname(__file__), | ||||
|             '../../../../../roles/web-app-bigbluebutton/filter_plugins' | ||||
|         ) | ||||
|     ) | ||||
| ) | ||||
|  | ||||
| from compose_mods import compose_mods | ||||
|  | ||||
| def sort_dict(obj): | ||||
|     if isinstance(obj, dict): | ||||
|         return {k: sort_dict(obj[k]) for k in sorted(obj)} | ||||
|     elif isinstance(obj, list): | ||||
|         return [sort_dict(v) for v in obj] | ||||
|     else: | ||||
|         return obj | ||||
|  | ||||
| class TestComposeModsFullFile(unittest.TestCase): | ||||
|     def setUp(self): | ||||
|         self.docker_repository_path = "/opt/docker/bigbluebutton/services/repository" | ||||
|         self.env_file = "/opt/docker/bigbluebutton/.env/env" | ||||
|         self.original = """# auto generated by ./scripts/generate-compose | ||||
| # don't edit this directly. | ||||
|  | ||||
| services: | ||||
|   bbb-web: | ||||
|     build: | ||||
|       context: mod/bbb-web | ||||
|       additional_contexts: | ||||
|         - src-web=./repos/bigbluebutton/bigbluebutton-web | ||||
|     volumes: | ||||
|       - ./data/bigbluebutton:/var/bigbluebutton | ||||
|       - ./data/freeswitch-meetings:/var/freeswitch/meetings | ||||
|  | ||||
|   freeswitch: | ||||
|     build: | ||||
|       context: mod/freeswitch | ||||
|       additional_contexts: | ||||
|         - freeswitch=./repos/freeswitch/ | ||||
|     volumes: | ||||
|       - ./data/freeswitch-meetings:/var/freeswitch/meetings | ||||
|  | ||||
|   nginx: | ||||
|     build: | ||||
|       context: mod/nginx | ||||
|  | ||||
|   redis: | ||||
|     image: redis:7.2-alpine | ||||
|  | ||||
|   coturn: | ||||
|     image: coturn/coturn:4.6-alpine | ||||
|     volumes: | ||||
|       - ./mod/coturn/turnserver.conf:/etc/coturn/turnserver.conf | ||||
|  | ||||
|   bbb-graphql-server: | ||||
|     build: | ||||
|       context: mod/bbb-graphql-server | ||||
| """ | ||||
|  | ||||
|         self.expected = """services: | ||||
|   bbb-web: | ||||
|     build: | ||||
|       context: /opt/docker/bigbluebutton/services/repository/mod/bbb-web | ||||
|       additional_contexts: | ||||
|         - src-web=/opt/docker/bigbluebutton/services/repository/repos/bigbluebutton/bigbluebutton-web | ||||
|     volumes: | ||||
|       - bigbluebutton:/var/bigbluebutton | ||||
|       - freeswitch:/var/freeswitch/meetings | ||||
|     env_file: | ||||
|       - /opt/docker/bigbluebutton/.env/env | ||||
|  | ||||
|   freeswitch: | ||||
|     build: | ||||
|       context: /opt/docker/bigbluebutton/services/repository/mod/freeswitch | ||||
|       additional_contexts: | ||||
|         - freeswitch=/opt/docker/bigbluebutton/services/repository/repos/freeswitch/ | ||||
|     volumes: | ||||
|       - freeswitch:/var/freeswitch/meetings | ||||
|     env_file: | ||||
|       - /opt/docker/bigbluebutton/.env/env | ||||
|  | ||||
|   nginx: | ||||
|     build: | ||||
|       context: /opt/docker/bigbluebutton/services/repository/mod/nginx | ||||
|     env_file: | ||||
|       - /opt/docker/bigbluebutton/.env/env | ||||
|  | ||||
|   redis: | ||||
|     image: redis:7.2-alpine | ||||
|     volumes: | ||||
|       - redis:/data | ||||
|     env_file: | ||||
|       - /opt/docker/bigbluebutton/.env/env | ||||
|  | ||||
|   coturn: | ||||
|     image: coturn/coturn:4.6-alpine | ||||
|     volumes: | ||||
|       - /opt/docker/bigbluebutton/services/repository/mod/coturn/turnserver.conf:/etc/coturn/turnserver.conf | ||||
|       - coturn:/var/lib/coturn | ||||
|     env_file: | ||||
|       - /opt/docker/bigbluebutton/.env/env | ||||
|  | ||||
|   bbb-graphql-server: | ||||
|     build: | ||||
|       context: /opt/docker/bigbluebutton/services/repository/mod/bbb-graphql-server | ||||
|     healthcheck: | ||||
|       test: | ||||
|         - CMD | ||||
|         - curl | ||||
|         - -f | ||||
|         - http://localhost:8085/healthz | ||||
|       interval: 30s | ||||
|       timeout: 10s | ||||
|       retries: 5 | ||||
|       start_period: 10s | ||||
|     env_file: | ||||
|       - /opt/docker/bigbluebutton/.env/env | ||||
|  | ||||
| volumes: | ||||
|   database: | ||||
|   greenlight: | ||||
|   redis: | ||||
|   coturn: | ||||
|   freeswitch: | ||||
|   bigbluebutton: | ||||
|   mediasoup: | ||||
| """ | ||||
|  | ||||
|     def test_full_file_semantic_match(self): | ||||
|         actual_data = yaml.safe_load(compose_mods(self.original, self.docker_repository_path, self.env_file)) | ||||
|         expected_data = yaml.safe_load(self.expected) | ||||
|         for key in expected_data: | ||||
|             self.assertIn(key, actual_data) | ||||
|             self.assertEqual(sort_dict(actual_data[key]), sort_dict(expected_data[key])) | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|     unittest.main() | ||||
		Reference in New Issue
	
	Block a user