From fd2321654441e95dd3fb2d22c7c3a60e76422a08 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Mon, 27 Nov 2017 22:17:09 +0100 Subject: [PATCH 01/21] [mod] Use proper functions to enable/start firewall during postinstall --- src/yunohost/service.py | 2 +- src/yunohost/tools.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/yunohost/service.py b/src/yunohost/service.py index 5401a1fab..0861d05cd 100644 --- a/src/yunohost/service.py +++ b/src/yunohost/service.py @@ -506,7 +506,7 @@ def _run_service_command(action, service): else: raise ValueError("Unknown action '%s'" % action) - need_lock = (services[service].get('need_lock') or False) \ + need_lock = services[service].get('need_lock', False) \ and action in ['start', 'stop', 'restart', 'reload'] try: diff --git a/src/yunohost/tools.py b/src/yunohost/tools.py index 042671125..51db12cfb 100644 --- a/src/yunohost/tools.py +++ b/src/yunohost/tools.py @@ -47,7 +47,7 @@ from yunohost.app import app_fetchlist, app_info, app_upgrade, app_ssowatconf, a from yunohost.domain import domain_add, domain_list, get_public_ip, _get_maindomain, _set_maindomain from yunohost.dyndns import _dyndns_available, _dyndns_provides from yunohost.firewall import firewall_upnp -from yunohost.service import service_status, service_regen_conf, service_log +from yunohost.service import service_status, service_regen_conf, service_log, service_start, service_enable from yunohost.monitor import monitor_disk, monitor_system from yunohost.utils.packages import ynh_packages_version @@ -398,8 +398,8 @@ def tools_postinstall(domain, password, ignore_dyndns=False): os.system('touch /etc/yunohost/installed') # Enable and start YunoHost firewall at boot time - os.system('update-rc.d yunohost-firewall enable') - os.system('service yunohost-firewall start &') + service_enable("yunohost-firewall") + service_start("yunohost-firewall") service_regen_conf(force=True) logger.success(m18n.n('yunohost_configured')) From 164377d5999aafc6523192539d4336c085a64477 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Mon, 27 Nov 2017 23:12:13 +0100 Subject: [PATCH 02/21] [mod] Use systemctl for all service operations --- src/yunohost/service.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/yunohost/service.py b/src/yunohost/service.py index 0861d05cd..f0948c961 100644 --- a/src/yunohost/service.py +++ b/src/yunohost/service.py @@ -498,11 +498,8 @@ def _run_service_command(action, service): raise MoulinetteError(errno.EINVAL, m18n.n('service_unknown', service=service)) cmd = None - if action in ['start', 'stop', 'restart', 'reload']: - cmd = 'service %s %s' % (service, action) - elif action in ['enable', 'disable']: - arg = 'defaults' if action == 'enable' else 'remove' - cmd = 'update-rc.d %s %s' % (service, arg) + if action in ['start', 'stop', 'restart', 'reload', 'enable', 'disable']: + cmd = 'systemctl %s %s' % (action, service) else: raise ValueError("Unknown action '%s'" % action) From 3a3ec7d9b5329967f64a0fda4dc1c8f2b289d85b Mon Sep 17 00:00:00 2001 From: Maniack Crudelis Date: Sun, 17 Dec 2017 20:26:52 +0100 Subject: [PATCH 03/21] [fix/enh] Use local variables --- data/helpers.d/backend | 10 +++++----- data/helpers.d/filesystem | 10 +++++----- data/helpers.d/ip | 10 +++++----- data/helpers.d/mysql | 6 +++--- data/helpers.d/network | 4 ++-- data/helpers.d/package | 18 +++++++++--------- data/helpers.d/print | 4 ++-- data/helpers.d/string | 12 ++++++------ data/helpers.d/system | 2 +- data/helpers.d/user | 4 ++-- data/helpers.d/utils | 29 +++++++++++++++-------------- 11 files changed, 55 insertions(+), 54 deletions(-) diff --git a/data/helpers.d/backend b/data/helpers.d/backend index c32ef02ac..8fef412cf 100644 --- a/data/helpers.d/backend +++ b/data/helpers.d/backend @@ -22,12 +22,12 @@ ynh_use_logrotate () { fi if [ $# -gt 0 ]; then if [ "$(echo ${1##*.})" == "log" ]; then # Keep only the extension to check if it's a logfile - logfile=$1 # In this case, focus logrotate on the logfile + local logfile=$1 # In this case, focus logrotate on the logfile else - logfile=$1/*.log # Else, uses the directory and all logfile into it. + local logfile=$1/*.log # Else, uses the directory and all logfile into it. fi else - logfile="/var/log/${app}/*.log" # Without argument, use a defaut directory in /var/log + local logfile="/var/log/${app}/*.log" # Without argument, use a defaut directory in /var/log fi cat > ./${app}-logrotate << EOF # Build a config file for logrotate $logfile { @@ -97,7 +97,7 @@ ynh_add_systemd_config () { # # usage: ynh_remove_systemd_config ynh_remove_systemd_config () { - finalsystemdconf="/etc/systemd/system/$app.service" + local finalsystemdconf="/etc/systemd/system/$app.service" if [ -e "$finalsystemdconf" ]; then sudo systemctl stop $app sudo systemctl disable $app @@ -124,7 +124,7 @@ ynh_add_nginx_config () { # Substitute in a nginx config file only if the variable is not empty if test -n "${path_url:-}"; then # path_url_slash_less is path_url, or a blank value if path_url is only '/' - path_url_slash_less=${path_url%/} + local path_url_slash_less=${path_url%/} ynh_replace_string "__PATH__/" "$path_url_slash_less/" "$finalnginxconf" ynh_replace_string "__PATH__" "$path_url" "$finalnginxconf" fi diff --git a/data/helpers.d/filesystem b/data/helpers.d/filesystem index 6fb073e06..6361d278e 100644 --- a/data/helpers.d/filesystem +++ b/data/helpers.d/filesystem @@ -180,12 +180,12 @@ ynh_restore_file () { local ARCHIVE_PATH="$YNH_CWD${ORIGIN_PATH}" # Default value for DEST_PATH = /$ORIGIN_PATH local DEST_PATH="${2:-$ORIGIN_PATH}" - + # If ARCHIVE_PATH doesn't exist, search for a corresponding path in CSV if [ ! -d "$ARCHIVE_PATH" ] && [ ! -f "$ARCHIVE_PATH" ] && [ ! -L "$ARCHIVE_PATH" ]; then ARCHIVE_PATH="$YNH_BACKUP_DIR/$(_get_archive_path \"$ORIGIN_PATH\")" fi - + # Restore ORIGIN_PATH into DEST_PATH mkdir -p $(dirname "$DEST_PATH") @@ -258,7 +258,7 @@ ynh_backup_if_checksum_is_different () { then # Proceed only if a value was stored into the app settings if ! echo "$checksum_value $file" | sudo md5sum -c --status then # If the checksum is now different - backup_file="/home/yunohost.conf/backup/$file.backup.$(date '+%Y%m%d.%H%M%S')" + local backup_file="/home/yunohost.conf/backup/$file.backup.$(date '+%Y%m%d.%H%M%S')" sudo mkdir -p "$(dirname "$backup_file")" sudo cp -a "$file" "$backup_file" # Backup the current file echo "File $file has been manually modified since the installation or last upgrade. So it has been duplicated in $backup_file" >&2 @@ -272,8 +272,8 @@ ynh_backup_if_checksum_is_different () { # usage: ynh_secure_remove path_to_remove # | arg: path_to_remove - File or directory to remove ynh_secure_remove () { - path_to_remove=$1 - forbidden_path=" \ + local path_to_remove=$1 + local forbidden_path=" \ /var/www \ /home/yunohost.app" diff --git a/data/helpers.d/ip b/data/helpers.d/ip index cb507b35a..874675c9d 100644 --- a/data/helpers.d/ip +++ b/data/helpers.d/ip @@ -8,12 +8,12 @@ ynh_validate_ip() { # http://stackoverflow.com/questions/319279/how-to-validate-ip-address-in-python#319298 - - IP_ADDRESS_FAMILY=$1 - IP_ADDRESS=$2 - + + local IP_ADDRESS_FAMILY=$1 + local IP_ADDRESS=$2 + [ "$IP_ADDRESS_FAMILY" == "4" ] || [ "$IP_ADDRESS_FAMILY" == "6" ] || return 1 - + python /dev/stdin << EOF import socket import sys diff --git a/data/helpers.d/mysql b/data/helpers.d/mysql index 42c204f95..56741ec0e 100644 --- a/data/helpers.d/mysql +++ b/data/helpers.d/mysql @@ -40,9 +40,9 @@ ynh_mysql_execute_file_as_root() { # | arg: user - the user to grant privilegies # | arg: pwd - the password to identify user by ynh_mysql_create_db() { - db=$1 + local db=$1 - sql="CREATE DATABASE ${db};" + local sql="CREATE DATABASE ${db};" # grant all privilegies to user if [[ $# -gt 1 ]]; then @@ -159,6 +159,6 @@ ynh_mysql_remove_db () { # | arg: name - name to correct/sanitize # | ret: the corrected name ynh_sanitize_dbid () { - dbid=${1//[-.]/_} # We should avoid having - and . in the name of databases. They are replaced by _ + local dbid=${1//[-.]/_} # We should avoid having - and . in the name of databases. They are replaced by _ echo $dbid } diff --git a/data/helpers.d/network b/data/helpers.d/network index c6764c1f5..f9e37e6cc 100644 --- a/data/helpers.d/network +++ b/data/helpers.d/network @@ -11,7 +11,7 @@ # usage: ynh_normalize_url_path path_to_normalize # | arg: url_path_to_normalize - URL path to normalize before using it ynh_normalize_url_path () { - path_url=$1 + local path_url=$1 test -n "$path_url" || ynh_die "ynh_normalize_url_path expect a URL path as first argument and received nothing." if [ "${path_url:0:1}" != "/" ]; then # If the first character is not a / path_url="/$path_url" # Add / at begin of path variable @@ -29,7 +29,7 @@ ynh_normalize_url_path () { # usage: ynh_find_port begin_port # | arg: begin_port - port to start to search ynh_find_port () { - port=$1 + local port=$1 test -n "$port" || ynh_die "The argument of ynh_find_port must be a valid port." while netcat -z 127.0.0.1 $port # Check if the port is free do diff --git a/data/helpers.d/package b/data/helpers.d/package index f28691579..ccb0c44d0 100644 --- a/data/helpers.d/package +++ b/data/helpers.d/package @@ -80,15 +80,15 @@ ynh_package_autopurge() { # usage: ynh_package_install_from_equivs controlfile # | arg: controlfile - path of the equivs control file ynh_package_install_from_equivs () { - controlfile=$1 + local controlfile=$1 # Check if the equivs package is installed. Or install it. ynh_package_is_installed 'equivs' \ || ynh_package_install equivs # retrieve package information - pkgname=$(grep '^Package: ' $controlfile | cut -d' ' -f 2) # Retrieve the name of the debian package - pkgversion=$(grep '^Version: ' $controlfile | cut -d' ' -f 2) # And its version number + local pkgname=$(grep '^Package: ' $controlfile | cut -d' ' -f 2) # Retrieve the name of the debian package + local pkgversion=$(grep '^Version: ' $controlfile | cut -d' ' -f 2) # And its version number [[ -z "$pkgname" || -z "$pkgversion" ]] \ && echo "Invalid control file" && exit 1 # Check if this 2 variables aren't empty. @@ -96,7 +96,7 @@ ynh_package_install_from_equivs () { ynh_package_update # Build and install the package - TMPDIR=$(mktemp -d) + local TMPDIR=$(mktemp -d) # Note that the cd executes into a sub shell # Create a fake deb package with equivs-build and the given control file # Install the fake package without its dependencies with dpkg @@ -118,13 +118,13 @@ ynh_package_install_from_equivs () { # usage: ynh_install_app_dependencies dep [dep [...]] # | arg: dep - the package name to install in dependence ynh_install_app_dependencies () { - dependencies=$@ - manifest_path="../manifest.json" + local dependencies=$@ + local manifest_path="../manifest.json" if [ ! -e "$manifest_path" ]; then manifest_path="../settings/manifest.json" # Into the restore script, the manifest is not at the same place fi - version=$(grep '\"version\": ' "$manifest_path" | cut -d '"' -f 4) # Retrieve the version number in the manifest file. - dep_app=${app//_/-} # Replace all '_' by '-' + local version=$(grep '\"version\": ' "$manifest_path" | cut -d '"' -f 4) # Retrieve the version number in the manifest file. + local dep_app=${app//_/-} # Replace all '_' by '-' cat > /tmp/${dep_app}-ynh-deps.control << EOF # Make a control file for equivs-build Section: misc @@ -148,6 +148,6 @@ EOF # # usage: ynh_remove_app_dependencies ynh_remove_app_dependencies () { - dep_app=${app//_/-} # Replace all '_' by '-' + local dep_app=${app//_/-} # Replace all '_' by '-' ynh_package_autopurge ${dep_app}-ynh-deps # Remove the fake package and its dependencies if they not still used. } diff --git a/data/helpers.d/print b/data/helpers.d/print index 36f4a120e..d9c8f1ec4 100644 --- a/data/helpers.d/print +++ b/data/helpers.d/print @@ -10,10 +10,10 @@ ynh_die() { # Simply duplicate the log, execute the yunohost command and replace the log without the result of this command # It's a very badly hack... ynh_no_log() { - ynh_cli_log=/var/log/yunohost/yunohost-cli.log + local ynh_cli_log=/var/log/yunohost/yunohost-cli.log sudo cp -a ${ynh_cli_log} ${ynh_cli_log}-move eval $@ - exit_code=$? + local exit_code=$? sudo mv ${ynh_cli_log}-move ${ynh_cli_log} return $? } diff --git a/data/helpers.d/string b/data/helpers.d/string index fbf598738..80fae8cf7 100644 --- a/data/helpers.d/string +++ b/data/helpers.d/string @@ -26,13 +26,13 @@ ynh_replace_string () { local replace_string=$2 local workfile=$3 - # Escape any backslash to preserve them as simple backslash. - match_string=${match_string//\\/"\\\\"} - replace_string=${replace_string//\\/"\\\\"} + # Escape any backslash to preserve them as simple backslash. + match_string=${match_string//\\/"\\\\"} + replace_string=${replace_string//\\/"\\\\"} - # Escape the & character, who has a special function in sed. - match_string=${match_string//&/"\&"} - replace_string=${replace_string//&/"\&"} + # Escape the & character, who has a special function in sed. + match_string=${match_string//&/"\&"} + replace_string=${replace_string//&/"\&"} # Escape the delimiter if it's in the string. match_string=${match_string//${delimit}/"\\${delimit}"} diff --git a/data/helpers.d/system b/data/helpers.d/system index 5f2ad385b..4bb941b7d 100644 --- a/data/helpers.d/system +++ b/data/helpers.d/system @@ -14,7 +14,7 @@ # Usage: ynh_exit_properly is used only by the helper ynh_abort_if_errors. # You must not use it directly. ynh_exit_properly () { - exit_code=$? + local exit_code=$? if [ "$exit_code" -eq 0 ]; then exit 0 # Exit without error if the script ended correctly fi diff --git a/data/helpers.d/user b/data/helpers.d/user index 0bb0736af..8e214691c 100644 --- a/data/helpers.d/user +++ b/data/helpers.d/user @@ -48,9 +48,9 @@ ynh_system_user_create () { if ! ynh_system_user_exists "$1" # Check if the user exists on the system then # If the user doesn't exist if [ $# -ge 2 ]; then # If a home dir is mentioned - user_home_dir="-d $2" + local user_home_dir="-d $2" else - user_home_dir="--no-create-home" + local user_home_dir="--no-create-home" fi sudo useradd $user_home_dir --system --user-group $1 --shell /usr/sbin/nologin || ynh_die "Unable to create $1 system account" fi diff --git a/data/helpers.d/utils b/data/helpers.d/utils index 2cb18c5c0..030fddcde 100644 --- a/data/helpers.d/utils +++ b/data/helpers.d/utils @@ -5,9 +5,9 @@ # usage: ynh_get_plain_key key [subkey [subsubkey ...]] # | ret: string - the key's value ynh_get_plain_key() { - prefix="#" - founded=0 - key=$1 + local prefix="#" + local founded=0 + local key=$1 shift while read line; do if [[ "$founded" == "1" ]] ; then @@ -36,7 +36,7 @@ ynh_get_plain_key() { # ynh_restore_upgradebackup () { echo "Upgrade failed." >&2 - app_bck=${app//_/-} # Replace all '_' by '-' + local app_bck=${app//_/-} # Replace all '_' by '-' # Check if an existing backup can be found before removing and restoring the application. if sudo yunohost backup list | grep -q $app_bck-pre-upgrade$backup_number @@ -64,9 +64,9 @@ ynh_backup_before_upgrade () { echo "This app doesn't have any backup script." >&2 return fi - backup_number=1 - old_backup_number=2 - app_bck=${app//_/-} # Replace all '_' by '-' + local backup_number=1 + local old_backup_number=2 + local app_bck=${app//_/-} # Replace all '_' by '-' # Check if a backup already exists with the prefix 1 if sudo yunohost backup list | grep -q $app_bck-pre-upgrade1 @@ -94,7 +94,7 @@ ynh_backup_before_upgrade () { # Download, check integrity, uncompress and patch the source from app.src # # The file conf/app.src need to contains: -# +# # SOURCE_URL=Address to download the app archive # SOURCE_SUM=Control sum # # (Optional) Program to check the integrity (sha256sum, md5sum...) @@ -113,9 +113,9 @@ ynh_backup_before_upgrade () { # Details: # This helper downloads sources from SOURCE_URL if there is no local source # archive in /opt/yunohost-apps-src/APP_ID/SOURCE_FILENAME -# +# # Next, it checks the integrity with "SOURCE_SUM_PRG -c --status" command. -# +# # If it's ok, the source archive will be uncompressed in $dest_dir. If the # SOURCE_IN_SUBDIR is true, the first level directory of the archive will be # removed. @@ -130,7 +130,7 @@ ynh_backup_before_upgrade () { ynh_setup_source () { local dest_dir=$1 local src_id=${2:-app} # If the argument is not given, source_id equals "app" - + # Load value from configuration file (see above for a small doc about this file # format) local src_url=$(grep 'SOURCE_URL=' "$YNH_CWD/../conf/${src_id}.src" | cut -d= -f2-) @@ -139,7 +139,7 @@ ynh_setup_source () { local src_format=$(grep 'SOURCE_FORMAT=' "$YNH_CWD/../conf/${src_id}.src" | cut -d= -f2-) local src_in_subdir=$(grep 'SOURCE_IN_SUBDIR=' "$YNH_CWD/../conf/${src_id}.src" | cut -d= -f2-) local src_filename=$(grep 'SOURCE_FILENAME=' "$YNH_CWD/../conf/${src_id}.src" | cut -d= -f2-) - + # Default value src_sumprg=${src_sumprg:-sha256sum} src_in_subdir=${src_in_subdir:-true} @@ -216,10 +216,11 @@ ynh_setup_source () { # | arg: ... - (Optionnal) More POST keys and values ynh_local_curl () { # Define url of page to curl - full_page_url=https://localhost$path_url$1 + local full_page_url=https://localhost$path_url$1 # Concatenate all other arguments with '&' to prepare POST data - POST_data="" + local POST_data="" + local arg="" for arg in "${@:2}" do POST_data="${POST_data}${arg}&" From 542528ab05716c5335cdc6079e9bb0029292e24d Mon Sep 17 00:00:00 2001 From: Maniack Crudelis Date: Thu, 21 Dec 2017 19:19:33 +0100 Subject: [PATCH 04/21] Fix broken ynh_replace_string (#394) * Fix broken ynh_replace_string * Replace name for ynh_replace_special_string --- data/helpers.d/string | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/data/helpers.d/string b/data/helpers.d/string index fbf598738..13399ffe0 100644 --- a/data/helpers.d/string +++ b/data/helpers.d/string @@ -26,6 +26,27 @@ ynh_replace_string () { local replace_string=$2 local workfile=$3 + # Escape the delimiter if it's in the string. + match_string=${match_string//${delimit}/"\\${delimit}"} + replace_string=${replace_string//${delimit}/"\\${delimit}"} + + sudo sed --in-place "s${delimit}${match_string}${delimit}${replace_string}${delimit}g" "$workfile" +} + +# Substitute/replace a special string by another in a file +# +# usage: ynh_replace_special_string match_string replace_string target_file +# | arg: match_string - String to be searched and replaced in the file +# | arg: replace_string - String that will replace matches +# | arg: target_file - File in which the string will be replaced. +# +# This helper will use ynh_replace_string, but as you can use special +# characters, you can't use some regular expressions and sub-expressions. +ynh_replace_special_string () { + local match_string=$1 + local replace_string=$2 + local workfile=$3 + # Escape any backslash to preserve them as simple backslash. match_string=${match_string//\\/"\\\\"} replace_string=${replace_string//\\/"\\\\"} @@ -34,9 +55,5 @@ ynh_replace_string () { match_string=${match_string//&/"\&"} replace_string=${replace_string//&/"\&"} - # Escape the delimiter if it's in the string. - match_string=${match_string//${delimit}/"\\${delimit}"} - replace_string=${replace_string//${delimit}/"\\${delimit}"} - - sudo sed --in-place "s${delimit}${match_string}${delimit}${replace_string}${delimit}g" "$workfile" + ynh_replace_string "$match_string" "$replace_string" "$workfile" } From a079e3f5eef856845e3485312e989bf13eabac38 Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Thu, 4 Jan 2018 18:02:58 +0100 Subject: [PATCH 05/21] [enh] display which app is being upgraded --- locales/en.json | 1 + src/yunohost/app.py | 1 + 2 files changed, 2 insertions(+) diff --git a/locales/en.json b/locales/en.json index 8dac6e799..e3bc763bb 100644 --- a/locales/en.json +++ b/locales/en.json @@ -34,6 +34,7 @@ "app_sources_fetch_failed": "Unable to fetch sources files", "app_unknown": "Unknown app", "app_unsupported_remote_type": "Unsupported remote type used for the app", + "app_upgrade_app_name": "Upgrading app {app}...", "app_upgrade_failed": "Unable to upgrade {app:s}", "app_upgrade_some_app_failed": "Unable to upgrade some applications", "app_upgraded": "{app:s} has been upgraded", diff --git a/src/yunohost/app.py b/src/yunohost/app.py index 403e76cc4..e9278855e 100644 --- a/src/yunohost/app.py +++ b/src/yunohost/app.py @@ -555,6 +555,7 @@ def app_upgrade(auth, app=[], url=None, file=None): logger.info("Upgrading apps %s", ", ".join(app)) for app_instance_name in apps: + logger.warning(m18n.n('app_upgrade_app_name', app=app_instance_name)) installed = _is_installed(app_instance_name) if not installed: raise MoulinetteError(errno.ENOPKG, From b97675516ee1f9dcc54327a82e87f083f1cc94e5 Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Thu, 4 Jan 2018 18:15:10 +0100 Subject: [PATCH 06/21] [enh] display app name everytime possible on requirements testing to improve UX --- locales/en.json | 10 +++++----- src/yunohost/app.py | 16 ++++++++-------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/locales/en.json b/locales/en.json index e3bc763bb..11598a473 100644 --- a/locales/en.json +++ b/locales/en.json @@ -16,7 +16,7 @@ "app_change_url_success": "Successfully changed {app:s} url to {domain:s}{path:s}", "app_extraction_failed": "Unable to extract installation files", "app_id_invalid": "Invalid app id", - "app_incompatible": "The app is incompatible with your YunoHost version", + "app_incompatible": "The app {app} is incompatible with your YunoHost version", "app_install_files_invalid": "Invalid installation files", "app_location_already_used": "An app is already installed in this location", "app_location_install_failed": "Unable to install the app in this location", @@ -26,11 +26,11 @@ "app_not_correctly_installed": "{app:s} seems to be incorrectly installed", "app_not_installed": "{app:s} is not installed", "app_not_properly_removed": "{app:s} has not been properly removed", - "app_package_need_update": "The app package needs to be updated to follow YunoHost changes", + "app_package_need_update": "The app {app} package needs to be updated to follow YunoHost changes", "app_removed": "{app:s} has been removed", - "app_requirements_checking": "Checking required packages...", - "app_requirements_failed": "Unable to meet requirements: {error}", - "app_requirements_unmeet": "Requirements are not met, the package {pkgname} ({version}) must be {spec}", + "app_requirements_checking": "Checking required packages for {app}...", + "app_requirements_failed": "Unable to meet requirements for {app}: {error}", + "app_requirements_unmeet": "Requirements are not met for {app}, the package {pkgname} ({version}) must be {spec}", "app_sources_fetch_failed": "Unable to fetch sources files", "app_unknown": "Unknown app", "app_unsupported_remote_type": "Unsupported remote type used for the app", diff --git a/src/yunohost/app.py b/src/yunohost/app.py index e9278855e..3802874b6 100644 --- a/src/yunohost/app.py +++ b/src/yunohost/app.py @@ -581,7 +581,7 @@ def app_upgrade(auth, app=[], url=None, file=None): continue # Check requirements - _check_manifest_requirements(manifest) + _check_manifest_requirements(manifest, app_instance_name=app_instance_name) app_setting_path = APPS_SETTING_PATH + '/' + app_instance_name @@ -684,7 +684,7 @@ def app_install(auth, app, label=None, args=None, no_remove_on_failure=False): app_id = manifest['id'] # Check requirements - _check_manifest_requirements(manifest) + _check_manifest_requirements(manifest, app_id) # Check if app can be forked instance_number = _installed_instance_number(app_id, last=True) + 1 @@ -1690,7 +1690,7 @@ def _encode_string(value): return value -def _check_manifest_requirements(manifest): +def _check_manifest_requirements(manifest, app_instance_name): """Check if required packages are met from the manifest""" requirements = manifest.get('requirements', dict()) @@ -1708,12 +1708,12 @@ def _check_manifest_requirements(manifest): if (not yunohost_req or not packages.SpecifierSet(yunohost_req) & '>= 2.3.6'): raise MoulinetteError(errno.EINVAL, '{0}{1}'.format( - m18n.g('colon', m18n.n('app_incompatible')), - m18n.n('app_package_need_update'))) + m18n.g('colon', m18n.n('app_incompatible'), app=app_instance_name), + m18n.n('app_package_need_update', app=app_instance_name))) elif not requirements: return - logger.info(m18n.n('app_requirements_checking')) + logger.info(m18n.n('app_requirements_checking', app=app_instance_name)) # Retrieve versions of each required package try: @@ -1722,7 +1722,7 @@ def _check_manifest_requirements(manifest): except packages.PackageException as e: raise MoulinetteError(errno.EINVAL, m18n.n('app_requirements_failed', - error=str(e))) + error=str(e), app=app_instance_name)) # Iterate over requirements for pkgname, spec in requirements.items(): @@ -1731,7 +1731,7 @@ def _check_manifest_requirements(manifest): raise MoulinetteError( errno.EINVAL, m18n.n('app_requirements_unmeet', pkgname=pkgname, version=version, - spec=spec)) + spec=spec, app=app_instance_name)) def _parse_args_from_manifest(manifest, action, args={}, auth=None): From a194e1fa1cc655e9076dc99b6caee6d6d9c4b68d Mon Sep 17 00:00:00 2001 From: "ljf (zamentur)" Date: Thu, 4 Jan 2018 18:44:13 +0100 Subject: [PATCH 07/21] [enh] Maintain ssh client connexion --- data/templates/ssh/sshd_config | 3 +++ 1 file changed, 3 insertions(+) diff --git a/data/templates/ssh/sshd_config b/data/templates/ssh/sshd_config index 695ea0d36..8c5a7fb95 100644 --- a/data/templates/ssh/sshd_config +++ b/data/templates/ssh/sshd_config @@ -66,6 +66,9 @@ PrintLastLog yes TCPKeepAlive yes #UseLogin no +# keep ssh sessions fresh +ClientAliveInterval 60 + #MaxStartups 10:30:60 Banner /etc/issue.net From 13aca112fa74b79f9c8097521f3f19abe24a72e2 Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Thu, 4 Jan 2018 20:31:58 +0100 Subject: [PATCH 08/21] [enh] make change_url possibility available on the API for the admin --- src/yunohost/app.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/yunohost/app.py b/src/yunohost/app.py index 403e76cc4..7ceb795d7 100644 --- a/src/yunohost/app.py +++ b/src/yunohost/app.py @@ -330,6 +330,9 @@ def app_info(app, show_status=False, raw=False): if not _is_installed(app): raise MoulinetteError(errno.EINVAL, m18n.n('app_not_installed', app=app)) + + app_setting_path = APPS_SETTING_PATH + app + if raw: ret = app_list(filter=app, raw=True)[app] ret['settings'] = _get_app_settings(app) @@ -345,11 +348,10 @@ def app_info(app, show_status=False, raw=False): upgradable = "no" ret['upgradable'] = upgradable + ret['change_url'] = os.path.exists(os.path.join(app_setting_path, "scripts", "change_url")) return ret - app_setting_path = APPS_SETTING_PATH + app - # Retrieve manifest and status with open(app_setting_path + '/manifest.json') as f: manifest = json.loads(str(f.read())) From aea13bc3e8816375b37ec33624d2fdcc6c5d1807 Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Sat, 6 Jan 2018 18:36:29 +0100 Subject: [PATCH 09/21] [enh] save the conf/ directory of app during installation and upgrade --- src/yunohost/app.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/yunohost/app.py b/src/yunohost/app.py index 403e76cc4..87178464c 100644 --- a/src/yunohost/app.py +++ b/src/yunohost/app.py @@ -621,10 +621,13 @@ def app_upgrade(auth, app=[], url=None, file=None): with open(app_setting_path + '/status.json', 'w+') as f: json.dump(status, f) - # Replace scripts and manifest - os.system('rm -rf "%s/scripts" "%s/manifest.json"' % (app_setting_path, app_setting_path)) + # Replace scripts and manifest and conf (if exists) + os.system('rm -rf "%s/scripts" "%s/manifest.json %/conf"' % (app_setting_path, app_setting_path, app_setting_path)) os.system('mv "%s/manifest.json" "%s/scripts" %s' % (extracted_app_folder, extracted_app_folder, app_setting_path)) + if os.path.exists(os.path.join(extracted_app_folder, "conf")): + os.system('cp -R %s/conf %s' % (extracted_app_folder, app_setting_path)) + # So much win upgraded_apps.append(app_instance_name) logger.success(m18n.n('app_upgraded', app=app_instance_name)) @@ -733,6 +736,9 @@ def app_install(auth, app, label=None, args=None, no_remove_on_failure=False): os.system('cp %s/manifest.json %s' % (extracted_app_folder, app_setting_path)) os.system('cp -R %s/scripts %s' % (extracted_app_folder, app_setting_path)) + if os.path.exists(os.path.join(extracted_app_folder, "conf")): + os.system('cp -R %s/conf %s' % (extracted_app_folder, app_setting_path)) + # Execute the app install script install_retcode = 1 try: From 7d9307c4c60edd2e7001100c86db95882b22ccca Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Sat, 6 Jan 2018 18:44:31 +0100 Subject: [PATCH 10/21] [doc$ add PULL_REQUEST_TEMPLATE.md --- src/yunohost/.github/PULL_REQUEST_TEMPLATE.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/yunohost/.github/PULL_REQUEST_TEMPLATE.md diff --git a/src/yunohost/.github/PULL_REQUEST_TEMPLATE.md b/src/yunohost/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..065c2dd90 --- /dev/null +++ b/src/yunohost/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,19 @@ +## The problem + +... + +## Solution + +... + +## PR Status + +... + + +## Validation + +- [ ] Principle agreement 0/2 : +- [ ] Quick review 0/1 : +- [ ] Simple test 0/1 : +- [ ] Deep review 0/1 : From f20ef340dc9aa648b5d9d94629076717a7a7b36e Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Sun, 7 Jan 2018 02:04:18 +0100 Subject: [PATCH 11/21] [fix] .github was not in the right folder --- {src/yunohost/.github => .github}/PULL_REQUEST_TEMPLATE.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {src/yunohost/.github => .github}/PULL_REQUEST_TEMPLATE.md (100%) diff --git a/src/yunohost/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md similarity index 100% rename from src/yunohost/.github/PULL_REQUEST_TEMPLATE.md rename to .github/PULL_REQUEST_TEMPLATE.md From 297026e6548ef1763f6c5d51bef1c940f02e532d Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Sun, 7 Jan 2018 16:43:10 +0100 Subject: [PATCH 12/21] [fix] improve UX, previous message was unclear for users qsd --- locales/en.json | 2 +- src/yunohost/app.py | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/locales/en.json b/locales/en.json index 8dac6e799..6e6ed6daa 100644 --- a/locales/en.json +++ b/locales/en.json @@ -19,7 +19,7 @@ "app_incompatible": "The app is incompatible with your YunoHost version", "app_install_files_invalid": "Invalid installation files", "app_location_already_used": "An app is already installed in this location", - "app_location_install_failed": "Unable to install the app in this location", + "app_location_install_failed": "Unable to install the app in this location because it conflit with the app '{other_app}' already installed on '{other_path}'", "app_location_unavailable": "This url is not available or conflicts with an already installed app", "app_manifest_invalid": "Invalid app manifest: {error}", "app_no_upgrade": "No app to upgrade", diff --git a/src/yunohost/app.py b/src/yunohost/app.py index 403e76cc4..5599c0d53 100644 --- a/src/yunohost/app.py +++ b/src/yunohost/app.py @@ -1169,10 +1169,12 @@ def app_checkurl(auth, url, app=None): continue if path == p: raise MoulinetteError(errno.EINVAL, - m18n.n('app_location_already_used')) + m18n.n('app_location_already_used', + app=a["id"], path=path)) elif path.startswith(p) or p.startswith(path): raise MoulinetteError(errno.EPERM, - m18n.n('app_location_install_failed')) + m18n.n('app_location_install_failed', + other_path=p, other_app=a['id'])) if app is not None and not installed: app_setting(app, 'domain', value=domain) From 9cd760defd74e815408ece4a7960631692681a0d Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Sun, 7 Jan 2018 17:04:48 +0100 Subject: [PATCH 13/21] [enh] make exceptions messages more obivous --- locales/en.json | 3 ++- src/yunohost/app.py | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/locales/en.json b/locales/en.json index 6e6ed6daa..1edf2609c 100644 --- a/locales/en.json +++ b/locales/en.json @@ -18,7 +18,8 @@ "app_id_invalid": "Invalid app id", "app_incompatible": "The app is incompatible with your YunoHost version", "app_install_files_invalid": "Invalid installation files", - "app_location_already_used": "An app is already installed in this location", + "app_location_already_used": "The app '{app}' is already installed on that location ({path})", + "app_make_default_location_already_used": "Can't make the app '{app}' the default on the domain {domain} is already used by the other app '{other_app}'", "app_location_install_failed": "Unable to install the app in this location because it conflit with the app '{other_app}' already installed on '{other_path}'", "app_location_unavailable": "This url is not available or conflicts with an already installed app", "app_manifest_invalid": "Invalid app manifest: {error}", diff --git a/src/yunohost/app.py b/src/yunohost/app.py index 5599c0d53..851fcdaa6 100644 --- a/src/yunohost/app.py +++ b/src/yunohost/app.py @@ -1016,7 +1016,9 @@ def app_makedefault(auth, app, domain=None): if '/' in app_map(raw=True)[domain]: raise MoulinetteError(errno.EEXIST, - m18n.n('app_location_already_used')) + m18n.n('app_make_default_location_already_used', + app=app, domain=app_domain, + other_app=app_map(raw=True)[domain]["/"]["id"])) try: with open('/etc/ssowat/conf.json.persistent') as json_conf: From e8196cbc9855ab460ec9cbcb6c3505e70eb46be1 Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Sun, 7 Jan 2018 17:23:02 +0100 Subject: [PATCH 14/21] [doc] add comment to speak intent --- src/yunohost/app.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/yunohost/app.py b/src/yunohost/app.py index 851fcdaa6..d9ca5977f 100644 --- a/src/yunohost/app.py +++ b/src/yunohost/app.py @@ -1173,6 +1173,7 @@ def app_checkurl(auth, url, app=None): raise MoulinetteError(errno.EINVAL, m18n.n('app_location_already_used', app=a["id"], path=path)) + # can't install "/a/b/" if "/a/" exists elif path.startswith(p) or p.startswith(path): raise MoulinetteError(errno.EPERM, m18n.n('app_location_install_failed', From 70e08ed40f32875fc1389a39c2ee0628ffecdf1e Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Mon, 8 Jan 2018 02:47:36 +0100 Subject: [PATCH 15/21] [fix] pkg is None, can't continue loop --- src/yunohost/utils/packages.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/yunohost/utils/packages.py b/src/yunohost/utils/packages.py index 9242d22d1..bc822da1f 100644 --- a/src/yunohost/utils/packages.py +++ b/src/yunohost/utils/packages.py @@ -414,6 +414,8 @@ def get_installed_version(*pkgnames, **kwargs): if strict: raise UnknownPackage(pkgname) logger.warning(m18n.n('package_unknown', pkgname=pkgname)) + continue + try: version = pkg.installed.version except AttributeError: From e0edbeca357f7aecae159a1e7c71aef006d9462d Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Mon, 8 Jan 2018 03:10:16 +0100 Subject: [PATCH 16/21] [enh] --version now display stable/testing/unstable information --- src/yunohost/utils/packages.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/yunohost/utils/packages.py b/src/yunohost/utils/packages.py index bc822da1f..18c4f2a3d 100644 --- a/src/yunohost/utils/packages.py +++ b/src/yunohost/utils/packages.py @@ -422,7 +422,21 @@ def get_installed_version(*pkgnames, **kwargs): if strict: raise UninstalledPackage(pkgname) version = None - versions[pkgname] = version + + try: + # stable, testing, unstable + repo = pkg.installed.origins[0].component + except AttributeError: + if strict: + raise UninstalledPackage(pkgname) + repo = "" + + versions[pkgname] = { + "version": version, + # when we don't have component it's because it's from a local + # install or from an image (like in vagrant) + "repo": repo if repo else "local", + } if len(pkgnames) == 1 and not as_dict: return versions[pkgnames[0]] @@ -438,6 +452,9 @@ def meets_version_specifier(pkgname, specifier): # YunoHost related methods --------------------------------------------------- def ynh_packages_version(*args, **kwargs): + # from cli the received arguments are: + # (Namespace(_callbacks=deque([]), _tid='_global', _to_return={}), []) {} + # they don't seems to serve any purpose """Return the version of each YunoHost package""" return get_installed_version( 'yunohost', 'yunohost-admin', 'moulinette', 'ssowat', From d7967f6d5fde81d4537bff8d2de1f723d1fceec4 Mon Sep 17 00:00:00 2001 From: JocelynDelalande Date: Mon, 8 Jan 2018 17:59:53 +0100 Subject: [PATCH 17/21] Fix comment lines in DNS zone example (using ";") If copy-pasted into a registrar zone file, the provided DNS zone sample for a given domain will fail, because comments lines start with "#" However, comments character in DNS zone files is ";" not "#" https://en.wikipedia.org/wiki/Zone_file --- src/yunohost/domain.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/yunohost/domain.py b/src/yunohost/domain.py index f828b0973..727a63df3 100644 --- a/src/yunohost/domain.py +++ b/src/yunohost/domain.py @@ -188,17 +188,17 @@ def domain_dns_conf(domain, ttl=None): result = "" - result += "# Basic ipv4/ipv6 records" + result += "; Basic ipv4/ipv6 records" for record in dns_conf["basic"]: result += "\n{name} {ttl} IN {type} {value}".format(**record) result += "\n\n" - result += "# XMPP" + result += "; XMPP" for record in dns_conf["xmpp"]: result += "\n{name} {ttl} IN {type} {value}".format(**record) result += "\n\n" - result += "# Mail" + result += "; Mail" for record in dns_conf["mail"]: result += "\n{name} {ttl} IN {type} {value}".format(**record) From 4f679367eb8905aee52a76dcefac4a2190a9a382 Mon Sep 17 00:00:00 2001 From: JimboJoe Date: Tue, 9 Jan 2018 20:30:43 +0100 Subject: [PATCH 18/21] Typo --- src/yunohost/utils/packages.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/yunohost/utils/packages.py b/src/yunohost/utils/packages.py index 18c4f2a3d..7df311406 100644 --- a/src/yunohost/utils/packages.py +++ b/src/yunohost/utils/packages.py @@ -454,7 +454,7 @@ def meets_version_specifier(pkgname, specifier): def ynh_packages_version(*args, **kwargs): # from cli the received arguments are: # (Namespace(_callbacks=deque([]), _tid='_global', _to_return={}), []) {} - # they don't seems to serve any purpose + # they don't seem to serve any purpose """Return the version of each YunoHost package""" return get_installed_version( 'yunohost', 'yunohost-admin', 'moulinette', 'ssowat', From 20f0e9a40c67fc9b373cd4ae33a982628c816552 Mon Sep 17 00:00:00 2001 From: Jimmy Monin Date: Tue, 9 Jan 2018 23:01:19 +0100 Subject: [PATCH 19/21] Fix conf dir clean-up --- src/yunohost/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/yunohost/app.py b/src/yunohost/app.py index 87178464c..7b6195e60 100644 --- a/src/yunohost/app.py +++ b/src/yunohost/app.py @@ -622,7 +622,7 @@ def app_upgrade(auth, app=[], url=None, file=None): json.dump(status, f) # Replace scripts and manifest and conf (if exists) - os.system('rm -rf "%s/scripts" "%s/manifest.json %/conf"' % (app_setting_path, app_setting_path, app_setting_path)) + os.system('rm -rf "%s/scripts" "%s/manifest.json %s/conf"' % (app_setting_path, app_setting_path, app_setting_path)) os.system('mv "%s/manifest.json" "%s/scripts" %s' % (extracted_app_folder, extracted_app_folder, app_setting_path)) if os.path.exists(os.path.join(extracted_app_folder, "conf")): From 9c44878d9203bf174bfc7c9ae164e57d781a5b5e Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Tue, 9 Jan 2018 23:21:33 +0100 Subject: [PATCH 20/21] [mod] add section in PR template to inform on how to test a PR --- .github/PULL_REQUEST_TEMPLATE.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 065c2dd90..9642e92f6 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -10,6 +10,9 @@ ... +## How to test + +... ## Validation From 2b2676a9c1d6f487cbbda00a17a6e3e8ff4a40cc Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Sun, 7 Jan 2018 23:03:22 +0100 Subject: [PATCH 21/21] [enh] add nginx -t output to diagnosis --- src/yunohost/tools.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/yunohost/tools.py b/src/yunohost/tools.py index 042671125..8262e6682 100644 --- a/src/yunohost/tools.py +++ b/src/yunohost/tools.py @@ -42,6 +42,7 @@ import apt.progress from moulinette import msettings, msignals, m18n from moulinette.core import MoulinetteError, init_authenticator from moulinette.utils.log import getActionLogger +from moulinette.utils.process import check_output from moulinette.utils.filesystem import read_json, write_to_json from yunohost.app import app_fetchlist, app_info, app_upgrade, app_ssowatconf, app_list, _install_appslist_fetch_cron from yunohost.domain import domain_add, domain_list, get_public_ip, _get_maindomain, _set_maindomain @@ -589,6 +590,9 @@ def tools_diagnosis(auth, private=False): 'swap': '%s (%s free)' % (system['memory']['swap']['total'], system['memory']['swap']['free']), } + # nginx -t + diagnosis['nginx'] = check_output("nginx -t").strip().split("\n") + # Services status services = service_status() diagnosis['services'] = {}