diff --git a/netbox/core/plugins.py b/netbox/core/plugins.py index 1fcb37f2bff..7da197a7050 100644 --- a/netbox/core/plugins.py +++ b/netbox/core/plugins.py @@ -9,6 +9,7 @@ from django.core.cache import cache from netbox.plugins import PluginConfig +from netbox.registry import registry from utilities.datetime import datetime_from_timestamp USER_AGENT_STRING = f'NetBox/{settings.RELEASE.version} {settings.RELEASE.edition}' @@ -76,7 +77,7 @@ def get_local_plugins(plugins=None): local_plugins = {} # Gather all locally-installed plugins - for plugin_name in settings.PLUGINS: + for plugin_name in registry['plugins']['installed']: plugin = importlib.import_module(plugin_name) plugin_config: PluginConfig = plugin.config diff --git a/netbox/core/views.py b/netbox/core/views.py index 713807a8224..ea1fd08d3b3 100644 --- a/netbox/core/views.py +++ b/netbox/core/views.py @@ -22,6 +22,7 @@ from core.utils import delete_rq_job, enqueue_rq_job, get_rq_jobs_from_status, requeue_rq_job, stop_rq_job from netbox.config import get_config, PARAMS +from netbox.registry import registry from netbox.views import generic from netbox.views.generic.base import BaseObjectView from netbox.views.generic.mixins import TableMixin @@ -560,7 +561,7 @@ def get(self, request): params = [param.name for param in PARAMS] data = { **stats, - 'plugins': settings.PLUGINS, + 'plugins': registry['plugins']['installed'], 'config': { k: getattr(config, k) for k in sorted(params) }, diff --git a/netbox/netbox/plugins/__init__.py b/netbox/netbox/plugins/__init__.py index 69881a25146..f339f9d513f 100644 --- a/netbox/netbox/plugins/__init__.py +++ b/netbox/netbox/plugins/__init__.py @@ -16,6 +16,7 @@ # Initialize plugin registry registry['plugins'].update({ + 'installed': [], 'graphql_schemas': [], 'menus': [], 'menu_items': {}, diff --git a/netbox/netbox/plugins/urls.py b/netbox/netbox/plugins/urls.py index 7a9f30c7eff..791c1d7b5f1 100644 --- a/netbox/netbox/plugins/urls.py +++ b/netbox/netbox/plugins/urls.py @@ -1,11 +1,11 @@ from importlib import import_module from django.apps import apps -from django.conf import settings from django.conf.urls import include from django.urls import path from django.utils.module_loading import import_string, module_has_submodule +from netbox.registry import registry from . import views plugin_patterns = [] @@ -15,7 +15,7 @@ ] # Register base/API URL patterns for each plugin -for plugin_path in settings.PLUGINS: +for plugin_path in registry['plugins']['installed']: plugin = import_module(plugin_path) plugin_name = plugin_path.split('.')[-1] app = apps.get_app_config(plugin_name) diff --git a/netbox/netbox/plugins/utils.py b/netbox/netbox/plugins/utils.py index c260f156db6..435afff6f24 100644 --- a/netbox/netbox/plugins/utils.py +++ b/netbox/netbox/plugins/utils.py @@ -2,6 +2,8 @@ from django.conf import settings from django.core.exceptions import ImproperlyConfigured +from netbox.registry import registry + __all__ = ( 'get_installed_plugins', 'get_plugin_config', @@ -13,7 +15,7 @@ def get_installed_plugins(): Return a dictionary mapping the names of installed plugins to their versions. """ plugins = {} - for plugin_name in settings.PLUGINS: + for plugin_name in registry['plugins']['installed']: plugin_name = plugin_name.rsplit('.', 1)[-1] plugin_config = apps.get_app_config(plugin_name) plugins[plugin_name] = getattr(plugin_config, 'version', None) diff --git a/netbox/netbox/plugins/views.py b/netbox/netbox/plugins/views.py index 6a10f2e2c0e..7044b6ea0ae 100644 --- a/netbox/netbox/plugins/views.py +++ b/netbox/netbox/plugins/views.py @@ -1,7 +1,6 @@ from collections import OrderedDict from django.apps import apps -from django.conf import settings from django.urls.exceptions import NoReverseMatch from drf_spectacular.utils import extend_schema from rest_framework import permissions @@ -9,6 +8,8 @@ from rest_framework.reverse import reverse from rest_framework.views import APIView +from netbox.registry import registry + @extend_schema(exclude=True) class InstalledPluginsAPIView(APIView): @@ -34,7 +35,10 @@ def _get_plugin_data(plugin_app_config): } def get(self, request, format=None): - return Response([self._get_plugin_data(apps.get_app_config(plugin)) for plugin in settings.PLUGINS]) + return Response([ + self._get_plugin_data(apps.get_app_config(plugin)) + for plugin in registry['plugins']['installed'] + ]) @extend_schema(exclude=True) @@ -64,7 +68,7 @@ def _get_plugin_entry(plugin, app_config, request, format): def get(self, request, format=None): entries = [] - for plugin in settings.PLUGINS: + for plugin in registry['plugins']['installed']: app_config = apps.get_app_config(plugin) entry = self._get_plugin_entry(plugin, app_config, request, format) if entry is not None: diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index 0682e713d64..ceb20d226da 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -16,6 +16,7 @@ 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 +from netbox.registry import registry from utilities.release import load_release_data from utilities.string import trailing_slash @@ -813,6 +814,9 @@ def _setting(name, default=None): f"__init__.py file and point to the PluginConfig subclass." ) + # Register the plugin as installed successfully + registry['plugins']['installed'].append(plugin_name) + plugin_module = "{}.{}".format(plugin_config.__module__, plugin_config.__name__) # type: ignore # Gather additional apps to load alongside this plugin