Skip to content

Commit

Permalink
Skip incompatible plugins during startup and remove from PLUGINS
Browse files Browse the repository at this point in the history
  • Loading branch information
bctiemann committed Jan 29, 2025
1 parent 5cd7c6d commit cb60769
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 7 deletions.
7 changes: 7 additions & 0 deletions netbox/core/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,9 @@
from django.core.exceptions import ImproperlyConfigured


class SyncError(Exception):
pass


class IncompatiblePluginError(ImproperlyConfigured):
pass
5 changes: 3 additions & 2 deletions netbox/netbox/plugins/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from django.utils.module_loading import import_string
from packaging import version

from core.exceptions import IncompatiblePluginError
from netbox.registry import registry
from netbox.search import register_search
from netbox.utils import register_data_backend
Expand Down Expand Up @@ -138,14 +139,14 @@ def validate(cls, user_config, netbox_version):
if cls.min_version is not None:
min_version = version.parse(cls.min_version)
if current_version < min_version:
raise ImproperlyConfigured(
raise IncompatiblePluginError(
f"Plugin {cls.__module__} requires NetBox minimum version {cls.min_version} (current: "
f"{netbox_version})."
)
if cls.max_version is not None:
max_version = version.parse(cls.max_version)
if current_version > max_version:
raise ImproperlyConfigured(
raise IncompatiblePluginError(
f"Plugin {cls.__module__} requires NetBox maximum version {cls.max_version} (current: "
f"{netbox_version})."
)
Expand Down
20 changes: 15 additions & 5 deletions netbox/netbox/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from django.core.validators import URLValidator
from django.utils.translation import gettext_lazy as _

from core.exceptions import IncompatiblePluginError
from netbox.config import PARAMS as CONFIG_PARAMS
from netbox.constants import RQ_QUEUE_DEFAULT, RQ_QUEUE_HIGH, RQ_QUEUE_LOW
from netbox.plugins import PluginConfig
Expand Down Expand Up @@ -789,6 +790,7 @@ def _setting(name, default=None):
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
Expand All @@ -810,6 +812,16 @@ def _setting(name, default=None):
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:
print(f'Unable to load plugin {plugin_name}: {e}')
incompatible_plugins.append(plugin_name)
continue

plugin_module = "{}.{}".format(plugin_config.__module__, plugin_config.__name__) # type: ignore

# Gather additional apps to load alongside this plugin
Expand Down Expand Up @@ -839,11 +851,6 @@ def _setting(name, default=None):
sorted_apps = reversed(list(dict.fromkeys(reversed(INSTALLED_APPS))))
INSTALLED_APPS = list(sorted_apps)

# Validate user-provided configuration settings and assign defaults
if plugin_name not in PLUGINS_CONFIG:
PLUGINS_CONFIG[plugin_name] = {}
plugin_config.validate(PLUGINS_CONFIG[plugin_name], RELEASE.version)

# Add middleware
plugin_middleware = plugin_config.middleware
if plugin_middleware and type(plugin_middleware) in (list, tuple):
Expand All @@ -865,6 +872,9 @@ def _setting(name, default=None):
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:
from .local_settings import *
Expand Down

0 comments on commit cb60769

Please sign in to comment.