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/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 +} 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 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) diff --git a/src/yunohost/app.py b/src/yunohost/app.py index 62fe9129c..8c35d5e39 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] @@ -1496,8 +1496,12 @@ def app_action_run(app_id, 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() @@ -1508,9 +1512,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 +1525,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,25 +1535,34 @@ 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_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') + + 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 { + "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_id, + "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 @@ -1606,23 +1619,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 @@ -1630,7 +1644,12 @@ def app_config_apply(app_id, args): config_panel = read_json(config_panel) - env = {"YNH_APP_ID": app_id} + 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), + } args = dict(urlparse.parse_qsl(args, keep_blank_values=True)) if args else {} for tab in config_panel.get("panel", []): 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 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])