Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closes #13368: Report installed plugins during server error #13387

Merged
merged 3 commits into from
Aug 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 0 additions & 21 deletions netbox/extras/plugins/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from importlib import import_module

from django.apps import AppConfig
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.utils.module_loading import import_string
from packaging import version
Expand Down Expand Up @@ -146,23 +145,3 @@ def validate(cls, user_config, netbox_version):
for setting, value in cls.default_settings.items():
if setting not in user_config:
user_config[setting] = value


#
# Utilities
#

def get_plugin_config(plugin_name, parameter, default=None):
"""
Return the value of the specified plugin configuration parameter.

Args:
plugin_name: The name of the plugin
parameter: The name of the configuration parameter
default: The value to return if the parameter is not defined (default: None)
"""
try:
plugin_config = settings.PLUGINS_CONFIG[plugin_name]
return plugin_config.get(parameter, default)
except KeyError:
raise ImproperlyConfigured(f"Plugin {plugin_name} is not registered.")
37 changes: 37 additions & 0 deletions netbox/extras/plugins/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from django.apps import apps
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured

__all__ = (
'get_installed_plugins',
'get_plugin_config',
)


def get_installed_plugins():
"""
Return a dictionary mapping the names of installed plugins to their versions.
"""
plugins = {}
for plugin_name in settings.PLUGINS:
plugin_name = plugin_name.rsplit('.', 1)[-1]
plugin_config = apps.get_app_config(plugin_name)
plugins[plugin_name] = getattr(plugin_config, 'version', None)

return dict(sorted(plugins.items()))


def get_plugin_config(plugin_name, parameter, default=None):
"""
Return the value of the specified plugin configuration parameter.

Args:
plugin_name: The name of the plugin
parameter: The name of the configuration parameter
default: The value to return if the parameter is not defined (default: None)
"""
try:
plugin_config = settings.PLUGINS_CONFIG[plugin_name]
return plugin_config.get(parameter, default)
except KeyError:
raise ImproperlyConfigured(f"Plugin {plugin_name} is not registered.")
3 changes: 2 additions & 1 deletion netbox/extras/tests/test_plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
from django.test import Client, TestCase, override_settings
from django.urls import reverse

from extras.plugins import PluginMenu, get_plugin_config
from extras.plugins import PluginMenu
from extras.tests.dummy_plugin import config as dummy_config
from extras.plugins.utils import get_plugin_config
from netbox.graphql.schema import Query
from netbox.registry import registry

Expand Down
11 changes: 2 additions & 9 deletions netbox/netbox/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from rest_framework.views import APIView
from rq.worker import Worker

from extras.plugins.utils import get_installed_plugins
from netbox.api.authentication import IsAuthenticatedOrLoginNotRequired


Expand Down Expand Up @@ -61,19 +62,11 @@ def get(self, request):
installed_apps[app_config.name] = version
installed_apps = {k: v for k, v in sorted(installed_apps.items())}

# Gather installed plugins
plugins = {}
for plugin_name in settings.PLUGINS:
plugin_name = plugin_name.rsplit('.', 1)[-1]
plugin_config = apps.get_app_config(plugin_name)
plugins[plugin_name] = getattr(plugin_config, 'version', None)
plugins = {k: v for k, v in sorted(plugins.items())}

return Response({
'django-version': DJANGO_VERSION,
'installed-apps': installed_apps,
'netbox-version': settings.VERSION,
'plugins': plugins,
'plugins': get_installed_plugins(),
'python-version': platform.python_version(),
'rq-workers-running': Worker.count(get_connection('default')),
})
3 changes: 3 additions & 0 deletions netbox/netbox/views/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
from django.views.generic import View
from sentry_sdk import capture_message

from extras.plugins.utils import get_installed_plugins

__all__ = (
'handler_404',
'handler_500',
Expand Down Expand Up @@ -53,4 +55,5 @@ def handler_500(request, template_name=ERROR_500_TEMPLATE_NAME):
'exception': str(type_),
'netbox_version': settings.VERSION,
'python_version': platform.python_version(),
'plugins': get_installed_plugins(),
}))
5 changes: 4 additions & 1 deletion netbox/templates/500.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ <h5 class="card-header">
{{ error }}

Python version: {{ python_version }}
NetBox version: {{ netbox_version }}</pre>
NetBox version: {{ netbox_version }}
Plugins: {% for plugin, version in plugins.items %}
{{ plugin }}: {{ version }}{% empty %}None installed{% endfor %}
</pre>
<p>
If further assistance is required, please post to the <a href="https://github.com/netbox-community/netbox/discussions">NetBox discussion forum</a> on GitHub.
</p>
Expand Down