From e8c19b4b84bac424b2d0aefbcb61c6734e4d4379 Mon Sep 17 00:00:00 2001 From: Kevin Veen-Birkenbach Date: Mon, 11 Aug 2025 18:46:02 +0200 Subject: [PATCH] Implemented correct path replace not just for context: but also for build: paths --- .../filter_plugins/compose_mods.py | 68 +++++++++++++------ 1 file changed, 48 insertions(+), 20 deletions(-) diff --git a/roles/web-app-bigbluebutton/filter_plugins/compose_mods.py b/roles/web-app-bigbluebutton/filter_plugins/compose_mods.py index e8607e72..8bd665fb 100644 --- a/roles/web-app-bigbluebutton/filter_plugins/compose_mods.py +++ b/roles/web-app-bigbluebutton/filter_plugins/compose_mods.py @@ -2,40 +2,67 @@ import re import yaml def compose_mods(yml_text, docker_repository_path, env_file): + # Named volume rewrites 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 - ) + + # Make other ./ paths absolute to the given repository + yml_text = re.sub(r'\./', docker_repository_path.rstrip('/') + '/', yml_text) + + # Keep the old context helpers (harmless if YAML step below fixes everything) yml_text = re.sub( r'(^\s*context:\s*)mod/(.*)', - r'\1' + docker_repository_path + r'/mod/\2', + r'\1' + docker_repository_path.rstrip('/') + r'/mod/\2', yml_text, flags=re.MULTILINE ) + def _prefix_mod(path: str) -> str: + """Prefix 'mod/...' (or './mod/...') with docker_repository_path, avoiding //.""" + p = str(path).strip().strip('\'"') + p = p.lstrip('./') + if p.startswith('mod/'): + return docker_repository_path.rstrip('/') + '/' + p + return path + try: - data = yaml.safe_load(yml_text) - services = data.get('services', {}) + data = yaml.safe_load(yml_text) or {} + services = data.get('services', {}) or {} + for name, svc in services.items(): + if not isinstance(svc, dict): + continue + + # ensure env_file svc['env_file'] = [env_file] + + # handle build when it is a string: e.g., build: "mod/periodic" + if 'build' in svc: + b = svc['build'] + if isinstance(b, str): + svc['build'] = _prefix_mod(b) + elif isinstance(b, dict): + ctx = b.get('context') + if isinstance(ctx, str): + b['context'] = _prefix_mod(ctx) + + # extras 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'], @@ -44,27 +71,28 @@ def compose_mods(yml_text, docker_repository_path, env_file): '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 - } + data.setdefault('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: + # leave the original yml_text as-is if parsing fails pass return yml_text + class FilterModule(object): def filters(self): return {