diff --git a/netbox/core/plugins.py b/netbox/core/plugins.py index e6d09711f..8fed9b3b7 100644 --- a/netbox/core/plugins.py +++ b/netbox/core/plugins.py @@ -77,7 +77,7 @@ def get_local_plugins(plugins=None): local_plugins = {} # Gather all locally-installed plugins - for plugin_name in registry['plugins']['installed']: + for plugin_name in settings.PLUGINS: plugin = importlib.import_module(plugin_name) plugin_config: PluginConfig = plugin.config installed_version = plugin_config.version @@ -91,7 +91,7 @@ def get_local_plugins(plugins=None): tag_line=plugin_config.description, description_short=plugin_config.description, is_local=True, - is_installed=True, + is_installed=plugin_name in registry['plugins']['installed'], installed_version=installed_version, ) @@ -99,7 +99,7 @@ def get_local_plugins(plugins=None): for k, v in local_plugins.items(): if k in plugins: plugins[k].is_local = True - plugins[k].is_installed = True + plugins[k].is_installed = k in registry['plugins']['installed'] plugins[k].installed_version = v.installed_version else: plugins[k] = v diff --git a/netbox/netbox/middleware.py b/netbox/netbox/middleware.py index b9424bd7c..4f9721430 100644 --- a/netbox/netbox/middleware.py +++ b/netbox/netbox/middleware.py @@ -2,6 +2,7 @@ from contextlib import ExitStack import logging import uuid +import warnings from django.conf import settings from django.contrib import auth, messages @@ -37,7 +38,10 @@ class CoreMiddleware: # Apply all registered request processors with ExitStack() as stack: for request_processor in registry['request_processors']: - stack.enter_context(request_processor(request)) + try: + stack.enter_context(request_processor(request)) + except Exception as e: + warnings.warn(f'Failed to initialize request processor {request_processor}: {e}') response = self.get_response(request) # Check if language cookie should be renewed diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index ad722e3a9..4e6e96d8a 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -791,7 +791,6 @@ if 'extras.events.process_event_queue' not in EVENTS_PIPELINE: EVENTS_PIPELINE.insert(0, 'extras.events.process_event_queue') # Register any configured plugins -incompatible_plugins = [] for plugin_name in PLUGINS: try: # Import the plugin module @@ -813,6 +812,15 @@ for plugin_name in PLUGINS: f"__init__.py file and point to the PluginConfig subclass." ) + # Validate version compatibility and user-provided configuration settings and assign defaults + if plugin_name not in PLUGINS_CONFIG: + PLUGINS_CONFIG[plugin_name] = {} + try: + plugin_config.validate(PLUGINS_CONFIG[plugin_name], RELEASE.version) + except IncompatiblePluginError as e: + warnings.warn(f'Unable to load plugin {plugin_name}: {e}') + continue + # Register the plugin as installed successfully registry['plugins']['installed'].append(plugin_name) @@ -866,8 +874,6 @@ for plugin_name in PLUGINS: else: raise ImproperlyConfigured(f"events_pipline in plugin: {plugin_name} must be a list or tuple") -[PLUGINS.remove(x) for x in incompatible_plugins] - # UNSUPPORTED FUNCTIONALITY: Import any local overrides. try: