Merge branch 'dev' into enh-dns-autoconf

This commit is contained in:
Alexandre Aubin 2021-09-16 20:57:18 +02:00
commit 23ab7776ce
20 changed files with 154 additions and 73 deletions

View file

@ -20,7 +20,7 @@ autofix-translated-strings:
- python3 reformat_locales.py
- '[ $(git diff -w | wc -l) != 0 ] || exit 0' # stop if there is nothing to commit
- git commit -am "[CI] Reformat / remove stale translated strings" || true
- git push -f origin "ci-remove-stale-translated-strings-${CI_COMMIT_REF_NAME}":"ci-remove-stale-translated-strings-${CI_COMMIT_REF_NAME}"
- git push -f origin "HEAD":"ci-remove-stale-translated-strings-${CI_COMMIT_REF_NAME}"
- hub pull-request -m "[CI] Reformat / remove stale translated strings" -b Yunohost:dev -p || true # GITHUB_USER and GITHUB_TOKEN registered here https://gitlab.com/yunohost/yunohost/-/settings/ci_cd
only:
variables:

View file

@ -43,12 +43,14 @@ ynh_replace_string () {
local target_file
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
set +o xtrace # set +x
local delimit=@
# Escape the delimiter if it's in the string.
match_string=${match_string//${delimit}/"\\${delimit}"}
replace_string=${replace_string//${delimit}/"\\${delimit}"}
set -o xtrace # set -x
sed --in-place "s${delimit}${match_string}${delimit}${replace_string}${delimit}g" "$target_file"
}

View file

@ -1,6 +1,6 @@
#!/bin/bash
YNH_APP_BASEDIR=$(realpath $([[ "$(basename $0)" =~ ^backup|restore$ ]] && echo '../settings' || echo '..'))
YNH_APP_BASEDIR=$(realpath $([[ "$(basename $0)" =~ ^backup|restore$ ]] && echo '../settings' || [[ -n "${YNH_ACTION:-}" ]] && echo '.' || echo '..' ))
# Handle script crashes / failures
#
@ -519,6 +519,8 @@ ynh_read_var_in_file() {
[[ -f $file ]] || ynh_die --message="File $file does not exists"
set +o xtrace # set +x
# Get the line number after which we search for the variable
local line_number=1
if [[ -n "$after" ]];
@ -526,6 +528,7 @@ ynh_read_var_in_file() {
line_number=$(grep -n $after $file | cut -d: -f1)
if [[ -z "$line_number" ]];
then
set -o xtrace # set -x
return 1
fi
fi
@ -555,6 +558,7 @@ ynh_read_var_in_file() {
# Extract the part after assignation sign
local expression_with_comment="$(tail +$line_number ${file} | grep -i -o -P $var_part'\K.*$' || echo YNH_NULL | head -n1)"
if [[ "$expression_with_comment" == "YNH_NULL" ]]; then
set -o xtrace # set -x
echo YNH_NULL
return 0
fi
@ -570,6 +574,7 @@ ynh_read_var_in_file() {
else
echo "$expression"
fi
set -o xtrace # set -x
}
# Set a value into heterogeneous file (yaml, json, php, python...)
@ -594,6 +599,8 @@ ynh_write_var_in_file() {
[[ -f $file ]] || ynh_die --message="File $file does not exists"
set +o xtrace # set +x
# Get the line number after which we search for the variable
local line_number=1
if [[ -n "$after" ]];
@ -601,6 +608,7 @@ ynh_write_var_in_file() {
line_number=$(grep -n $after $file | cut -d: -f1)
if [[ -z "$line_number" ]];
then
set -o xtrace # set -x
return 1
fi
fi
@ -631,6 +639,7 @@ ynh_write_var_in_file() {
# Extract the part after assignation sign
local expression_with_comment="$(tail +$line_number ${file} | grep -i -o -P $var_part'\K.*$' || echo YNH_NULL | head -n1)"
if [[ "$expression_with_comment" == "YNH_NULL" ]]; then
set -o xtrace # set -x
return 1
fi
@ -661,6 +670,7 @@ ynh_write_var_in_file() {
fi
sed -ri "${range}s$delimiter(^${var_part}).*\$$delimiter\1${value}${endline}${delimiter}i" ${file}
fi
set -o xtrace # set -x
}
@ -727,6 +737,7 @@ ynh_secure_remove () {
local file
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
set +o xtrace # set +x
local forbidden_path=" \
/var/www \
@ -754,6 +765,8 @@ ynh_secure_remove () {
else
ynh_print_info --message="'$file' wasn't deleted because it doesn't exist."
fi
set -o xtrace # set -x
}
# Extract a key from a plain command output

View file

@ -177,7 +177,7 @@
"iptables_unavailable": "No podeu modificar les iptables aquí. O bé sou en un contenidor o bé el vostre nucli no és compatible amb aquesta opció",
"log_corrupted_md_file": "El fitxer de metadades YAML associat amb els registres està malmès: « {md_file} »\nError: {error}",
"log_link_to_log": "El registre complet d'aquesta operació: «<a href=\"#/tools/logs/{name}\" style=\"text-decoration:underline\">{desc}</a>»",
"log_help_to_get_log": "Per veure el registre de l'operació « {desc} », utilitzeu l'ordre «yunohost log show {name}{name} »",
"log_help_to_get_log": "Per veure el registre de l'operació « {desc} », utilitzeu l'ordre «yunohost log show {name} »",
"log_link_to_failed_log": "No s'ha pogut completar l'operació « {desc} ». Per obtenir ajuda, <a href=\"#/tools/logs/{name}\">proveïu el registre complete de l'operació clicant aquí</a>",
"log_help_to_get_failed_log": "No s'ha pogut completar l'operació « {desc} ». Per obtenir ajuda, compartiu el registre complete de l'operació utilitzant l'ordre «yunohost log share {name} »",
"log_does_exists": "No hi ha cap registre per l'operació amb el nom«{log} », utilitzeu «yunohost log list» per veure tots els registre d'operació disponibles",

View file

@ -244,7 +244,7 @@
"dpkg_is_broken": "Du kannst das gerade nicht tun, weil dpkg/APT (der Systempaketmanager) in einem defekten Zustand zu sein scheint.... Du kannst versuchen, dieses Problem zu lösen, indem du dich über SSH verbindest und `sudo apt install --fix-broken` sowie/oder `sudo dpkg --configure -a` ausführst.",
"global_settings_unknown_setting_from_settings_file": "Unbekannter Schlüssel in den Einstellungen: '{setting_key}', verwerfen und speichern in /etc/yunohost/settings-unknown.json",
"log_link_to_log": "Vollständiges Log dieser Operation: '<a href=\"#/tools/logs/{name}\" style=\"text-decoration:underline\">{desc}</a>'",
"log_help_to_get_log": "Um das Protokoll der Operation '{desc}' anzuzeigen, verwenden Sie den Befehl 'yunohost log show {name}{name}'",
"log_help_to_get_log": "Um das Protokoll der Operation '{desc}' anzuzeigen, verwenden Sie den Befehl 'yunohost log show {name}'",
"global_settings_setting_security_nginx_compatibility": "Kompatibilitäts- vs. Sicherheits-Kompromiss für den Webserver NGINX. Betrifft die Ciphers (und andere sicherheitsrelevante Aspekte)",
"global_settings_setting_service_ssh_allow_deprecated_dsa_hostkey": "Erlaubt die Verwendung eines (veralteten) DSA-Hostkeys für die SSH-Daemon-Konfiguration",
"log_app_remove": "Entferne die Applikation '{}'",

View file

@ -15,6 +15,8 @@
"app_already_up_to_date": "{app} is already up-to-date",
"app_argument_choice_invalid": "Use one of these choices '{choices}' for the argument '{name}' instead of '{value}'",
"app_argument_invalid": "Pick a valid value for the argument '{name}': {error}",
"app_argument_password_help_keep": "Press Enter to keep the current value",
"app_argument_password_help_optional": "Type one space to empty the password",
"app_argument_password_no_default": "Error while parsing password argument '{name}': password argument can't have a default value for security reason",
"app_argument_required": "Argument '{name}' is required",
"app_change_url_identical_domains": "The old and new domain/url_path are identical ('{domain}{path}'), nothing to do.",
@ -424,7 +426,7 @@
"log_dyndns_subscribe": "Subscribe to a YunoHost subdomain '{}'",
"log_dyndns_update": "Update the IP associated with your YunoHost subdomain '{}'",
"log_help_to_get_failed_log": "The operation '{desc}' could not be completed. Please share the full log of this operation using the command 'yunohost log share {name}' to get help",
"log_help_to_get_log": "To view the log of the operation '{desc}', use the command 'yunohost log show {name}{name}'",
"log_help_to_get_log": "To view the log of the operation '{desc}', use the command 'yunohost log show {name}'",
"log_letsencrypt_cert_install": "Install a Let's Encrypt certificate on '{}' domain",
"log_letsencrypt_cert_renew": "Renew '{}' Let's Encrypt certificate",
"log_link_to_failed_log": "Could not complete the operation '{desc}'. Please provide the full log of this operation by <a href=\"#/tools/logs/{name}\">clicking here</a> to get help",

View file

@ -326,7 +326,7 @@
"log_dyndns_subscribe": "Aboni al YunoHost-subdominio '{}'",
"password_too_simple_4": "La pasvorto bezonas almenaŭ 12 signojn kaj enhavas ciferon, majuskle, pli malaltan kaj specialajn signojn",
"regenconf_file_updated": "Agordodosiero '{conf}' ĝisdatigita",
"log_help_to_get_log": "Por vidi la protokolon de la operacio '{desc}', uzu la komandon 'yunohost log show {name}{name}'",
"log_help_to_get_log": "Por vidi la protokolon de la operacio '{desc}', uzu la komandon 'yunohost log show {name}'",
"global_settings_setting_security_nginx_compatibility": "Kongruo vs sekureca kompromiso por la TTT-servilo NGINX. Afektas la ĉifradojn (kaj aliajn aspektojn pri sekureco)",
"restore_complete": "Restarigita",
"hook_exec_failed": "Ne povis funkcii skripto: {path}",

View file

@ -325,7 +325,7 @@
"log_does_exists": "No existe ningún registro de actividades con el nombre '{log}', ejecute 'yunohost log list' para ver todos los registros de actividades disponibles",
"log_help_to_get_failed_log": "No se pudo completar la operación «{desc}». Para obtener ayuda, comparta el registro completo de esta operación ejecutando la orden «yunohost log share {name}»",
"log_link_to_failed_log": "No se pudo completar la operación «{desc}». Para obtener ayuda, proporcione el registro completo de esta operación <a href=\"#/tools/logs/{name}\">pulsando aquí</a>",
"log_help_to_get_log": "Para ver el registro de la operación «{desc}», ejecute la orden «yunohost log show {name}{name}»",
"log_help_to_get_log": "Para ver el registro de la operación «{desc}», ejecute la orden «yunohost log show {name}»",
"log_link_to_log": "Registro completo de esta operación: «<a href=\"#/tools/logs/{name}\" style=\"text-decoration:underline\">{desc}</a>»",
"log_corrupted_md_file": "El archivo de metadatos YAML asociado con el registro está dañado: «{md_file}\nError: {error}»",
"hook_json_return_error": "No se pudo leer la respuesta del gancho {path}. Error: {msg}. Contenido sin procesar: {raw_content}",

View file

@ -500,7 +500,7 @@
"log_does_exists": "هیچ گزارش عملیاتی با نام '{log}' وجود ندارد ، برای مشاهده همه گزارش عملیّات های موجود در خط فرمان از دستور 'yunohost log list' استفاده کنید",
"log_help_to_get_failed_log": "عملیات '{desc}' کامل نشد. لطفاً برای دریافت راهنمایی و کمک ، گزارش کامل این عملیات را با استفاده از دستور 'yunohost log share {name}' به اشتراک بگذارید",
"log_link_to_failed_log": "عملیّات '{desc}' کامل نشد. لطفاً گزارش کامل این عملیات را ارائه دهید بواسطه <a href=\"#/tools/logs/{name}\">اینجا را کلیک کنید</a> برای دریافت کمک",
"log_help_to_get_log": "برای مشاهده گزارش عملیات '{desc}'، از دستور 'yunohost log show {name}{name}' استفاده کنید",
"log_help_to_get_log": "برای مشاهده گزارش عملیات '{desc}'، از دستور 'yunohost log show {name}' استفاده کنید",
"log_link_to_log": "گزارش کامل این عملیات: <a href=\"#/tools/logs/{name}\" style=\"text-decoration:underline\">{desc}</a>'",
"log_corrupted_md_file": "فایل فوق داده YAML مربوط به گزارش ها آسیب دیده است: '{md_file}\nخطا: {error} '",
"ldap_server_is_down_restart_it": "سرویس LDAP خاموش است ، سعی کنید آن را دوباره راه اندازی کنید...",

View file

@ -251,7 +251,7 @@
"experimental_feature": "Attention : cette fonctionnalité est expérimentale et ne doit pas être considérée comme stable, vous ne devriez pas l'utiliser à moins que vous ne sachiez ce que vous faites.",
"log_corrupted_md_file": "Le fichier YAML de métadonnées associé aux logs est corrompu : '{md_file}'\nErreur : {error}",
"log_link_to_log": "Journal complet de cette opération : '<a href=\"#/tools/logs/{name}\" style=\"text-decoration:underline\"> {desc} </a>'",
"log_help_to_get_log": "Pour voir le journal de cette opération '{desc}', utilisez la commande 'yunohost log show {name}{name}'",
"log_help_to_get_log": "Pour voir le journal de cette opération '{desc}', utilisez la commande 'yunohost log show {name}'",
"log_link_to_failed_log": "L'opération '{desc}' a échoué ! Pour obtenir de l'aide, merci de partager le journal de l'opération en <a href=\"#/tools/logs/{name}\">cliquant ici</a>",
"log_help_to_get_failed_log": "L'opération '{desc}' a échoué ! Pour obtenir de l'aide, merci de partager le journal de l'opération en utilisant la commande 'yunohost log share {name}'",
"log_does_exists": "Il n'y a pas de journal des opérations avec le nom '{log}', utilisez 'yunohost log list' pour voir tous les journaux d'opérations disponibles",

View file

@ -358,7 +358,7 @@
"global_settings_setting_security_webadmin_allowlist_enabled": "Permitir que só algúns IPs accedan á webadmin.",
"disk_space_not_sufficient_update": "Non hai espazo suficiente no disco para actualizar esta aplicación",
"disk_space_not_sufficient_install": "Non queda espazo suficiente no disco para instalar esta aplicación",
"log_help_to_get_log": "Para ver o rexistro completo da operación '{desc}', usa o comando 'yunohost log show {name}{name}'",
"log_help_to_get_log": "Para ver o rexistro completo da operación '{desc}', usa o comando 'yunohost log show {name}'",
"log_link_to_log": "Rexistro completo desta operación: '<a href=\"#/tools/logs/{name}\" style=\"text-decoration:underline\">{desc}</a>'",
"log_corrupted_md_file": "O ficheiro YAML con metadatos asociado aos rexistros está danado: '{md_file}\nErro: {error}'",
"iptables_unavailable": "Non podes andar remexendo en iptables aquí. Ou ben estás nun contedor ou o teu kernel non ten soporte para isto",

View file

@ -249,7 +249,7 @@
"good_practices_about_admin_password": "Stai per impostare una nuova password di amministratore. La password deve essere almeno di 8 caratteri - anche se è buona pratica utilizzare password più lunghe (es. una frase, una serie di parole) e/o utilizzare vari tipi di caratteri (maiuscole, minuscole, numeri e simboli).",
"log_corrupted_md_file": "Il file dei metadati YAML associato con i registri è danneggiato: '{md_file}'\nErrore: {error}",
"log_link_to_log": "Registro completo di questa operazione: '<a href=\"#/tools/logs/{name}\" style=\"text-decoration:underline\">{desc}</a>'",
"log_help_to_get_log": "Per vedere il registro dell'operazione '{desc}', usa il comando 'yunohost log show {name}{name}'",
"log_help_to_get_log": "Per vedere il registro dell'operazione '{desc}', usa il comando 'yunohost log show {name}'",
"global_settings_setting_security_postfix_compatibility": "Bilanciamento tra compatibilità e sicurezza per il server Postfix. Riguarda gli algoritmi di cifratura (e altri aspetti legati alla sicurezza)",
"log_link_to_failed_log": "Impossibile completare l'operazione '{desc}'! Per ricevere aiuto, per favore fornisci il registro completo dell'operazione <a href=\"#/tools/logs/{name}\">cliccando qui</a>",
"log_help_to_get_failed_log": "L'operazione '{desc}' non può essere completata. Per ottenere aiuto, per favore condividi il registro completo dell'operazione utilizzando il comando 'yunohost log share {name}'",

View file

@ -115,7 +115,7 @@
"domain_deletion_failed": "Kunne ikke slette domene",
"domain_dyndns_already_subscribed": "Du har allerede abonnement på et DynDNS-domene",
"log_link_to_log": "Full logg for denne operasjonen: '<a href=\"#/tools/logs/{name}\" style=\"text-decoration:underline\">{desc}</a>'",
"log_help_to_get_log": "For å vise loggen for operasjonen '{desc}', bruk kommandoen 'yunohost log show {name}{name}'",
"log_help_to_get_log": "For å vise loggen for operasjonen '{desc}', bruk kommandoen 'yunohost log show {name}'",
"log_user_create": "Legg til '{}' bruker",
"app_change_url_success": "{app} nettadressen er nå {domain}{path}",
"app_install_failed": "Kunne ikke installere {app}: {error}"

View file

@ -248,7 +248,7 @@
"experimental_feature": "Atencion: aquesta foncionalitat es experimentala e deu pas èsser considerada coma establa, deuriatz pas lutilizar levat que sapiatz çò que fasètz.",
"log_corrupted_md_file": "Lo fichièr YAML de metadonadas ligat als jornals daudit es damatjat: « {md_file} »\nError: {error}",
"log_link_to_log": "Jornal complèt daquesta operacion: <a href=\"#/tools/logs/{name}\" style=\"text-decoration:underline\">{desc}</a>",
"log_help_to_get_log": "Per veire lo jornal daquesta operacion « {desc} », utilizatz la comanda «yunohost log show {name}{name} »",
"log_help_to_get_log": "Per veire lo jornal daquesta operacion « {desc} », utilizatz la comanda «yunohost log show {name} »",
"log_link_to_failed_log": "Loperacion « {desc} » a pas capitat! Per obténer dajuda, mercés <a href=\"#/tools/logs/{name}\"> de fornir lo jornal complèt de loperacion</a>",
"log_help_to_get_failed_log": "Loperacion « {desc} » a pas reüssit! Per obténer dajuda, mercés de partejar lo jornal daudit complèt daquesta operacion en utilizant la comanda «yunohost log share {name} »",
"log_does_exists": "I a pas cap de jornal daudit per loperacion amb lo nom « {log} », utilizatz «yunohost log list» per veire totes los jornals doperacion disponibles",

View file

@ -248,7 +248,7 @@
"log_does_exists": "Немає журналу операцій з назвою '{log}', використовуйте 'yunohost log list', щоб подивитися всі доступні журнали операцій",
"log_help_to_get_failed_log": "Операція '{desc}' не може бути завершена. Будь ласка, поділіться повним журналом цієї операції, використовуючи команду 'yunohost log share {name}', щоб отримати допомогу",
"log_link_to_failed_log": "Не вдалося завершити операцію '{desc}'. Будь ласка, надайте повний журнал цієї операції, <a href=\"#/tools/logs/{name}\">натиснувши тут</a>, щоб отримати допомогу",
"log_help_to_get_log": "Щоб переглянути журнал операції '{desc}', використовуйте команду 'yunohost log show {name}{name}'",
"log_help_to_get_log": "Щоб переглянути журнал операції '{desc}', використовуйте команду 'yunohost log show {name}'",
"log_link_to_log": "Повний журнал цієї операції: '<a href=\"#/tools/logs/{name}\" style=\"text-decoration:underline\">{desc}</a>'",
"log_corrupted_md_file": "Файл метаданих YAML, пов'язаний з журналами, пошкоджено: '{md_file}\nПомилка: {error}'",
"iptables_unavailable": "Ви не можете грати з iptables тут. Ви перебуваєте або в контейнері, або ваше ядро не підтримує його",

View file

@ -511,7 +511,7 @@
"log_does_exists": "没有名称为'{log}'的操作日志,请使用 'yunohost log list' 查看所有可用的操作日志",
"log_help_to_get_failed_log": "操作'{desc}'无法完成。请使用命令'yunohost log share {name}' 共享此操作的完整日志以获取帮助",
"log_link_to_failed_log": "无法完成操作 '{desc}'。请通过<a href=\"#/tools/logs/{name}\">单击此处</a>提供此操作的完整日志以获取帮助",
"log_help_to_get_log": "要查看操作'{desc}'的日志,请使用命令'yunohost log show {name}{name}'",
"log_help_to_get_log": "要查看操作'{desc}'的日志,请使用命令'yunohost log show {name}'",
"log_link_to_log": "此操作的完整日志: '<a href=\"#/tools/logs/{name}\" style=\"text-decoration:underline\">{desc}</a>'",
"log_corrupted_md_file": "与日志关联的YAML元数据文件已损坏: '{md_file}\n错误: {error}'",
"iptables_unavailable": "你不能在这里使用iptables。你要么在一个容器中要么你的内核不支持它",

View file

@ -1652,25 +1652,34 @@ def app_action_run(operation_logger, app, action, args=None):
)
env_dict["YNH_ACTION"] = action
_, path = tempfile.mkstemp()
tmp_workdir_for_app = _make_tmp_workdir_for_app(app=app)
_, action_script = tempfile.mkstemp(dir=tmp_workdir_for_app)
with open(path, "w") as script:
with open(action_script, "w") as script:
script.write(action_declaration["command"])
os.chmod(path, 700)
if action_declaration.get("cwd"):
cwd = action_declaration["cwd"].replace("$app", app)
else:
cwd = os.path.join(APPS_SETTING_PATH, app)
cwd = tmp_workdir_for_app
# FIXME: this should probably be ran in a tmp workdir...
retcode = hook_exec(
path,
env=env_dict,
chdir=cwd,
user=action_declaration.get("user", "root"),
)[0]
try:
retcode = hook_exec(
action_script,
env=env_dict,
chdir=cwd,
user=action_declaration.get("user", "root"),
)[0]
# Calling hook_exec could fail miserably, or get
# manually interrupted (by mistake or because script was stuck)
# In that case we still want to delete the tmp work dir
except (KeyboardInterrupt, EOFError, Exception):
retcode = -1
import traceback
logger.error(m18n.n("unexpected_error", error="\n" + traceback.format_exc()))
finally:
shutil.rmtree(tmp_workdir_for_app)
if retcode not in action_declaration.get("accepted_return_codes", [0]):
msg = "Error while executing action '%s' of app '%s': return code %s" % (
@ -1681,8 +1690,6 @@ def app_action_run(operation_logger, app, action, args=None):
operation_logger.error(msg)
raise YunohostError(msg, raw_msg=True)
os.remove(path)
operation_logger.success()
return logger.success("Action successed!")
@ -1760,7 +1767,6 @@ class AppConfigPanel(ConfigPanel):
default_script = """#!/bin/bash
source /usr/share/yunohost/helpers
ynh_abort_if_errors
final_path=$(ynh_app_setting_get $app final_path)
ynh_app_config_run $1
"""
write_to_file(config_script, default_script)
@ -1768,11 +1774,13 @@ ynh_app_config_run $1
# Call config script to extract current values
logger.debug(f"Calling '{action}' action from config script")
app_id, app_instance_nb = _parse_app_instance_name(self.app)
settings = _get_app_settings(app_id)
env.update(
{
"app_id": app_id,
"app": self.app,
"app_instance_nb": str(app_instance_nb),
"final_path": settings.get("final_path", "")
}
)
@ -2173,6 +2181,13 @@ def _set_default_ask_questions(arguments):
key = "app_manifest_%s_ask_%s" % (script_name, arg["name"])
arg["ask"] = m18n.n(key)
# Also it in fact doesn't make sense for any of those questions to have an example value nor a default value...
if arg.get("type") in ["domain", "user", "password"]:
if "example" in arg:
del arg["example"]
if "default" in arg:
del arg["domain"]
return arguments

View file

@ -69,7 +69,13 @@ def log_list(limit=None, with_details=False, with_suboperations=False):
logs = list(reversed(sorted(logs)))
if limit is not None:
logs = logs[:limit]
if with_suboperations:
logs = logs[:limit]
else:
# If we displaying only parent, we are still gonna load up to limit * 5 logs
# because many of them are suboperations which are not gonna be kept
# Yet we still want to obtain ~limit number of logs
logs = logs[:limit * 5]
for log in logs:
@ -122,6 +128,9 @@ def log_list(limit=None, with_details=False, with_suboperations=False):
else:
operations = [o for o in operations.values()]
if limit:
operations = operations[:limit]
operations = list(reversed(sorted(operations, key=lambda o: o["name"])))
# Reverse the order of log when in cli, more comfortable to read (avoid
# unecessary scrolling)
@ -151,26 +160,37 @@ def log_show(
filter_irrelevant = True
if filter_irrelevant:
filters = [
r"set [+-]x$",
r"set [+-]o xtrace$",
r"local \w+$",
r"local legacy_args=.*$",
r".*Helper used in legacy mode.*",
r"args_array=.*$",
r"local -A args_array$",
r"ynh_handle_getopts_args",
r"ynh_script_progression",
]
def _filter(lines):
filters = [
r"set [+-]x$",
r"set [+-]o xtrace$",
r"set [+-]o errexit$",
r"set [+-]o nounset$",
r"trap '' EXIT",
r"local \w+$",
r"local exit_code=(1|0)$",
r"local legacy_args=.*$",
r"local -A args_array$",
r"args_array=.*$",
r"ret_code=1",
r".*Helper used in legacy mode.*",
r"ynh_handle_getopts_args",
r"ynh_script_progression",
r"sleep 0.5",
r"'\[' (1|0) -eq (1|0) '\]'$",
r"\[?\['? -n '' '?\]\]?$",
r"rm -rf /var/cache/yunohost/download/$",
r"type -t ynh_clean_setup$",
r"DEBUG - \+ echo '",
r"DEBUG - \+ exit (1|0)$",
]
filters = [re.compile(f) for f in filters]
return [line for line in lines if not any(f.search(line.strip()) for f in filters)]
else:
filters = []
def _filter(lines):
return lines
def _filter_lines(lines, filters=[]):
filters = [re.compile(f) for f in filters]
return [
line for line in lines if not any(f.search(line.strip()) for f in filters)
]
# Normalize log/metadata paths and filenames
abs_path = path
@ -209,7 +229,7 @@ def log_show(
content += "\n============\n\n"
if os.path.exists(log_path):
actual_log = read_file(log_path)
content += "\n".join(_filter_lines(actual_log.split("\n"), filters))
content += "\n".join(_filter(actual_log.split("\n")))
url = yunopaste(content)
@ -282,13 +302,13 @@ def log_show(
if os.path.exists(log_path):
from yunohost.service import _tail
if number and filters:
if number and filter_irrelevant:
logs = _tail(log_path, int(number * 4))
elif number:
logs = _tail(log_path, int(number))
else:
logs = read_file(log_path)
logs = _filter_lines(logs, filters)
logs = list(_filter(logs))
if number:
logs = logs[-number:]
infos["log_path"] = log_path

View file

@ -552,7 +552,7 @@ def test_question_password_input_test_ask():
prompt.assert_called_with(
message=ask_text,
is_password=True,
confirm=True,
confirm=False,
prefill="",
is_multiline=False,
)

View file

@ -203,7 +203,6 @@ class ConfigPanel:
"panels": {
"properties": ["name", "services", "actions", "help"],
"default": {
"name": "",
"services": [],
"actions": {"apply": {"en": "Apply"}},
},
@ -277,7 +276,9 @@ class ConfigPanel:
continue
subnode = convert(value, subnode_type)
subnode["id"] = key
if node_type == "sections":
if node_type == "toml":
subnode.setdefault("name", {"en": key.capitalize()})
elif node_type == "sections":
subnode["name"] = key # legacy
subnode.setdefault("optional", toml_node.get("optional", True))
node.setdefault(subnode_type, []).append(subnode)
@ -364,7 +365,8 @@ class ConfigPanel:
display_header(f"\n{'='*40}\n>>>> {name}\n{'='*40}")
continue
name = _value_for_locale(section["name"])
display_header(f"\n# {name}")
if name:
display_header(f"\n# {name}")
# Check and ask unanswered questions
self.new_values.update(
@ -473,6 +475,20 @@ class Question(object):
def normalize(value, option={}):
return value
def _prompt(self, text):
prefill = ""
if self.current_value is not None:
prefill = self.humanize(self.current_value, self)
elif self.default is not None:
prefill = self.humanize(self.default, self)
self.value = Moulinette.prompt(
message=text,
is_password=self.hide_user_input_in_prompt,
confirm=False, # We doesn't want to confirm this kind of password like in webadmin
prefill=prefill,
is_multiline=(self.type == "text"),
)
def ask_if_needed(self):
for i in range(5):
# Display question if no value filled or if it's a readonly message
@ -480,20 +496,8 @@ class Question(object):
text_for_user_input_in_cli = self._format_text_for_user_input_in_cli()
if getattr(self, "readonly", False):
Moulinette.display(text_for_user_input_in_cli)
elif self.value is None:
prefill = ""
if self.current_value is not None:
prefill = self.humanize(self.current_value, self)
elif self.default is not None:
prefill = self.humanize(self.default, self)
self.value = Moulinette.prompt(
message=text_for_user_input_in_cli,
is_password=self.hide_user_input_in_prompt,
confirm=self.hide_user_input_in_prompt,
prefill=prefill,
is_multiline=(self.type == "text"),
)
self._prompt(text_for_user_input_in_cli)
# Apply default value
class_default = getattr(self, "default_value", None)
@ -529,7 +533,7 @@ class Question(object):
raise YunohostValidationError("app_argument_required", name=self.name)
# we have an answer, do some post checks
if self.value is not None:
if self.value not in [None, ""]:
if self.choices and self.value not in self.choices:
self._raise_invalid_answer()
if self.pattern and not re.match(self.pattern["regexp"], str(self.value)):
@ -547,13 +551,13 @@ class Question(object):
choices=", ".join(self.choices),
)
def _format_text_for_user_input_in_cli(self):
def _format_text_for_user_input_in_cli(self, column=False):
text_for_user_input_in_cli = _value_for_locale(self.ask)
if self.choices:
text_for_user_input_in_cli += " [{0}]".format(" | ".join(self.choices))
if self.help:
if self.help or column:
text_for_user_input_in_cli += ":\033[m"
if self.help:
text_for_user_input_in_cli += "\n - "
@ -694,6 +698,23 @@ class PasswordQuestion(Question):
assert_password_is_strong_enough("user", self.value)
def _format_text_for_user_input_in_cli(self):
need_column = self.current_value or self.optional
text_for_user_input_in_cli = super()._format_text_for_user_input_in_cli(need_column)
if self.current_value:
text_for_user_input_in_cli += "\n - " + m18n.n("app_argument_password_help_keep")
if self.optional:
text_for_user_input_in_cli += "\n - " + m18n.n("app_argument_password_help_optional")
return text_for_user_input_in_cli
def _prompt(self, text):
super()._prompt(text)
if self.current_value and self.value == "":
self.value = self.current_value
elif self.value == " ":
self.value = ""
class PathQuestion(Question):
argument_type = "path"
@ -802,6 +823,14 @@ class UserQuestion(Question):
super().__init__(question, user_answers)
self.choices = user_list()["users"]
if not self.choices:
raise YunohostValidationError(
"app_argument_invalid",
name=self.name,
error="You should create a YunoHost user first."
)
if self.default is None:
root_mail = "root@%s" % _get_maindomain()
for user in self.choices.keys():