mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-14 09:51:22 -06:00
Change PLUGINS_ENABLED to a list of specific plugins (PLUGINS)
This commit is contained in:
parent
06116cdde7
commit
f469c794ce
@ -299,6 +299,17 @@ Determine how many objects to display per page within each list of objects.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## PLUGINS
|
||||||
|
|
||||||
|
Default: Empty
|
||||||
|
|
||||||
|
A list of installed [NetBox plugins](../../plugins/) to enable. Plugins will not take effect unless they are listed here.
|
||||||
|
|
||||||
|
!!! warning
|
||||||
|
Plugins extend NetBox by allowing external code to run with the same access and privileges as NetBox itself. Only install plugins from trusted sources. The NetBox maintainers make absolutely no guarantees about the integrity or security of your installation with plugins enabled.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## PLUGINS_CONFIG
|
## PLUGINS_CONFIG
|
||||||
|
|
||||||
Default: Empty
|
Default: Empty
|
||||||
@ -317,18 +328,7 @@ PLUGINS_CONFIG = {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that `PLUGINS_ENABLED` must be set to True for this to take effect.
|
Note that a plugin must be listed in `PLUGINS` for its configuration to take effect.
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## PLUGINS_ENABLED
|
|
||||||
|
|
||||||
Default: `False`
|
|
||||||
|
|
||||||
Enable [NetBox plugins](../../plugins/).
|
|
||||||
|
|
||||||
!!! warning
|
|
||||||
Plugins extend NetBox by allowing external code to run with the same access and privileges as NetBox itself. Only install plugins from trusted sources. The NetBox maintainers make absolutely no guarantees about the integrity or security of your installation with plugins enabled.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -61,13 +61,10 @@ setup(
|
|||||||
install_requires=[],
|
install_requires=[],
|
||||||
packages=find_packages(),
|
packages=find_packages(),
|
||||||
include_package_data=True,
|
include_package_data=True,
|
||||||
entry_points={
|
|
||||||
'netbox_plugins': 'netbox_animal_sounds=netbox_animal_sounds:AnimalSoundsConfig'
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
Many of these are self-explanatory, but for more information, see the [setuptools documentation](https://setuptools.readthedocs.io/en/latest/setuptools.html). The key requirement for a NetBox plugin is the presence of an entry point for `netbox_plugins` pointing to the `PluginConfig` subclass, which we'll create next.
|
Many of these are self-explanatory, but for more information, see the [setuptools documentation](https://setuptools.readthedocs.io/en/latest/setuptools.html).
|
||||||
|
|
||||||
### Define a PluginConfig
|
### Define a PluginConfig
|
||||||
|
|
||||||
@ -87,8 +84,12 @@ class AnimalSoundsConfig(PluginConfig):
|
|||||||
default_settings = {
|
default_settings = {
|
||||||
'loud': False
|
'loud': False
|
||||||
}
|
}
|
||||||
|
|
||||||
|
config = AnimalSoundsConfig
|
||||||
```
|
```
|
||||||
|
|
||||||
|
NetBox looks for the `config` variable within a plugin's `__init__.py` to load its configuration. Typically, this will be set to the PluginConfig subclass, but you may wish to dynamically generate a PluginConfig class based on environment variables or other factors.
|
||||||
|
|
||||||
#### PluginConfig Attributes
|
#### PluginConfig Attributes
|
||||||
|
|
||||||
| Name | Description |
|
| Name | Description |
|
||||||
|
@ -41,12 +41,14 @@ $ source /opt/netbox/venv/bin/activate
|
|||||||
|
|
||||||
Alternatively, you may wish to install the plugin manually by running `python setup.py install`. If you are developing a plugin and want to install it only temporarily, run `python setup.py develop` instead.
|
Alternatively, you may wish to install the plugin manually by running `python setup.py install`. If you are developing a plugin and want to install it only temporarily, run `python setup.py develop` instead.
|
||||||
|
|
||||||
### Enable Plugins
|
### Enable the Plugin
|
||||||
|
|
||||||
In `configuration.py`, ensure the `PLUGINS_ENABLED` parameter is set to True:
|
In `configuration.py`, add the plugin's name to the `PLUGINS` list:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
PLUGINS_ENABLED = True
|
PLUGINS = [
|
||||||
|
'plugin_name',
|
||||||
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
### Configure Plugin
|
### Configure Plugin
|
||||||
|
@ -10,7 +10,7 @@ from urllib.parse import urlsplit
|
|||||||
from django.contrib.messages import constants as messages
|
from django.contrib.messages import constants as messages
|
||||||
from django.core.exceptions import ImproperlyConfigured, ValidationError
|
from django.core.exceptions import ImproperlyConfigured, ValidationError
|
||||||
from django.core.validators import URLValidator
|
from django.core.validators import URLValidator
|
||||||
from pkg_resources import iter_entry_points, parse_version
|
from pkg_resources import parse_version
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -92,8 +92,8 @@ NAPALM_PASSWORD = getattr(configuration, 'NAPALM_PASSWORD', '')
|
|||||||
NAPALM_TIMEOUT = getattr(configuration, 'NAPALM_TIMEOUT', 30)
|
NAPALM_TIMEOUT = getattr(configuration, 'NAPALM_TIMEOUT', 30)
|
||||||
NAPALM_USERNAME = getattr(configuration, 'NAPALM_USERNAME', '')
|
NAPALM_USERNAME = getattr(configuration, 'NAPALM_USERNAME', '')
|
||||||
PAGINATE_COUNT = getattr(configuration, 'PAGINATE_COUNT', 50)
|
PAGINATE_COUNT = getattr(configuration, 'PAGINATE_COUNT', 50)
|
||||||
|
PLUGINS = getattr(configuration, 'PLUGINS', [])
|
||||||
PLUGINS_CONFIG = getattr(configuration, 'PLUGINS_CONFIG', {})
|
PLUGINS_CONFIG = getattr(configuration, 'PLUGINS_CONFIG', {})
|
||||||
PLUGINS_ENABLED = getattr(configuration, 'PLUGINS_ENABLED', False)
|
|
||||||
PREFER_IPV4 = getattr(configuration, 'PREFER_IPV4', False)
|
PREFER_IPV4 = getattr(configuration, 'PREFER_IPV4', False)
|
||||||
REMOTE_AUTH_AUTO_CREATE_USER = getattr(configuration, 'REMOTE_AUTH_AUTO_CREATE_USER', False)
|
REMOTE_AUTH_AUTO_CREATE_USER = getattr(configuration, 'REMOTE_AUTH_AUTO_CREATE_USER', False)
|
||||||
REMOTE_AUTH_BACKEND = getattr(configuration, 'REMOTE_AUTH_BACKEND', 'utilities.auth_backends.RemoteUserBackend')
|
REMOTE_AUTH_BACKEND = getattr(configuration, 'REMOTE_AUTH_BACKEND', 'utilities.auth_backends.RemoteUserBackend')
|
||||||
@ -637,59 +637,68 @@ if PAGINATE_COUNT not in PER_PAGE_DEFAULTS:
|
|||||||
# Plugins
|
# Plugins
|
||||||
#
|
#
|
||||||
|
|
||||||
PLUGINS = set()
|
for plugin_name in PLUGINS:
|
||||||
if PLUGINS_ENABLED:
|
|
||||||
for entry_point in iter_entry_points(group='netbox_plugins', name=None):
|
|
||||||
# Append plugin name to PLUGINS
|
|
||||||
plugin = entry_point.module_name
|
|
||||||
PLUGINS.add(plugin)
|
|
||||||
|
|
||||||
# Append plugin to INSTALLED_APPS. Specify the path to the PluginConfig so that we don't
|
# Import plugin module
|
||||||
# have to define default_app_config.
|
try:
|
||||||
app_config = entry_point.load()
|
plugin = importlib.import_module(plugin_name)
|
||||||
INSTALLED_APPS.append(f"{app_config.__module__}.{app_config.__name__}")
|
except ImportError:
|
||||||
|
raise ImproperlyConfigured(
|
||||||
|
f"Unable to import plugin {plugin_name}: Module not found. Check that the plugin module has been "
|
||||||
|
f"installed within the correct Python environment."
|
||||||
|
)
|
||||||
|
|
||||||
# Check version constraints
|
# Determine plugin config and add to INSTALLED_APPS.
|
||||||
parsed_min_version = parse_version(app_config.min_version or VERSION)
|
try:
|
||||||
parsed_max_version = parse_version(app_config.max_version or VERSION)
|
plugin_config = plugin.config
|
||||||
if app_config.min_version and app_config.max_version and parsed_min_version > parsed_max_version:
|
INSTALLED_APPS.append(f"{plugin_config.__module__}.{plugin_config.__name__}")
|
||||||
raise ImproperlyConfigured(f"Plugin {plugin} specifies invalid version constraints!")
|
except AttributeError:
|
||||||
if app_config.min_version and parsed_min_version > parse_version(VERSION):
|
raise ImproperlyConfigured(
|
||||||
raise ImproperlyConfigured(f"Plugin {plugin} requires NetBox minimum version {app_config.min_version}!")
|
f"Plugin {plugin_name} does not provide a 'config' variable. This should be defined in the plugin's "
|
||||||
if app_config.max_version and parsed_max_version < parse_version(VERSION):
|
f"__init__.py file and point to the PluginConfig subclass."
|
||||||
raise ImproperlyConfigured(f"Plugin {plugin} requires NetBox maximum version {app_config.max_version}!")
|
)
|
||||||
|
|
||||||
# Add middleware
|
# Check version constraints
|
||||||
plugin_middleware = app_config.middleware
|
parsed_min_version = parse_version(plugin_config.min_version or VERSION)
|
||||||
if plugin_middleware and type(plugin_middleware) in (list, tuple):
|
parsed_max_version = parse_version(plugin_config.max_version or VERSION)
|
||||||
MIDDLEWARE.extend(plugin_middleware)
|
if plugin_config.min_version and plugin_config.max_version and parsed_min_version > parsed_max_version:
|
||||||
|
raise ImproperlyConfigured(f"Plugin {plugin_name} specifies invalid version constraints!")
|
||||||
|
if plugin_config.min_version and parsed_min_version > parse_version(VERSION):
|
||||||
|
raise ImproperlyConfigured(f"Plugin {plugin_name} requires NetBox minimum version {plugin_config.min_version}!")
|
||||||
|
if plugin_config.max_version and parsed_max_version < parse_version(VERSION):
|
||||||
|
raise ImproperlyConfigured(f"Plugin {plugin_name} requires NetBox maximum version {plugin_config.max_version}!")
|
||||||
|
|
||||||
# Verify required configuration settings
|
# Add middleware
|
||||||
if plugin not in PLUGINS_CONFIG:
|
plugin_middleware = plugin_config.middleware
|
||||||
PLUGINS_CONFIG[plugin] = {}
|
if plugin_middleware and type(plugin_middleware) in (list, tuple):
|
||||||
for setting in app_config.required_settings:
|
MIDDLEWARE.extend(plugin_middleware)
|
||||||
if setting not in PLUGINS_CONFIG[plugin]:
|
|
||||||
raise ImproperlyConfigured(
|
|
||||||
f"Plugin {plugin} requires '{setting}' to be present in the PLUGINS_CONFIG section of "
|
|
||||||
f"configuration.py."
|
|
||||||
)
|
|
||||||
|
|
||||||
# Apply default configuration values
|
# Verify required configuration settings
|
||||||
for setting, value in app_config.default_settings.items():
|
if plugin_name not in PLUGINS_CONFIG:
|
||||||
if setting not in PLUGINS_CONFIG[plugin]:
|
PLUGINS_CONFIG[plugin_name] = {}
|
||||||
PLUGINS_CONFIG[plugin][setting] = value
|
for setting in plugin_config.required_settings:
|
||||||
|
if setting not in PLUGINS_CONFIG[plugin_name]:
|
||||||
|
raise ImproperlyConfigured(
|
||||||
|
f"Plugin {plugin_name} requires '{setting}' to be present in the PLUGINS_CONFIG section of "
|
||||||
|
f"configuration.py."
|
||||||
|
)
|
||||||
|
|
||||||
# Apply cacheops config
|
# Apply default configuration values
|
||||||
plugin_cacheops = app_config.caching_config
|
for setting, value in plugin_config.default_settings.items():
|
||||||
if plugin_cacheops:
|
if setting not in PLUGINS_CONFIG[plugin_name]:
|
||||||
if type(plugin_cacheops) is not dict:
|
PLUGINS_CONFIG[plugin_name][setting] = value
|
||||||
raise ImproperlyConfigured(f"Plugin {plugin} caching_config must be a dictionary.")
|
|
||||||
for key in plugin_cacheops.keys():
|
# Apply cacheops config
|
||||||
# Validate config is only being set for the given plugin
|
plugin_cacheops = plugin_config.caching_config
|
||||||
app = key.split('.')[0]
|
if plugin_cacheops:
|
||||||
if app != plugin:
|
if type(plugin_cacheops) is not dict:
|
||||||
raise ImproperlyConfigured(f"Plugin {plugin} may not modify caching config for another app: {app}")
|
raise ImproperlyConfigured(f"Plugin {plugin_name} caching_config must be a dictionary.")
|
||||||
else:
|
for key in plugin_cacheops.keys():
|
||||||
# Apply the default config like all other core apps
|
# Validate config is only being set for the given plugin
|
||||||
plugin_cacheops = {f"{plugin}.*": {'ops': 'all'}}
|
app = key.split('.')[0]
|
||||||
CACHEOPS.update(plugin_cacheops)
|
if app != plugin_name:
|
||||||
|
raise ImproperlyConfigured(f"Plugin {plugin_name} may not modify caching config for another app: {app}")
|
||||||
|
else:
|
||||||
|
# Apply the default config like all other core apps
|
||||||
|
plugin_cacheops = {f"{plugin_name}.*": {'ops': 'all'}}
|
||||||
|
CACHEOPS.update(plugin_cacheops)
|
||||||
|
Loading…
Reference in New Issue
Block a user