From b1634785fb510d3a0def3931845420b3b38a870f Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Mon, 17 Jun 2019 17:32:47 +0200 Subject: [PATCH 1/3] Add a new 'plain_dict' return type for hook_exec, and use it for app config --- src/yunohost/app.py | 33 +++++++-------------------------- src/yunohost/hook.py | 28 ++++++++++++++++++++-------- 2 files changed, 27 insertions(+), 34 deletions(-) diff --git a/src/yunohost/app.py b/src/yunohost/app.py index 1f172a267..c6187a52b 100644 --- a/src/yunohost/app.py +++ b/src/yunohost/app.py @@ -362,10 +362,10 @@ def app_info(app, show_status=False, raw=False): ret['upgradable'] = upgradable ret['change_url'] = os.path.exists(os.path.join(app_setting_path, "scripts", "change_url")) - + with open(os.path.join(APPS_SETTING_PATH, app, 'manifest.json')) as json_manifest: manifest = json.load(json_manifest) - + ret['version'] = manifest.get('version', '-') return ret @@ -1606,31 +1606,12 @@ def app_config_show_panel(app): "YNH_APP_INSTANCE_NAME": app, "YNH_APP_INSTANCE_NUMBER": str(app_instance_nb), } - parsed_values = {} - # I need to parse stdout to communicate between scripts because I can't - # read the child environment :( (that would simplify things so much) - # after hours of research this is apparently quite a standard way, another - # option would be to add an explicite pipe or a named pipe for that - # a third option would be to write in a temporary file but I don't like - # that because that could expose sensitive data - def parse_stdout(line): - line = line.rstrip() - logger.info(line) - - if line.strip().startswith("YNH_CONFIG_") and "=" in line: - # XXX error handling? - # XXX this might not work for multilines stuff :( (but echo without - # formatting should do it no?) - key, value = line.strip().split("=", 1) - logger.debug("config script declared: %s -> %s", key, value) - parsed_values[key] = value - - return_code = hook_exec(config_script, - args=["show"], - env=env, - stdout_callback=parse_stdout, - )[0] + 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) diff --git a/src/yunohost/hook.py b/src/yunohost/hook.py index 42807fdf7..f1b7515bc 100644 --- a/src/yunohost/hook.py +++ b/src/yunohost/hook.py @@ -298,7 +298,7 @@ def hook_callback(action, hooks=[], args=None, no_trace=False, chdir=None, def hook_exec(path, args=None, raise_on_error=False, no_trace=False, chdir=None, env=None, user="root", stdout_callback=None, - stderr_callback=None): + stderr_callback=None, return_format="json"): """ Execute hook from a file with arguments @@ -401,19 +401,31 @@ def hook_exec(path, args=None, raise_on_error=False, no_trace=False, try: with open(stdreturn, 'r') as f: raw_content = f.read() - if raw_content != '': - returnjson = read_json(stdreturn) + returncontent = {} + + if return_format == "json": + if raw_content != '': + try: + returncontent = read_json(stdreturn) + except Exception as e: + raise YunohostError('hook_json_return_error', + path=path, msg=str(e), + raw_content=raw_content) + + elif return_format == "plain_dict": + for line in raw_content.split("\n"): + if "=" in line: + key, value = line.strip().split("=", 1) + returncontent[key] = value + else: - returnjson = {} - except Exception as e: - raise YunohostError('hook_json_return_error', path=path, msg=str(e), - raw_content=raw_content) + raise YunohostError("Excepted value for return_format is either 'json' or 'plain_dict', got '%s'" % return_format) finally: stdreturndir = os.path.split(stdreturn)[0] os.remove(stdreturn) os.rmdir(stdreturndir) - return returncode, returnjson + return returncode, returncontent def _extract_filename_parts(filename): From 52d1aff2ae6a9a7bbd3ee8b51a2d9f577b710f6e Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Tue, 18 Jun 2019 15:11:19 +0200 Subject: [PATCH 2/3] Remove unused stdout/stderr_callback arg --- src/yunohost/hook.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/yunohost/hook.py b/src/yunohost/hook.py index f1b7515bc..67e77f033 100644 --- a/src/yunohost/hook.py +++ b/src/yunohost/hook.py @@ -297,8 +297,7 @@ def hook_callback(action, hooks=[], args=None, no_trace=False, chdir=None, def hook_exec(path, args=None, raise_on_error=False, no_trace=False, - chdir=None, env=None, user="root", stdout_callback=None, - stderr_callback=None, return_format="json"): + chdir=None, env=None, user="root", return_format="json"): """ Execute hook from a file with arguments @@ -372,8 +371,8 @@ def hook_exec(path, args=None, raise_on_error=False, no_trace=False, # Define output callbacks and call command callbacks = ( - stdout_callback if stdout_callback else lambda l: logger.debug(l.rstrip()+"\r"), - stderr_callback if stderr_callback else lambda l: logger.warning(l.rstrip()), + lambda l: logger.debug(l.rstrip()+"\r"), + lambda l: logger.warning(l.rstrip()), ) if stdinfo: From 5262b52cffd7ed649a69fd62f74fa79a05d88597 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Tue, 18 Jun 2019 16:03:00 +0200 Subject: [PATCH 3/3] Add a helper to easily return stuff in config script --- data/helpers.d/logging | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/data/helpers.d/logging b/data/helpers.d/logging index 9e8cc06cb..ed8054622 100644 --- a/data/helpers.d/logging +++ b/data/helpers.d/logging @@ -282,6 +282,16 @@ ynh_script_progression () { ynh_print_info "[$progression_bar] > ${message}${print_exec_time}" } +# Return data to the Yunohost core for later processing +# (to be used by special hooks like app config panel and core diagnosis) +# +# usage: ynh_return somedata +# +# Requires YunoHost version 3.6.0 or higher. +ynh_return () { + echo "$1" >> "$YNH_STDRETURN" +} + # Debugger for app packagers # # usage: ynh_debug [--message=message] [--trace=1/0]