mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
164 lines
5.1 KiB
Python
164 lines
5.1 KiB
Python
import collections
|
|
|
|
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
|
|
|
|
from netbox.registry import registry
|
|
from netbox.search import register_search
|
|
from .navigation import *
|
|
from .registration import *
|
|
from .templates import *
|
|
|
|
# Initialize plugin registry
|
|
registry['plugins'] = {
|
|
'graphql_schemas': [],
|
|
'menus': [],
|
|
'menu_items': {},
|
|
'preferences': {},
|
|
'template_extensions': collections.defaultdict(list),
|
|
}
|
|
|
|
|
|
#
|
|
# Plugin AppConfig class
|
|
#
|
|
|
|
class PluginConfig(AppConfig):
|
|
"""
|
|
Subclass of Django's built-in AppConfig class, to be used for NetBox plugins.
|
|
"""
|
|
# Plugin metadata
|
|
author = ''
|
|
author_email = ''
|
|
description = ''
|
|
version = ''
|
|
|
|
# Root URL path under /plugins. If not set, the plugin's label will be used.
|
|
base_url = None
|
|
|
|
# Minimum/maximum compatible versions of NetBox
|
|
min_version = None
|
|
max_version = None
|
|
|
|
# Default configuration parameters
|
|
default_settings = {}
|
|
|
|
# Mandatory configuration parameters
|
|
required_settings = []
|
|
|
|
# Middleware classes provided by the plugin
|
|
middleware = []
|
|
|
|
# Django-rq queues dedicated to the plugin
|
|
queues = []
|
|
|
|
# Django apps to append to INSTALLED_APPS when plugin requires them.
|
|
django_apps = []
|
|
|
|
# Default integration paths. Plugin authors can override these to customize the paths to
|
|
# integrated components.
|
|
search_indexes = 'search.indexes'
|
|
graphql_schema = 'graphql.schema'
|
|
menu = 'navigation.menu'
|
|
menu_items = 'navigation.menu_items'
|
|
template_extensions = 'template_content.template_extensions'
|
|
user_preferences = 'preferences.preferences'
|
|
|
|
def ready(self):
|
|
plugin_name = self.name.rsplit('.', 1)[-1]
|
|
|
|
# Register search extensions (if defined)
|
|
try:
|
|
search_indexes = import_string(f"{self.__module__}.{self.search_indexes}")
|
|
for idx in search_indexes:
|
|
register_search(idx)
|
|
except ImportError:
|
|
pass
|
|
|
|
# Register template content (if defined)
|
|
try:
|
|
template_extensions = import_string(f"{self.__module__}.{self.template_extensions}")
|
|
register_template_extensions(template_extensions)
|
|
except ImportError:
|
|
pass
|
|
|
|
# Register navigation menu and/or menu items (if defined)
|
|
try:
|
|
menu = import_string(f"{self.__module__}.{self.menu}")
|
|
register_menu(menu)
|
|
except ImportError:
|
|
pass
|
|
try:
|
|
menu_items = import_string(f"{self.__module__}.{self.menu_items}")
|
|
register_menu_items(self.verbose_name, menu_items)
|
|
except ImportError:
|
|
pass
|
|
|
|
# Register GraphQL schema (if defined)
|
|
try:
|
|
graphql_schema = import_string(f"{self.__module__}.{self.graphql_schema}")
|
|
register_graphql_schema(graphql_schema)
|
|
except ImportError:
|
|
pass
|
|
|
|
# Register user preferences (if defined)
|
|
try:
|
|
user_preferences = import_string(f"{self.__module__}.{self.user_preferences}")
|
|
register_user_preferences(plugin_name, user_preferences)
|
|
except ImportError:
|
|
pass
|
|
|
|
@classmethod
|
|
def validate(cls, user_config, netbox_version):
|
|
|
|
# Enforce version constraints
|
|
current_version = version.parse(netbox_version)
|
|
if cls.min_version is not None:
|
|
min_version = version.parse(cls.min_version)
|
|
if current_version < min_version:
|
|
raise ImproperlyConfigured(
|
|
f"Plugin {cls.__module__} requires NetBox minimum version {cls.min_version}."
|
|
)
|
|
if cls.max_version is not None:
|
|
max_version = version.parse(cls.max_version)
|
|
if current_version > max_version:
|
|
raise ImproperlyConfigured(
|
|
f"Plugin {cls.__module__} requires NetBox maximum version {cls.max_version}."
|
|
)
|
|
|
|
# Verify required configuration settings
|
|
for setting in cls.required_settings:
|
|
if setting not in user_config:
|
|
raise ImproperlyConfigured(
|
|
f"Plugin {cls.__module__} requires '{setting}' to be present in the PLUGINS_CONFIG section of "
|
|
f"configuration.py."
|
|
)
|
|
|
|
# Apply default configuration values
|
|
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.")
|