From b52297b8e12b66f29ef349e9e8132168429ca5a9 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Fri, 7 Sep 2018 16:47:32 +0200 Subject: [PATCH 1/9] [i18n] Translated using Weblate (Arabic) (#539) Currently translated at 91.8% (371 of 404 strings) --- locales/ar.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/locales/ar.json b/locales/ar.json index cda9c2c8b..f300ec864 100644 --- a/locales/ar.json +++ b/locales/ar.json @@ -296,8 +296,8 @@ "restore_system_part_failed": "Unable to restore the '{part:s}' system part", "server_shutdown": "سوف ينطفئ الخادوم", "server_shutdown_confirm": "سوف ينطفئ الخادوم حالا. متأكد ؟ [{answers:s}]", - "server_reboot": "The server will reboot", - "server_reboot_confirm": "The server will reboot immediatly, are you sure? [{answers:s}]", + "server_reboot": "سيعاد تشغيل الخادوم", + "server_reboot_confirm": "سيعاد تشغيل الخادوم في الحين. هل أنت متأكد ؟ [{answers:s}]", "service_add_failed": "تعذرت إضافة خدمة '{service:s}'", "service_added": "The service '{service:s}' has been added", "service_already_started": "Service '{service:s}' has already been started", From 9550bf3eb15906b4864ce4b22ccc96e6fa9a61c8 Mon Sep 17 00:00:00 2001 From: Maniack Crudelis Date: Fri, 7 Sep 2018 16:50:17 +0200 Subject: [PATCH 2/9] Add many print helpers (#523) * Add many print helpers * Typo fix --- data/helpers.d/print | 103 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 99 insertions(+), 4 deletions(-) diff --git a/data/helpers.d/print b/data/helpers.d/print index d35c3e929..93d402e64 100644 --- a/data/helpers.d/print +++ b/data/helpers.d/print @@ -8,12 +8,11 @@ ynh_die() { # Display a message in the 'INFO' logging category # # usage: ynh_info "Some message" -ynh_info() -{ - echo "$1" >>"$YNH_STDINFO" +ynh_print_info() { + echo "$1" >> "$YNH_STDINFO" } -# Ignore the yunohost-cli log to prevent errors with conditionals commands +# Ignore the yunohost-cli log to prevent errors with conditional commands # # [internal] # @@ -29,3 +28,99 @@ ynh_no_log() { sudo mv ${ynh_cli_log}-move ${ynh_cli_log} return $? } + +# Main printer, just in case in the future we have to change anything about that. +# +# [internal] +# +ynh_print_log () { + echo -e "${1}" +} + +# Print a warning on stderr +# +# usage: ynh_print_warn "Text to print" +# | arg: text - The text to print +ynh_print_warn () { + ynh_print_log "\e[93m\e[1m[WARN]\e[0m ${1}" >&2 +} + +# Print an error on stderr +# +# usage: ynh_print_err "Text to print" +# | arg: text - The text to print +ynh_print_err () { + ynh_print_log "\e[91m\e[1m[ERR]\e[0m ${1}" >&2 +} + +# Execute a command and print the result as an error +# +# usage: ynh_exec_err command to execute +# usage: ynh_exec_err "command to execute | following command" +# In case of use of pipes, you have to use double quotes. Otherwise, this helper will be executed with the first command, then be sent to the next pipe. +# +# | arg: command - command to execute +ynh_exec_err () { + ynh_print_err "$(eval $@)" +} + +# Execute a command and print the result as a warning +# +# usage: ynh_exec_warn command to execute +# usage: ynh_exec_warn "command to execute | following command" +# In case of use of pipes, you have to use double quotes. Otherwise, this helper will be executed with the first command, then be sent to the next pipe. +# +# | arg: command - command to execute +ynh_exec_warn () { + ynh_print_warn "$(eval $@)" +} + +# Execute a command and force the result to be printed on stdout +# +# usage: ynh_exec_warn_less command to execute +# usage: ynh_exec_warn_less "command to execute | following command" +# In case of use of pipes, you have to use double quotes. Otherwise, this helper will be executed with the first command, then be sent to the next pipe. +# +# | arg: command - command to execute +ynh_exec_warn_less () { + eval $@ 2>&1 +} + +# Execute a command and redirect stdout in /dev/null +# +# usage: ynh_exec_quiet command to execute +# usage: ynh_exec_quiet "command to execute | following command" +# In case of use of pipes, you have to use double quotes. Otherwise, this helper will be executed with the first command, then be sent to the next pipe. +# +# | arg: command - command to execute +ynh_exec_quiet () { + eval $@ > /dev/null +} + +# Execute a command and redirect stdout and stderr in /dev/null +# +# usage: ynh_exec_fully_quiet command to execute +# usage: ynh_exec_fully_quiet "command to execute | following command" +# In case of use of pipes, you have to use double quotes. Otherwise, this helper will be executed with the first command, then be sent to the next pipe. +# +# | arg: command - command to execute +ynh_exec_fully_quiet () { + eval $@ > /dev/null 2>&1 +} + +# Remove any logs for all the following commands. +# +# usage: ynh_print_OFF +# WARNING: You should be careful with this helper, and never forget to use ynh_print_ON as soon as possible to restore the logging. +ynh_print_OFF () { + set +x +} + +# Restore the logging after ynh_print_OFF +# +# usage: ynh_print_ON +ynh_print_ON () { + set -x + # Print an echo only for the log, to be able to know that ynh_print_ON has been called. + echo ynh_print_ON > /dev/null +} From 8edc5c1ae35bec49f87a6cef0e612c920abf722c Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Wed, 5 Sep 2018 23:20:31 +0200 Subject: [PATCH 3/9] [mod] uniformise returned info --- src/yunohost/app.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/yunohost/app.py b/src/yunohost/app.py index 62fe9129c..da6e6d767 100644 --- a/src/yunohost/app.py +++ b/src/yunohost/app.py @@ -1544,6 +1544,8 @@ def app_config_show_panel(app_id): if not os.path.exists(config_panel) or not os.path.exists(config_script): return { + "app_id": app_id, + "app_name": app_info_dict["name"], "config_panel": [], } From b111c57aa591f9b60b19a260f70467bdcf8a9fd1 Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Sat, 8 Sep 2018 02:45:18 +0200 Subject: [PATCH 4/9] [fix] app_id is id in app list, not in yunohost --- data/actionsmap/yunohost.yml | 24 +++++++++--------- src/yunohost/app.py | 49 ++++++++++++++++++++---------------- 2 files changed, 40 insertions(+), 33 deletions(-) diff --git a/data/actionsmap/yunohost.yml b/data/actionsmap/yunohost.yml index 140f8bc6a..ec4a6bf08 100644 --- a/data/actionsmap/yunohost.yml +++ b/data/actionsmap/yunohost.yml @@ -780,18 +780,18 @@ app: ### app_action_list() list: action_help: List app actions - api: GET /apps//actions + api: GET /apps//actions arguments: - app_id: - help: app id + app: + help: App name ### app_action_run() run: action_help: Run app action - api: PUT /apps//actions/ + api: PUT /apps//actions/ arguments: - app_id: - help: app id + app: + help: App name action: help: action id -a: @@ -805,18 +805,18 @@ app: ### app_config_show_panel() show-panel: action_help: show config panel for the application - api: GET /apps//config-panel + api: GET /apps//config-panel arguments: - app_id: - help: App ID + app: + help: App name ### app_config_apply() apply: action_help: apply the new configuration - api: POST /apps//config + api: POST /apps//config arguments: - app_id: - help: App ID + app: + help: App name -a: full: --args help: Serialized arguments for new configuration (i.e. "domain=domain.tld&path=/path") diff --git a/src/yunohost/app.py b/src/yunohost/app.py index da6e6d767..3b5cecd7b 100644 --- a/src/yunohost/app.py +++ b/src/yunohost/app.py @@ -1461,33 +1461,33 @@ def app_change_label(auth, app, new_label): # actions todo list: # * docstring -def app_action_list(app_id): +def app_action_list(app): logger.warning(m18n.n('experimental_feature')) # this will take care of checking if the app is installed - app_info_dict = app_info(app_id) + app_info_dict = app_info(app) - actions = os.path.join(APPS_SETTING_PATH, app_id, 'actions.json') + actions = os.path.join(APPS_SETTING_PATH, app, 'actions.json') return { - "app_id": app_id, + "app": app, "app_name": app_info_dict["name"], "actions": read_json(actions) if os.path.exists(actions) else [], } -def app_action_run(app_id, action, args=None): +def app_action_run(app, action, args=None): logger.warning(m18n.n('experimental_feature')) from yunohost.hook import hook_exec import tempfile # will raise if action doesn't exist - actions = app_action_list(app_id)["actions"] + actions = app_action_list(app)["actions"] actions = {x["id"]: x for x in actions} if action not in actions: - raise MoulinetteError(errno.EINVAL, "action '%s' not available for app '%s', available actions are: %s" % (action, app_id, ", ".join(actions.keys()))) + raise MoulinetteError(errno.EINVAL, "action '%s' not available for app '%s', available actions are: %s" % (action, app, ", ".join(actions.keys()))) action_declaration = actions[action] @@ -1508,9 +1508,9 @@ def app_action_run(app_id, action, args=None): os.chmod(path, 700) if action_declaration.get("cwd"): - cwd = action_declaration["cwd"].replace("$app_id", app_id) + cwd = action_declaration["cwd"].replace("$app", app_id) else: - cwd = "/etc/yunohost/apps/" + app_id + cwd = "/etc/yunohost/apps/" + app retcode = hook_exec( path, @@ -1521,7 +1521,7 @@ def app_action_run(app_id, action, args=None): ) if retcode not in action_declaration.get("accepted_return_codes", [0]): - raise MoulinetteError(retcode, "Error while executing action '%s' of app '%s': return code %s" % (action, app_id, retcode)) + raise MoulinetteError(retcode, "Error while executing action '%s' of app '%s': return code %s" % (action, app, retcode)) os.remove(path) @@ -1531,27 +1531,31 @@ def app_action_run(app_id, action, args=None): # Config panel todo list: # * docstrings # * merge translations on the json once the workflow is in place -def app_config_show_panel(app_id): +def app_config_show_panel(app): logger.warning(m18n.n('experimental_feature')) from yunohost.hook import hook_exec # this will take care of checking if the app is installed - app_info_dict = app_info(app_id) + app_info_dict = app_info(app) + + config_panel = os.path.join(APPS_SETTING_PATH, app, 'config_panel.json') + config_script = os.path.join(APPS_SETTING_PATH, app, 'scripts', 'config') - config_panel = os.path.join(APPS_SETTING_PATH, app_id, 'config_panel.json') - config_script = os.path.join(APPS_SETTING_PATH, app_id, 'scripts', 'config') if not os.path.exists(config_panel) or not os.path.exists(config_script): return { "app_id": app_id, + "app": app, "app_name": app_info_dict["name"], "config_panel": [], } config_panel = read_json(config_panel) - env = {"YNH_APP_ID": app_id} + env = { + "YNH_APP_ID": app, + } parsed_values = {} # I need to parse stdout to communicate between scripts because I can't @@ -1608,23 +1612,24 @@ def app_config_show_panel(app_id): return { "app_id": app_id, + "app": app, "app_name": app_info_dict["name"], "config_panel": config_panel, } -def app_config_apply(app_id, args): +def app_config_apply(app, args): logger.warning(m18n.n('experimental_feature')) from yunohost.hook import hook_exec - installed = _is_installed(app_id) + installed = _is_installed(app) if not installed: raise MoulinetteError(errno.ENOPKG, - m18n.n('app_not_installed', app=app_id)) + m18n.n('app_not_installed', app=app)) - config_panel = os.path.join(APPS_SETTING_PATH, app_id, 'config_panel.json') - config_script = os.path.join(APPS_SETTING_PATH, app_id, 'scripts', 'config') + config_panel = os.path.join(APPS_SETTING_PATH, app, 'config_panel.json') + config_script = os.path.join(APPS_SETTING_PATH, app, 'scripts', 'config') if not os.path.exists(config_panel) or not os.path.exists(config_script): # XXX real exception @@ -1632,7 +1637,9 @@ def app_config_apply(app_id, args): config_panel = read_json(config_panel) - env = {"YNH_APP_ID": app_id} + env = { + "YNH_APP_ID": app, + } args = dict(urlparse.parse_qsl(args, keep_blank_values=True)) if args else {} for tab in config_panel.get("panel", []): From a95fb3905ef67f67e8e8993f2dead03181edda55 Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Sat, 8 Sep 2018 02:45:33 +0200 Subject: [PATCH 5/9] [enh] add more local variables during config execution --- src/yunohost/app.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/yunohost/app.py b/src/yunohost/app.py index 3b5cecd7b..8c35d5e39 100644 --- a/src/yunohost/app.py +++ b/src/yunohost/app.py @@ -1496,8 +1496,12 @@ def app_action_run(app, action, args=None): args_odict = _parse_args_for_action(actions[action], args=args_dict) args_list = args_odict.values() + app_id, app_instance_nb = _parse_app_instance_name(app) + env_dict = _make_environment_dict(args_odict, prefix="ACTION_") env_dict["YNH_APP_ID"] = app_id + env_dict["YNH_APP_INSTANCE_NAME"] = app + env_dict["YNH_APP_INSTANCE_NUMBER"] = str(app_instance_nb) env_dict["YNH_ACTION"] = action _, path = tempfile.mkstemp() @@ -1542,6 +1546,7 @@ def app_config_show_panel(app): config_panel = os.path.join(APPS_SETTING_PATH, app, 'config_panel.json') config_script = os.path.join(APPS_SETTING_PATH, app, 'scripts', 'config') + app_id, app_instance_nb = _parse_app_instance_name(app) if not os.path.exists(config_panel) or not os.path.exists(config_script): return { @@ -1554,7 +1559,9 @@ def app_config_show_panel(app): config_panel = read_json(config_panel) env = { - "YNH_APP_ID": app, + "YNH_APP_ID": app_id, + "YNH_APP_INSTANCE_NAME": app, + "YNH_APP_INSTANCE_NUMBER": str(app_instance_nb), } parsed_values = {} @@ -1637,8 +1644,11 @@ def app_config_apply(app, args): config_panel = read_json(config_panel) + app_id, app_instance_nb = _parse_app_instance_name(app) env = { - "YNH_APP_ID": app, + "YNH_APP_ID": app_id, + "YNH_APP_INSTANCE_NAME": app, + "YNH_APP_INSTANCE_NUMBER": str(app_instance_nb), } args = dict(urlparse.parse_qsl(args, keep_blank_values=True)) if args else {} From 3d60e2d34bb05f15f7efb69dc830ae41b337a833 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Tue, 11 Sep 2018 14:35:54 +0000 Subject: [PATCH 6/9] Update changelog --- debian/changelog | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/debian/changelog b/debian/changelog index a24f5c054..8b57aeee0 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,18 @@ +yunohost (3.2.0) stable; urgency=low + + * Add many print and exec helpers (#523) + * Add su directive as option for logrotate helper (#511) + * Add equivs, fake-hwclock and jq as base dependencies (#515, #514, #532) + * Allow to add a service description on "yunohost service add" (#529) + * Add option '--need-lock' to 'yunohost service add' (#530) + * Don't backup user home with .nobackup file (#536) + * Add a script to automatically generate helpers documentation (#538) + * [i18n] Improve Arabic translation + + Thanks to all contributors (Bram, Maniack, irina11y, Josue, BoF, ljf, Aleks) ! <3 + + -- Alexandre Aubin Tue, 11 Sep 2018 16:30:00 +0000 + yunohost (3.2.0~testing1) testing; urgency=low * Add logging system of every unit operation (#165) From 8e574d2b5f19173762f01d7be564df2522a6cc86 Mon Sep 17 00:00:00 2001 From: "ljf (zamentur)" Date: Thu, 13 Sep 2018 15:36:18 +0200 Subject: [PATCH 7/9] [fix] Error due to unwanted backslash ! (#541) --- data/hooks/backup/17-data_home | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/hooks/backup/17-data_home b/data/hooks/backup/17-data_home index ea783700a..f7a797b6b 100755 --- a/data/hooks/backup/17-data_home +++ b/data/hooks/backup/17-data_home @@ -12,8 +12,8 @@ backup_dir="${1}/data/home" # Backup user home for f in $(find /home/* -type d -prune | awk -F/ '{print $NF}'); do if [[ ! "$f" =~ ^yunohost|lost\+found ]]; then - if [ ! -e "/home/\$f/.nobackup" ]; then - ynh_backup "/home/\$f" "${backup_dir}/\$f" 1 + if [ ! -e "/home/$f/.nobackup" ]; then + ynh_backup "/home/$f" "${backup_dir}/$f" 1 fi fi done From d420bb240f8a97ce63521e5104d336ecb60a3aef Mon Sep 17 00:00:00 2001 From: "ljf (zamentur)" Date: Thu, 13 Sep 2018 17:00:26 +0200 Subject: [PATCH 8/9] [enh] Don't send email if no certificate need to be renewed (#540) --- src/yunohost/certificate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/yunohost/certificate.py b/src/yunohost/certificate.py index a2886c266..049eeb0f4 100644 --- a/src/yunohost/certificate.py +++ b/src/yunohost/certificate.py @@ -340,7 +340,7 @@ def certificate_renew(auth, domain_list, force=False, no_checks=False, email=Fal domain_list.append(domain) - if len(domain_list) == 0: + if len(domain_list) == 0 and not email: logger.info("No certificate needs to be renewed.") # Else, validate the domain list given From 9e87da8d2656355428a11fb482852995f46bd1a3 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Fri, 14 Sep 2018 15:03:36 +0200 Subject: [PATCH 9/9] [yolo] Add head -n1, because on some setups like stupid OVH, 'VERSION_ID' is duplicated :| --- src/yunohost/data_migrations/0003_migrate_to_stretch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/yunohost/data_migrations/0003_migrate_to_stretch.py b/src/yunohost/data_migrations/0003_migrate_to_stretch.py index 7347f0e66..26f91ae0b 100644 --- a/src/yunohost/data_migrations/0003_migrate_to_stretch.py +++ b/src/yunohost/data_migrations/0003_migrate_to_stretch.py @@ -94,7 +94,7 @@ class MyMigration(Migration): # with /etc/lsb-release for instance -_-) # Instead, we rely on /etc/os-release which should be the raw info from # the distribution... - return int(check_output("grep VERSION_ID /etc/os-release | tr '\"' ' ' | cut -d ' ' -f2")) + return int(check_output("grep VERSION_ID /etc/os-release | head -n 1 | tr '\"' ' ' | cut -d ' ' -f2")) def yunohost_major_version(self): return int(get_installed_version("yunohost").split('.')[0])