From fddb79e841470a58f8bea31293417f80c3e1dd7b Mon Sep 17 00:00:00 2001 From: ljf Date: Tue, 17 Aug 2021 17:07:26 +0200 Subject: [PATCH] [wip] Reduce config panel var --- data/helpers.d/configpanel | 18 ++---- src/yunohost/app.py | 116 ++++++++++++++++++------------------- 2 files changed, 60 insertions(+), 74 deletions(-) diff --git a/data/helpers.d/configpanel b/data/helpers.d/configpanel index 5ab199aea..685f30a98 100644 --- a/data/helpers.d/configpanel +++ b/data/helpers.d/configpanel @@ -115,19 +115,16 @@ for panel_name,panel in loaded_toml.items(): if isinstance(section, dict): for name, param in section.items(): if isinstance(param, dict) and param.get('type', 'string') not in ['info', 'warning', 'error']: - print("%s.%s.%s=%s" %(panel_name, section_name, name, param.get('source', 'settings'))) + print("%s=%s" % (name, param.get('source', 'settings'))) EOL ` for param_source in $params_sources do - local _dot_setting=$(echo "$param_source" | cut -d= -f1) - local _snake_setting="YNH_CONFIG_$(ynh_lowerdot_to_uppersnake $_dot_setting)" - local short_setting=$(echo "$_dot_setting" | cut -d. -f3) + local short_setting="$(echo $param_source | cut -d= -f1)" local getter="get__${short_setting}" local source="$(echo $param_source | cut -d= -f2)" sources[${short_setting}]="$source" file_hash[${short_setting}]="" - dot_settings[${short_setting}]="${_dot_setting}" # Get value from getter if exists if type -t $getter 2>/dev/null | grep -q '^function$' 2>/dev/null; then @@ -149,9 +146,6 @@ EOL old[$short_setting]="$source" file_hash[$short_setting]="true" fi - set +u - new[$short_setting]="${!_snake_setting}" - set -u done set -x @@ -191,8 +185,7 @@ _ynh_panel_apply() { _ynh_panel_show() { for short_setting in "${!old[@]}" do - local key="YNH_CONFIG_$(ynh_lowerdot_to_uppersnake $dot_settings[$short_setting])" - ynh_return "$key=${old[$short_setting]}" + ynh_return "${short_setting}=${old[$short_setting]}" done } @@ -238,7 +231,7 @@ _ynh_panel_validate() { fi if [ -n "$result" ] then - local key="YNH_ERROR_$(ynh_lowerdot_to_uppersnake $dot_settings[$short_setting])" + local key="YNH_ERROR_${$short_setting}" ynh_return "$key=$result" is_error=true fi @@ -247,7 +240,7 @@ _ynh_panel_validate() { if [[ "$is_error" == "true" ]] then - ynh_die + ynh_die "" fi set -x @@ -275,7 +268,6 @@ ynh_panel_run() { declare -Ag changed=() declare -Ag file_hash=() declare -Ag sources=() - declare -Ag dot_settings=() ynh_panel_get case $1 in diff --git a/src/yunohost/app.py b/src/yunohost/app.py index d8e4748f6..faa5098c9 100644 --- a/src/yunohost/app.py +++ b/src/yunohost/app.py @@ -1782,59 +1782,49 @@ def app_config_show_panel(operation_logger, app): } env = { - "YNH_APP_ID": app_id, - "YNH_APP_INSTANCE_NAME": app, - "YNH_APP_INSTANCE_NUMBER": str(app_instance_nb), + "app_id": app_id, + "app": app, + "app_instance_nb": str(app_instance_nb), } - # FIXME: this should probably be ran in a tmp workdir... - return_code, parsed_values = hook_exec( - config_script, args=["show"], env=env, return_format="plain_dict" - ) - - if return_code != 0: - raise Exception( - "script/config show return value code: %s (considered as an error)", - return_code, + try: + ret, parsed_values = hook_exec( + config_script, args=["show"], env=env, return_format="plain_dict" ) + # Here again, calling hook_exec could fail miserably, or get + # manually interrupted (by mistake or because script was stuck) + except (KeyboardInterrupt, EOFError, Exception): + raise YunohostError("unexpected_error") logger.debug("Generating global variables:") for tab in config_panel.get("panel", []): - tab_id = tab["id"] # this makes things easier to debug on crash for section in tab.get("sections", []): - section_id = section["id"] for option in section.get("options", []): - option_name = option["name"] - generated_name = ( - "YNH_CONFIG_%s_%s_%s" % (tab_id, section_id, option_name) - ).upper() - option["name"] = generated_name logger.debug( - " * '%s'.'%s'.'%s' -> %s", + " * '%s'.'%s'.'%s'", tab.get("name"), section.get("name"), option.get("name"), - generated_name, ) - if generated_name in parsed_values: + if option['name'] in parsed_values: # code is not adapted for that so we have to mock expected format :/ if option.get("type") == "boolean": - if parsed_values[generated_name].lower() in ("true", "1", "y"): - option["default"] = parsed_values[generated_name] + if parsed_values[option['name']].lower() in ("true", "1", "y"): + option["default"] = parsed_values[option['name']] else: del option["default"] else: - option["default"] = parsed_values[generated_name] + option["default"] = parsed_values[option['name']] args_dict = _parse_args_in_yunohost_format( - {option["name"]: parsed_values[generated_name]}, [option] + parsed_values, [option] ) option["default"] = args_dict[option["name"]][0] else: logger.debug( "Variable '%s' is not declared by config script, using default", - generated_name, + option['name'], ) # do nothing, we'll use the default if present @@ -1869,32 +1859,26 @@ def app_config_apply(operation_logger, app, args): operation_logger.start() app_id, app_instance_nb = _parse_app_instance_name(app) env = { - "YNH_APP_ID": app_id, - "YNH_APP_INSTANCE_NAME": app, - "YNH_APP_INSTANCE_NUMBER": str(app_instance_nb), + "app_id": app_id, + "app": app, + "app_instance_nb": str(app_instance_nb), } args = dict(urllib.parse.parse_qsl(args, keep_blank_values=True)) if args else {} upload_dir = None for tab in config_panel.get("panel", []): - tab_id = tab["id"] # this makes things easier to debug on crash for section in tab.get("sections", []): - section_id = section["id"] for option in section.get("options", []): - option_name = option["name"] - generated_name = ( - "YNH_CONFIG_%s_%s_%s" % (tab_id, section_id, option_name) - ).upper() - if generated_name in args: + if option['name'] in args: # Upload files from API # A file arg contains a string with "FILENAME:BASE64_CONTENT" if 'type' in option and option["type"] == "file" \ and msettings.get('interface') == 'api': if upload_dir is None: upload_dir = tempfile.mkdtemp(prefix='tmp_configpanel_') - filename = args[generated_name + '[name]'] - content = args[generated_name] + filename = args[option['name'] + '[name]'] + content = args[option['name']] logger.debug("Save uploaded file %s from API into %s", filename, upload_dir) # Filename is given by user of the API. For security reason, we have replaced @@ -1912,14 +1896,14 @@ def app_config_apply(operation_logger, app, args): raise YunohostError("cannot_write_file", file=file_path, error=str(e)) except Exception as e: raise YunohostError("error_writing_file", file=file_path, error=str(e)) - args[generated_name] = file_path + args[option['name']] = file_path logger.debug( - "include into env %s=%s", generated_name, args[generated_name] + "include into env %s=%s", option['name'], args[option['name']] ) - env[generated_name] = args[generated_name] + env[option['name']] = args[option['name']] else: - logger.debug("no value for key id %s", generated_name) + logger.debug("no value for key id %s", option['name']) # for debug purpose for key in args: @@ -1928,25 +1912,21 @@ def app_config_apply(operation_logger, app, args): "Ignore key '%s' from arguments because it is not in the config", key ) - # FIXME: this should probably be ran in a tmp workdir... - return_code = hook_exec( - config_script, - args=["apply"], - env=env, - )[0] - - # Delete files uploaded from API - if msettings.get('interface') == 'api': - if upload_dir is not None: - shutil.rmtree(upload_dir) - - if return_code != 0: - msg = ( - "'script/config apply' return value code: %s (considered as an error)" - % return_code + try: + hook_exec( + config_script, + args=["apply"], + env=env ) - operation_logger.error(msg) - raise Exception(msg) + # Here again, calling hook_exec could fail miserably, or get + # manually interrupted (by mistake or because script was stuck) + except (KeyboardInterrupt, EOFError, Exception): + raise YunohostError("unexpected_error") + finally: + # Delete files uploaded from API + if msettings.get('interface') == 'api': + if upload_dir is not None: + shutil.rmtree(upload_dir) logger.success("Config updated as expected") return { @@ -2991,16 +2971,30 @@ class DisplayTextArgumentParser(YunoHostArgumentFormatParser): def parse(self, question, user_answers): print(question["ask"]) +class FileArgumentParser(YunoHostArgumentFormatParser): + argument_type = "file" + + ARGUMENTS_TYPE_PARSERS = { "string": StringArgumentParser, + "text": StringArgumentParser, + "select": StringArgumentParser, + "tags": StringArgumentParser, + "email": StringArgumentParser, + "url": StringArgumentParser, + "date": StringArgumentParser, + "time": StringArgumentParser, + "color": StringArgumentParser, "password": PasswordArgumentParser, "path": PathArgumentParser, "boolean": BooleanArgumentParser, "domain": DomainArgumentParser, "user": UserArgumentParser, "number": NumberArgumentParser, + "range": NumberArgumentParser, "display_text": DisplayTextArgumentParser, + "file": FileArgumentParser, }