perf: improve perf for a bunch of operations by lazy import + lazy define of config-panel related stuff

This commit is contained in:
Alexandre Aubin 2023-11-27 18:03:23 +01:00 committed by axolotle
parent 650c0136f2
commit 3dda3bc4d5
2 changed files with 259 additions and 233 deletions

View file

@ -17,11 +17,11 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import time
import glob
import os
import shutil
import yaml
import time
import re
import subprocess
import tempfile
@ -45,13 +45,6 @@ from moulinette.utils.filesystem import (
chmod,
)
from yunohost.utils.configpanel import ConfigPanel
from yunohost.utils.form import (
DomainOption,
WebPathOption,
ask_questions_and_parse_answers,
parse_raw_options,
)
from yunohost.utils.i18n import _value_for_locale
from yunohost.utils.error import YunohostError, YunohostValidationError
from yunohost.utils.system import (
@ -414,6 +407,7 @@ def app_change_url(operation_logger, app, domain, path):
path -- New path at which the application will be move
"""
from yunohost.utils.form import DomainOption, WebPathOption
from yunohost.hook import hook_exec_with_script_debug_if_failure, hook_callback
from yunohost.service import service_reload_or_restart
@ -964,6 +958,8 @@ def app_upgrade(
def app_manifest(app, with_screenshot=False):
from yunohost.utils.form import parse_raw_options
manifest, extracted_app_folder = _extract_app(app)
manifest["install"] = parse_raw_options(manifest.get("install", {}), serialize=True)
@ -1060,6 +1056,7 @@ def app_install(
)
from yunohost.regenconf import manually_modified_files
from yunohost.utils.legacy import _patch_legacy_php_versions, _patch_legacy_helpers
from yunohost.utils.form import ask_questions_and_parse_answers
# Check if disk space available
if free_space_in_directory("/") <= 512 * 1000 * 1000:
@ -1393,7 +1390,7 @@ def app_remove(operation_logger, app, purge=False, force_workdir=None):
permission_delete,
permission_sync_to_user,
)
from yunohost.domain import domain_list, domain_config_get, domain_config_set
from yunohost.domain import domain_list, domain_config_set, _get_raw_domain_settings
if not _is_installed(app):
raise YunohostValidationError(
@ -1471,7 +1468,7 @@ def app_remove(operation_logger, app, purge=False, force_workdir=None):
hook_remove(app)
for domain in domain_list()["domains"]:
if domain_config_get(domain, "feature.app.default_app") == app:
if _get_raw_domain_settings(domain).get("default_app") == app:
domain_config_set(domain, "feature.app.default_app", "_none")
if ret == 0:
@ -1572,6 +1569,7 @@ def app_register_url(app, domain, path):
domain -- The domain on which the app should be registered (e.g. your.domain.tld)
path -- The path to be registered (e.g. /coffee)
"""
from yunohost.utils.form import DomainOption, WebPathOption
from yunohost.permission import (
permission_url,
user_permission_update,
@ -1614,7 +1612,7 @@ def app_ssowatconf():
"""
from yunohost.domain import (
domain_list,
domain_config_get,
_get_raw_domain_settings,
_get_domain_portal_dict,
)
from yunohost.permission import user_permission_list
@ -1654,8 +1652,8 @@ def app_ssowatconf():
# FIXME : this could be handled by nginx's regen conf to further simplify ssowat's code ...
redirected_urls = {}
for domain in domains:
default_app = domain_config_get(domain, "feature.app.default_app")
if default_app != "_none" and _is_installed(default_app):
default_app = _get_raw_domain_settings(domain).get("default_app")
if default_app not in ["_none", None] and _is_installed(default_app):
app_settings = _get_app_settings(default_app)
app_domain = app_settings["domain"]
app_path = app_settings["path"]
@ -1753,11 +1751,13 @@ def app_change_label(app, new_label):
def app_action_list(app):
AppConfigPanel = _get_AppConfigPanel()
return AppConfigPanel(app).list_actions()
@is_unit_operation()
def app_action_run(operation_logger, app, action, args=None, args_file=None):
AppConfigPanel = _get_AppConfigPanel()
return AppConfigPanel(app).run_action(
action, args=args, args_file=args_file, operation_logger=operation_logger
)
@ -1779,6 +1779,7 @@ def app_config_get(app, key="", full=False, export=False):
else:
mode = "classic"
AppConfigPanel = _get_AppConfigPanel()
try:
config_ = AppConfigPanel(app)
return config_.get(key, mode)
@ -1798,11 +1799,15 @@ def app_config_set(
Apply a new app configuration
"""
AppConfigPanel = _get_AppConfigPanel()
config_ = AppConfigPanel(app)
return config_.set(key, value, args, args_file, operation_logger=operation_logger)
def _get_AppConfigPanel():
from yunohost.utils.configpanel import ConfigPanel
class AppConfigPanel(ConfigPanel):
entity_type = "app"
save_path_tpl = os.path.join(APPS_SETTING_PATH, "{entity}/settings.yml")
@ -1884,6 +1889,8 @@ ynh_app_config_run $1
raise YunohostError("app_action_failed", action=action, app=app)
return values
return AppConfigPanel
def _get_app_settings(app):
"""
@ -2782,6 +2789,7 @@ def _get_conflicting_apps(domain, path, ignore_app=None):
"""
from yunohost.domain import _assert_domain_exists
from yunohost.utils.form import DomainOption, WebPathOption
domain = DomainOption.normalize(domain)
path = WebPathOption.normalize(path)

View file

@ -34,17 +34,8 @@ from moulinette.utils.filesystem import (
write_to_yaml,
)
from yunohost.app import (
app_ssowatconf,
_installed_apps,
_get_app_settings,
_get_conflicting_apps,
)
from yunohost.regenconf import regen_conf, _force_clear_hashes, _process_regen_conf
from yunohost.utils.configpanel import ConfigPanel
from yunohost.utils.form import BaseOption
from yunohost.utils.error import YunohostError, YunohostValidationError
from yunohost.utils.dns import is_yunohost_dyndns_domain
from yunohost.log import is_unit_operation
if TYPE_CHECKING:
@ -191,7 +182,7 @@ def domain_info(domain):
domain -- Domain to be checked
"""
from yunohost.app import app_info
from yunohost.app import app_info, _installed_apps, _get_app_settings
from yunohost.dns import _get_registar_settings
from yunohost.certificate import certificate_status
@ -268,6 +259,7 @@ def domain_add(
from yunohost.utils.ldap import _get_ldap_interface
from yunohost.utils.password import assert_password_is_strong_enough
from yunohost.certificate import _certificate_install_selfsigned
from yunohost.utils.dns import is_yunohost_dyndns_domain
if dyndns_recovery_password:
operation_logger.data_to_redact.append(dyndns_recovery_password)
@ -383,8 +375,15 @@ def domain_remove(
"""
import glob
from yunohost.hook import hook_callback
from yunohost.app import app_ssowatconf, app_info, app_remove
from yunohost.app import (
app_ssowatconf,
app_info,
app_remove,
_get_app_settings,
_installed_apps,
)
from yunohost.utils.ldap import _get_ldap_interface
from yunohost.utils.dns import is_yunohost_dyndns_domain
if dyndns_recovery_password:
operation_logger.data_to_redact.append(dyndns_recovery_password)
@ -566,6 +565,7 @@ def domain_main_domain(operation_logger, new_main_domain=None):
"""
from yunohost.tools import _set_hostname
from yunohost.app import app_ssowatconf
# If no new domain specified, we return the current main domain
if not new_main_domain:
@ -614,6 +614,8 @@ def domain_url_available(domain, path):
path -- The path to check (e.g. /coffee)
"""
from yunohost.app import _get_conflicting_apps
return len(_get_conflicting_apps(domain, path)) == 0
@ -623,7 +625,8 @@ def _get_raw_domain_settings(domain):
so the file may be completely empty
"""
_assert_domain_exists(domain)
path = DomainConfigPanel.save_path_tpl.format(entity=domain)
# NB: this corresponds to save_path_tpl in DomainConfigPanel
path = f"{DOMAIN_SETTINGS_DIR}/{domain}.yml"
if os.path.exists(path):
return read_yaml(path)
@ -647,6 +650,7 @@ def domain_config_get(domain, key="", full=False, export=False):
else:
mode = "classic"
DomainConfigPanel = _get_DomainConfigPanel()
config = DomainConfigPanel(domain)
return config.get(key, mode)
@ -658,11 +662,17 @@ def domain_config_set(
"""
Apply a new domain configuration
"""
from yunohost.utils.form import BaseOption
DomainConfigPanel = _get_DomainConfigPanel()
BaseOption.operation_logger = operation_logger
config = DomainConfigPanel(domain)
return config.set(key, value, args, args_file, operation_logger=operation_logger)
def _get_DomainConfigPanel():
from yunohost.utils.configpanel import ConfigPanel
class DomainConfigPanel(ConfigPanel):
entity_type = "domain"
save_path_tpl = f"{DOMAIN_SETTINGS_DIR}/{{entity}}.yml"
@ -693,7 +703,9 @@ class DomainConfigPanel(ConfigPanel):
if not any_filter or panel_id == "dns":
from yunohost.dns import _get_registrar_config_section
raw_config["dns"]["registrar"] = _get_registrar_config_section(self.entity)
raw_config["dns"]["registrar"] = _get_registrar_config_section(
self.entity
)
# Cert stuff
if not any_filter or panel_id == "cert":
@ -721,7 +733,9 @@ class DomainConfigPanel(ConfigPanel):
# FIXME not sure why "summary" was injected in settings values
# ("summary", "summary")
]:
raw_config["cert"]["cert"][option_id]["default"] = status[status_key]
raw_config["cert"]["cert"][option_id]["default"] = status[
status_key
]
# Other specific strings used in config panels
# i18n: domain_config_cert_renew_help
@ -739,7 +753,7 @@ class DomainConfigPanel(ConfigPanel):
}
if "default_app" in next_settings:
from yunohost.app import app_ssowatconf, app_map
from yunohost.app import app_map
if "/" in app_map(raw=True).get(self.entity, {}):
raise YunohostValidationError(
@ -816,6 +830,8 @@ class DomainConfigPanel(ConfigPanel):
# Reload ssowat if default app changed
if "default_app" in next_settings:
from yunohost.app import app_ssowatconf
app_ssowatconf()
stuff_to_regen_conf = set()
@ -828,6 +844,8 @@ class DomainConfigPanel(ConfigPanel):
if stuff_to_regen_conf:
regen_conf(names=list(stuff_to_regen_conf))
return DomainConfigPanel
def domain_action_run(domain, action, args=None):
import urllib.parse