-
Notifications
You must be signed in to change notification settings - Fork 115
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
Allow selecting enabled plugins #5083
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Added ``ENABLED_PLUGINS`` option to allow selecting installed plugins to be enabled. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,9 +12,9 @@ | |
|
||
from contextlib import suppress | ||
from importlib import import_module | ||
from importlib.metadata import entry_points | ||
from logging import getLogger | ||
from pathlib import Path | ||
from pkg_resources import iter_entry_points | ||
|
||
from cryptography.fernet import Fernet | ||
from django.core.exceptions import ImproperlyConfigured | ||
|
@@ -81,14 +81,6 @@ | |
"pulpcore.app", | ||
] | ||
|
||
# Enumerate the installed Pulp plugins during the loading process for use in the status API | ||
INSTALLED_PULP_PLUGINS = [] | ||
|
||
for entry_point in iter_entry_points("pulpcore.plugin"): | ||
plugin_app_config = entry_point.load() | ||
INSTALLED_PULP_PLUGINS.append(entry_point.module_name) | ||
INSTALLED_APPS.append(plugin_app_config) | ||
|
||
# Optional apps that help with development, or augment Pulp in some non-critical way | ||
OPTIONAL_APPS = [ | ||
"crispy_forms", | ||
|
@@ -317,9 +309,17 @@ | |
|
||
# HERE STARTS DYNACONF EXTENSION LOAD (Keep at the very bottom of settings.py) | ||
# Read more at https://dynaconf.readthedocs.io/en/latest/guides/django.html | ||
from dynaconf import DjangoDynaconf, Validator # noqa | ||
from dynaconf import DjangoDynaconf, Dynaconf, Validator # noqa | ||
|
||
# Validators | ||
|
||
enabled_plugins_validator = Validator( | ||
"ENABLED_PLUGINS", | ||
is_type_of=list, | ||
len_min=1, | ||
when=Validator("ENABLED_PLUGINS", must_exist=True), | ||
) | ||
|
||
content_origin_validator = Validator( | ||
"CONTENT_ORIGIN", | ||
must_exist=True, | ||
|
@@ -407,19 +407,43 @@ | |
authentication_json_header_validator & authentication_json_header_jq_filter_validator | ||
) | ||
|
||
|
||
def load_plugin_config_hook(settings): | ||
# Enumerate the installed Pulp plugins during the loading process for use in the status API | ||
ENABLED_PLUGINS = getattr(settings, "ENABLED_PLUGINS", None) | ||
installed_plugins = [] | ||
installed_plugin_apps = [] | ||
|
||
for entry_point in entry_points().get("pulpcore.plugin", []): | ||
if ENABLED_PLUGINS is not None and entry_point.name not in ENABLED_PLUGINS: | ||
continue | ||
installed_plugins.append(entry_point.module) | ||
installed_plugin_apps.append(entry_point.load()) | ||
|
||
plugin_settings = Dynaconf( | ||
PRELOAD_FOR_DYNACONF=[f"{module}.app.settings" for module in installed_plugins] | ||
) | ||
|
||
data = {"dynaconf_merge": True} | ||
data.update(plugin_settings.as_dict()) | ||
data.update(settings.as_dict()) | ||
data["INSTALLED_APPS"].extend(installed_plugin_apps) | ||
data["INSTALLED_APPS"].append("dynaconf_merge_unique") | ||
return data | ||
|
||
|
||
settings = DjangoDynaconf( | ||
__name__, | ||
ENVVAR_PREFIX_FOR_DYNACONF="PULP", | ||
ENV_SWITCHER_FOR_DYNACONF="PULP_ENV", | ||
PRELOAD_FOR_DYNACONF=[ | ||
"{}.app.settings".format(plugin_name) for plugin_name in INSTALLED_PULP_PLUGINS | ||
], | ||
ENVVAR_FOR_DYNACONF="PULP_SETTINGS", | ||
post_hooks=(load_plugin_config_hook,), | ||
Comment on lines
-414
to
+440
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Where does ENABLED_PLUGINS comes from? an environment variable? I see 2 simpler ways for doing it without requiring a hook
PRELOAD_FOR_DYNACONF=[
"{}.app.settings".format(plugin_name)
for plugin_name in INSTALLED_PULP_PLUGINS
if plugin_name in os.getenv("PULP_ENABLED_PLUGINS", [])
], The downside of above strategy is that variable will need to come from envvar, not set on a settings.py file.
settings = DjangoDynaconf(....)
# then imediatelly after
for plugin_name in INSTALLED_PULP_PLUGINS:
if plugin_name not in settings.get("enabled_plugins", []):
continue
settings.load_file("{}.app.settings".format(plugin_name)) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this will also require a late validation, so replace validators= [...] with settings = DjangoDynaconf(...)
for plugin_name in INSTALLED_PULP_PLUGINS:
....
# invoke validators
settings.validators.register(**list_of_validators)
settings.validators.validade() There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It can come from any outside of pulp code base config source. e.g. Does this method ensure that the chainloaded plugin settings (like pulp_containers There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are right, my suggestion would put plugin loading at the end of the process and then override local settings. That is why in the current implementation we are using PRELOAD to ensure plugins settings loads before other settings sources. Looks like we needed to have support for One idea is to write a custom loader to bring plugin_settings and then change the order of loaders putting the plugin_loader before everything else. ideas @pedro-psb ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If taking approach 2, I believe an explicit load of the settings files should ensure the external file precedence: settings = DjangoDynaconf(...)
# (plugins load)
settings.load_file(settings.get("PULP_SETTINGS"))
# (validators) But this original hook solution seems to do the trick, is there a particular reason not to use it? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The thing is that we need to keep the order, because "everything else" is what may provide the ENABLED_PLUGINS. |
||
load_dotenv=False, | ||
validators=[ | ||
api_root_validator, | ||
cache_validator, | ||
content_origin_validator, | ||
enabled_plugins_validator, | ||
sha256_validator, | ||
storage_validator, | ||
unknown_algs_validator, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does it make sense to add validatiion to the setting so that at least one plugin needs to be enabled?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically pulp would start just fine without it. So Maybe?