##// END OF EJS Templates
feat(configs): deprecared old hooks protocol and ssh wrapper....
feat(configs): deprecared old hooks protocol and ssh wrapper. New defaults are now set on v2 keys, so previous installation are automatically set to new keys. Fallback mode is still available.

File last commit:

r5337:363e5238 default
r5496:cab50adf default
Show More
settings_maker.py
184 lines | 6.3 KiB | text/x-python | PythonLexer
# Copyright (C) 2010-2023 RhodeCode GmbH
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License, version 3
# (only), as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# This program is dual-licensed. If you wish to learn more about the
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
import os
import textwrap
import string
import functools
import logging
import tempfile
import logging.config
from rhodecode.lib.type_utils import str2bool, aslist
log = logging.getLogger(__name__)
# skip keys, that are set here, so we don't double process those
set_keys = {
'__file__': ''
}
class SettingsMaker:
def __init__(self, app_settings):
self.settings = app_settings
@classmethod
def _bool_func(cls, input_val):
if isinstance(input_val, bytes):
# decode to str
input_val = input_val.decode('utf8')
return str2bool(input_val)
@classmethod
def _int_func(cls, input_val):
return int(input_val)
@classmethod
def _float_func(cls, input_val):
return float(input_val)
@classmethod
def _list_func(cls, input_val, sep=','):
return aslist(input_val, sep=sep)
@classmethod
def _string_func(cls, input_val, lower=True):
if lower:
input_val = input_val.lower()
return input_val
@classmethod
def _string_no_quote_func(cls, input_val, lower=True):
"""
Special case string function that detects if value is set to empty quote string
e.g.
core.binar_dir = ""
"""
input_val = cls._string_func(input_val, lower=lower)
if input_val in ['""', "''"]:
return ''
@classmethod
def _dir_func(cls, input_val, ensure_dir=False, mode=0o755):
# ensure we have our dir created
if not os.path.isdir(input_val) and ensure_dir:
os.makedirs(input_val, mode=mode, exist_ok=True)
if not os.path.isdir(input_val):
raise Exception(f'Dir at {input_val} does not exist')
return input_val
@classmethod
def _file_path_func(cls, input_val, ensure_dir=False, mode=0o755):
dirname = os.path.dirname(input_val)
cls._dir_func(dirname, ensure_dir=ensure_dir)
return input_val
@classmethod
def _key_transformator(cls, key):
return "{}_{}".format('RC'.upper(), key.upper().replace('.', '_').replace('-', '_'))
def maybe_env_key(self, key):
# now maybe we have this KEY in env, search and use the value with higher priority.
transformed_key = self._key_transformator(key)
envvar_value = os.environ.get(transformed_key)
if envvar_value:
log.debug('using `%s` key instead of `%s` key for config', transformed_key, key)
return envvar_value
def env_expand(self):
replaced = {}
for k, v in self.settings.items():
if k not in set_keys:
envvar_value = self.maybe_env_key(k)
if envvar_value:
replaced[k] = envvar_value
set_keys[k] = envvar_value
# replace ALL keys updated
self.settings.update(replaced)
def enable_logging(self, logging_conf=None, level='INFO', formatter='generic'):
"""
Helper to enable debug on running instance
:return:
"""
if not str2bool(self.settings.get('logging.autoconfigure')):
log.info('logging configuration based on main .ini file')
return
if logging_conf is None:
logging_conf = self.settings.get('logging.logging_conf_file') or ''
if not os.path.isfile(logging_conf):
log.error('Unable to setup logging based on %s, '
'file does not exist.... specify path using logging.logging_conf_file= config setting. ', logging_conf)
return
with open(logging_conf, 'rt') as f:
ini_template = textwrap.dedent(f.read())
ini_template = string.Template(ini_template).safe_substitute(
RC_LOGGING_LEVEL=os.environ.get('RC_LOGGING_LEVEL', '') or level,
RC_LOGGING_FORMATTER=os.environ.get('RC_LOGGING_FORMATTER', '') or formatter
)
with tempfile.NamedTemporaryFile(prefix='rc_logging_', suffix='.ini', delete=False) as f:
log.info('Saved Temporary LOGGING config at %s', f.name)
f.write(ini_template)
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)
if default_when_empty and not input_val:
# use default value when value is set in the config but it is empty
input_val = default
parser_func = {
'bool': self._bool_func,
'int': self._int_func,
'float': self._float_func,
'list': self._list_func,
'list:newline': functools.partial(self._list_func, sep='/n'),
'list:spacesep': functools.partial(self._list_func, sep=' '),
'string': functools.partial(self._string_func, lower=lower),
'string:noquote': functools.partial(self._string_no_quote_func, lower=lower),
'dir': self._dir_func,
'dir:ensured': functools.partial(self._dir_func, ensure_dir=True),
'file': self._file_path_func,
'file:ensured': functools.partial(self._file_path_func, ensure_dir=True),
None: lambda i: i
}[parser]
envvar_value = self.maybe_env_key(key)
if envvar_value:
input_val = envvar_value
set_keys[key] = input_val
self.settings[key] = parser_func(input_val)
return self.settings[key]