From 1ef224f5fd3f3b9994b6dad6bfb494a1be20bb22 Mon Sep 17 00:00:00 2001 From: Marc 'risson' Schmitt Date: Fri, 9 Feb 2024 19:41:33 +0100 Subject: [PATCH] blueprints: only watch for fs events we're interested in (#7810) Signed-off-by: Marc 'risson' Schmitt --- authentik/blueprints/v1/tasks.py | 47 +++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/authentik/blueprints/v1/tasks.py b/authentik/blueprints/v1/tasks.py index c6b78a4e83..701bbb0fdf 100644 --- a/authentik/blueprints/v1/tasks.py +++ b/authentik/blueprints/v1/tasks.py @@ -60,7 +60,12 @@ def start_blueprint_watcher(): if _file_watcher_started: return observer = Observer() - observer.schedule(BlueprintEventHandler(), CONFIG.get("blueprints_dir"), recursive=True) + observer.schedule( + BlueprintEventHandler(), + CONFIG.get("blueprints_dir"), + recursive=True, + event_filter=(FileCreatedEvent, FileModifiedEvent), + ) observer.start() _file_watcher_started = True @@ -68,26 +73,36 @@ def start_blueprint_watcher(): class BlueprintEventHandler(FileSystemEventHandler): """Event handler for blueprint events""" - def on_any_event(self, event: FileSystemEvent): - if not isinstance(event, (FileCreatedEvent, FileModifiedEvent)): - return + # We only ever get creation and modification events. + # See the creation of the Observer instance above for the event filtering. + + # Even though we filter to only get file events, we might still get + # directory events as some implementations such as inotify do not support + # filtering on file/directory. + + def dispatch(self, event: FileSystemEvent) -> None: + """Call specific event handler method. Ignores directory changes.""" if event.is_directory: - return + return None + return super().dispatch(event) + + def on_created(self, event: FileSystemEvent): + """Process file creation""" + LOGGER.debug("new blueprint file created, starting discovery") + for tenant in Tenant.objects.filter(ready=True): + with tenant: + blueprints_discovery.delay() + + def on_modified(self, event: FileSystemEvent): + """Process file modification""" + path = Path(event.src_path) root = Path(CONFIG.get("blueprints_dir")).absolute() - path = Path(event.src_path).absolute() rel_path = str(path.relative_to(root)) for tenant in Tenant.objects.filter(ready=True): with tenant: - root = Path(CONFIG.get("blueprints_dir")).absolute() - path = Path(event.src_path).absolute() - rel_path = str(path.relative_to(root)) - if isinstance(event, FileCreatedEvent): - LOGGER.debug("new blueprint file created, starting discovery", path=rel_path) - blueprints_discovery.delay(rel_path) - if isinstance(event, FileModifiedEvent): - for instance in BlueprintInstance.objects.filter(path=rel_path, enabled=True): - LOGGER.debug("modified blueprint file, starting apply", instance=instance) - apply_blueprint.delay(instance.pk.hex) + for instance in BlueprintInstance.objects.filter(path=rel_path, enabled=True): + LOGGER.debug("modified blueprint file, starting apply", instance=instance) + apply_blueprint.delay(instance.pk.hex) @CELERY_APP.task(