From 260801d4aff887894b56d2c149464e671e9a0725 Mon Sep 17 00:00:00 2001 From: ievgenii vdovenko Date: Mon, 4 Aug 2025 16:27:12 +0200 Subject: [PATCH] feature: moves logic of dumping default values to ini file --- rhodecode/apps/file_store/__init__.py | 2 -- rhodecode/config/config_maker.py | 49 ++++----------------------- rhodecode/config/settings_maker.py | 38 +++++++++++++++++++-- rhodecode/lib/hook_daemon/utils.py | 6 ++-- rhodecode/lib/pyramid_utils.py | 7 ++-- 5 files changed, 49 insertions(+), 53 deletions(-) diff --git a/rhodecode/apps/file_store/__init__.py b/rhodecode/apps/file_store/__init__.py index cd9f1c86..33e99761 100755 --- a/rhodecode/apps/file_store/__init__.py +++ b/rhodecode/apps/file_store/__init__.py @@ -50,14 +50,12 @@ def _sanitize_settings_and_apply_defaults(settings): settings_maker.make_setting( config_keys.legacy_filesystem_storage_path, default_store_dir, - default_when_empty=True, ) # filesystem defaults settings_maker.make_setting( config_keys.filesystem_storage_path, default_store_dir, - default_when_empty=True, ) settings_maker.make_setting(config_keys.filesystem_shards, 8, parser="int") diff --git a/rhodecode/config/config_maker.py b/rhodecode/config/config_maker.py index d2e1c306..08ff4ec8 100644 --- a/rhodecode/config/config_maker.py +++ b/rhodecode/config/config_maker.py @@ -22,40 +22,12 @@ import logging from pyramid.settings import asbool -from rhodecode.config.settings_maker import SettingsMaker +from rhodecode.config.settings_maker import SettingsMaker, generate_token from rhodecode.config import utils as config_utils log = logging.getLogger(__name__) -def initialize_ini_config_default_values_if_not_present(ini_path: str): - from configupdater import ConfigUpdater # use configupdater to not break comments and formatting's - - def dump_config(): - with open(ini_path, "w") as configfile: - updater.write(configfile) - - if not ini_path or not os.path.exists(ini_path): - log.warning("Config file %s not found.", ini_path) - return - - updater = ConfigUpdater() - updater.read(ini_path) - - section = "app:main" - option = "app.service_api.token" - - if not updater[section][option].value.strip(): - updater[section][option] = generate_token() - dump_config() - - -def generate_token(length: int = 32) -> str: - import secrets - - return secrets.token_urlsafe(length) - - def sanitize_settings_and_apply_defaults(global_config, settings): """ Applies settings defaults and does all type conversion. @@ -150,13 +122,11 @@ def sanitize_settings_and_apply_defaults(global_config, settings): "vcs.git.lfs.storage_location", "/var/opt/rhodecode_repo_store/.cache/git_lfs_store", parser="dir:ensured", - default_when_empty=True, ) settings_maker.make_setting( "vcs.hg.largefiles.storage_location", "/var/opt/rhodecode_repo_store/.cache/hg_largefiles_store", parser="dir:ensured", - default_when_empty=True, ) settings_maker.make_setting("vcs.methods.cache", True, parser="bool") @@ -176,31 +146,27 @@ def sanitize_settings_and_apply_defaults(global_config, settings): tmp_cache_dir = jn(temp_store, "rc_cache") # save default, cache dir, and use it for all backends later. - default_cache_dir = settings_maker.make_setting( - "cache_dir", default=tmp_cache_dir, default_when_empty=True, parser="dir:ensured" - ) + default_cache_dir = settings_maker.make_setting("cache_dir", default=tmp_cache_dir, parser="dir:ensured") # exception store cache settings_maker.make_setting( "exception_tracker.store_path", default=jn(default_cache_dir, "exc_store"), - default_when_empty=True, parser="dir:ensured", ) settings_maker.make_setting( "celerybeat-schedule.path", default=jn(default_cache_dir, "celerybeat_schedule", "celerybeat-schedule.db"), - default_when_empty=True, parser="file:ensured", ) # celery - broker_url = settings_maker.make_setting("celery.broker_url", "redis://redis:6379/8", default_when_empty=True) + broker_url = settings_maker.make_setting("celery.broker_url", "redis://redis:6379/8") settings_maker.make_setting("celery.result_backend", broker_url) settings_maker.make_setting("exception_tracker.send_email", False, parser="bool") - settings_maker.make_setting("exception_tracker.email_prefix", "[RHODECODE ERROR]", default_when_empty=True) + settings_maker.make_setting("exception_tracker.email_prefix", "[RHODECODE ERROR]") # sessions, ensure file since no-value is memory settings_maker.make_setting("beaker.session.type", "file") @@ -251,7 +217,6 @@ def sanitize_settings_and_apply_defaults(global_config, settings): settings_maker.make_setting( "archive_cache.filesystem.store_dir", jn(default_cache_dir, "archive_cache"), - default_when_empty=True, ) settings_maker.make_setting("archive_cache.filesystem.cache_shards", 8, parser="int") settings_maker.make_setting("archive_cache.filesystem.cache_size_gb", 10, parser="float") @@ -264,7 +229,6 @@ def sanitize_settings_and_apply_defaults(global_config, settings): settings_maker.make_setting( "archive_cache.objectstore.url", "http://s3-minio:9000", - default_when_empty=True, ) settings_maker.make_setting("archive_cache.objectstore.key", "") settings_maker.make_setting("archive_cache.objectstore.secret", "") @@ -272,7 +236,6 @@ def sanitize_settings_and_apply_defaults(global_config, settings): settings_maker.make_setting( "archive_cache.objectstore.bucket", "rhodecode-archive-cache", - default_when_empty=True, ) settings_maker.make_setting("archive_cache.objectstore.bucket_shards", 8, parser="int") @@ -283,11 +246,11 @@ def sanitize_settings_and_apply_defaults(global_config, settings): settings_maker.make_setting("archive_cache.objectstore.retry_backoff", 1, parser="int") settings_maker.make_setting("archive_cache.objectstore.retry_attempts", 10, parser="int") + settings_maker.make_setting("app.service_api.token", generate_token(), parser="string", write_default_to_ini=True) + settings_maker.env_expand() # configure instance id config_utils.set_instance_id(settings) - initialize_ini_config_default_values_if_not_present(global_config.get("__file__")) - return settings diff --git a/rhodecode/config/settings_maker.py b/rhodecode/config/settings_maker.py index 4bca59d2..a0143487 100644 --- a/rhodecode/config/settings_maker.py +++ b/rhodecode/config/settings_maker.py @@ -33,6 +33,33 @@ log = logging.getLogger(__name__) set_keys = {"__file__": ""} +def initialize_ini_config_default_values_if_not_present( + ini_path: str, option: str, default_val: object, section: str = "app:main" +): + from configupdater import ConfigUpdater # use configupdater to not break comments and formatting's + + def dump_config(): + with open(ini_path, "w") as configfile: + updater.write(configfile) + + if not ini_path or not os.path.exists(ini_path): + log.warning("Config file %s not found.", ini_path) + return + + updater = ConfigUpdater() + updater.read(ini_path) + + if not updater[section][option].value.strip(): + updater[section][option] = default_val + dump_config() + + +def generate_token(length: int = 32) -> str: + import secrets + + return secrets.token_urlsafe(length) + + class SettingsMaker: def __init__(self, app_settings): self.settings = app_settings @@ -154,10 +181,15 @@ class SettingsMaker: logging.config.fileConfig(f.name) os.remove(f.name) - def make_setting(self, key, default, lower=False, default_when_empty=False, parser=None): - input_val = self.settings.get(key, default) + def make_setting(self, key, default, lower=False, parser=None, write_default_to_ini=False): + input_val = self.settings.get(key) - if default_when_empty and not input_val: + if write_default_to_ini and not input_val: + initialize_ini_config_default_values_if_not_present( + ini_path=self.settings.get("__file__"), option=key, default_val=default + ) + + if not input_val: # use default value when value is set in the config but it is empty input_val = default diff --git a/rhodecode/lib/hook_daemon/utils.py b/rhodecode/lib/hook_daemon/utils.py index 0a1eab62..71be7191 100644 --- a/rhodecode/lib/hook_daemon/utils.py +++ b/rhodecode/lib/hook_daemon/utils.py @@ -19,7 +19,7 @@ import time import logging -from rhodecode.config.config_maker import initialize_ini_config_default_values_if_not_present +from rhodecode.config.settings_maker import initialize_ini_config_default_values_if_not_present, generate_token from rhodecode.lib.config_utils import get_app_config_lightweight from rhodecode.lib.hook_daemon.base import Hooks @@ -34,7 +34,9 @@ def prepare_callback_daemon(extras, protocol: str, txn_id=None): hooks_config = {} match protocol: case "celery": - initialize_ini_config_default_values_if_not_present(extras["config"]) + initialize_ini_config_default_values_if_not_present( + ini_path=extras["config"], option="app.service_api.token", default_val=generate_token() + ) config = get_app_config_lightweight(extras["config"]) broker_url = config.get("celery.broker_url") diff --git a/rhodecode/lib/pyramid_utils.py b/rhodecode/lib/pyramid_utils.py index 658d32b1..1be6c45b 100644 --- a/rhodecode/lib/pyramid_utils.py +++ b/rhodecode/lib/pyramid_utils.py @@ -21,19 +21,20 @@ import os from pyramid.paster import bootstrap as pyramid_bootstrap, setup_logging # pragma: no cover from pyramid.threadlocal import get_current_request as pyramid_current_request -from rhodecode.config.config_maker import initialize_ini_config_default_values_if_not_present - def bootstrap(config_uri, options=None, env=None): from rhodecode.config.utils import DEFAULT_USER from rhodecode.lib.config_utils import get_app_config_lightweight from rhodecode.lib.utils2 import AttributeDict from rhodecode.lib.request import Request + from rhodecode.config.settings_maker import initialize_ini_config_default_values_if_not_present, generate_token if env: os.environ.update(env) - initialize_ini_config_default_values_if_not_present(config_uri) + initialize_ini_config_default_values_if_not_present( + ini_path=config_uri, option="app.service_api.token", default_val=generate_token() + ) config = get_app_config_lightweight(config_uri) base_url = config["app.base_url"]