From 1dadac080ef5d14d52d1c4a4a1ff0236ad1b827f Mon Sep 17 00:00:00 2001 From: Maniack Crudelis Date: Sat, 16 Dec 2017 23:22:54 +0100 Subject: [PATCH] Use new helpers --- manifest.json | 2 +- scripts/_common.sh | 370 +++++++++++++++++++++++++++++++++++++++++---- scripts/_sed | 51 +++++++ scripts/change_url | 27 +--- scripts/install | 48 +++--- scripts/remove | 2 +- scripts/restore | 33 ++-- scripts/upgrade | 32 ++-- 8 files changed, 440 insertions(+), 125 deletions(-) create mode 100644 scripts/_sed diff --git a/manifest.json b/manifest.json index 3f6e44c..a704ad6 100644 --- a/manifest.json +++ b/manifest.json @@ -6,7 +6,7 @@ "en": "Self hosting images and sharing anonymous application", "fr": "Application d'hébergement et de partage d'images anonyme" }, - "version": "0.8.6", + "version": "0.8.6~ynh1", "url": "https://lut.im", "license": "AGPL-3.0", "maintainer": { diff --git a/scripts/_common.sh b/scripts/_common.sh index cac8bd1..883fe5e 100755 --- a/scripts/_common.sh +++ b/scripts/_common.sh @@ -1,31 +1,5 @@ #!/bin/bash -#================================================= -# DISPLAYING -#================================================= - -NO_PRINT () { # Supprime l'affichage dans stdout pour la commande en argument. - set +x - $@ - set -x -} - -WARNING () { # Écrit sur le canal d'erreur pour passer en warning. - $@ >&2 -} - -SUPPRESS_WARNING () { # Force l'écriture sur la sortie standard - $@ 2>&1 -} - -QUIET () { # Redirige la sortie standard dans /dev/null - $@ > /dev/null -} - -ALL_QUIET () { # Redirige la sortie standard et d'erreur dans /dev/null - $@ > /dev/null 2>&1 -} - #================================================= # BACKUP #================================================= @@ -42,8 +16,8 @@ CHECK_SIZE () { # Vérifie avant chaque backup que l'espace est suffisant if [ $free_space -le $backup_size ] then - WARNING echo "Espace insuffisant pour sauvegarder $file_to_analyse." - WARNING echo "Espace disponible: $(HUMAN_SIZE $free_space)" + ynh_print_err "Espace insuffisant pour sauvegarder $file_to_analyse." + ynh_print_err "Espace disponible: $(HUMAN_SIZE $free_space)" ynh_die "Espace nécessaire: $(HUMAN_SIZE $backup_size)" fi } @@ -57,7 +31,7 @@ IS_PACKAGE_CHECK () { # Détermine une exécution en conteneur (Non testé) } #================================================= -# NODEJS +# EXPERIMENTAL HELPERS #================================================= # INFOS @@ -234,6 +208,344 @@ EOF chmod +x "/etc/cron.daily/node_update" } +#================================================= + +# Start or restart a service and follow its booting +# +# usage: ynh_check_starting "Line to match" [Log file] [Timeout] +# +# | arg: Line to match - The line to find in the log to attest the service have finished to boot. +# | arg: Log file - The log file to watch +# /var/log/$app/$app.log will be used if no other log is defined. +# | arg: Timeout - The maximum time to wait before ending the watching. Defaut 300 seconds. +ynh_check_starting () { + local line_to_match="$1" + local app_log="${2:-/var/log/$app/$app.log}" + local timeout=${3:-300} + + ynh_clean_check_starting () { + # Stop the execution of tail. + kill -s 15 $pid_tail 2>&1 + ynh_secure_remove "$templog" 2>&1 + } + + echo "Starting of $app" >&2 + systemctl restart $app + local templog="$(mktemp)" + # Following the starting of the app in its log + tail -f -n1 "$app_log" > "$templog" & + # Get the PID of the tail command + local pid_tail=$! + + local i=0 + for i in `seq 1 $timeout` + do + # Read the log until the sentence is found, that means the app finished to start. Or run until the timeout + if grep --quiet "$line_to_match" "$templog" + then + echo "The service $app has correctly started." >&2 + break + fi + echo -n "." >&2 + sleep 1 + done + if [ $i -eq $timeout ] + then + echo "The service $app didn't fully started before the timeout." >&2 + fi + + echo "" + ynh_clean_check_starting +} + +#================================================= + +ynh_print_log () { + echo "${1}" +} + +# Print an info on stdout +# +# usage: ynh_print_info "Text to print" +# | arg: text - The text to print +ynh_print_info () { + ynh_print_log "[INFO] ${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 "[WARN] ${1}" >&2 +} + +# Print a error on stderr +# +# usage: ynh_print_err "Text to print" +# | arg: text - The text to print +ynh_print_err () { + ynh_print_log "[ERR] ${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 send 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 send 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 send 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 send 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 send to the next pipe. +# +# | arg: command - command to execute +ynh_exec_fully_quiet () { + eval $@ > /dev/null 2>&1 +} + +#================================================= + +# Install or update the main directory yunohost.multimedia +# +# usage: ynh_multimedia_build_main_dir +ynh_multimedia_build_main_dir () { + wget -nv https://github.com/YunoHost-Apps/yunohost.multimedia/archive/master.zip 2>&1 + unzip -q master.zip + ./yunohost.multimedia-master/script/ynh_media_build.sh +} + +# Add a directory in yunohost.multimedia +# This "directory" will be a symbolic link to a existing directory. +# +# usage: ynh_multimedia_addfolder "Source directory" "Destination directory" +# +# | arg: Source directory - The real directory which contains your medias. +# | arg: Destination directory - The name and the place of the symbolic link, relative to "/home/yunohost.multimedia" +ynh_multimedia_addfolder () { + local source_dir="$1" + local dest_dir="$2" + ./yunohost.multimedia-master/script/ynh_media_addfolder.sh --source="$source_dir" --dest="$dest_dir" +} + +# Move a directory in yunohost.multimedia, and replace by a symbolic link +# +# usage: ynh_multimedia_movefolder "Source directory" "Destination directory" +# +# | arg: Source directory - The real directory which contains your medias. +# It will be moved to "Destination directory" +# A symbolic link will replace it. +# | arg: Destination directory - The new name and place of the directory, relative to "/home/yunohost.multimedia" +ynh_multimedia_movefolder () { + local source_dir="$1" + local dest_dir="$2" + ./yunohost.multimedia-master/script/ynh_media_addfolder.sh --inv --source="$source_dir" --dest="$dest_dir" +} + +# Allow an user to have an write authorisation in multimedia directories +# +# usage: ynh_multimedia_addaccess user_name +# +# | arg: user_name - The name of the user which gain this access. +ynh_multimedia_addaccess () { + local user_name=$1 + groupadd -f multimedia + usermod -a -G multimedia $user_name +} + +#================================================= + +# Create a dedicated fail2ban config (jail and filter conf files) +# +# usage: ynh_add_fail2ban_config log_file filter [max_retry [ports]] +# | arg: log_file - Log file to be checked by fail2ban +# | arg: failregex - Failregex to be looked for by fail2ban +# | arg: max_retry - Maximum number of retries allowed before banning IP address - default: 3 +# | arg: ports - Ports blocked for a banned IP address - default: http,https +ynh_add_fail2ban_config () { + # Process parameters + logpath=$1 + failregex=$2 + max_retry=${3:-3} + ports=${4:-http,https} + + test -n "$logpath" || ynh_die "ynh_add_fail2ban_config expects a logfile path as first argument and received nothing." + test -n "$failregex" || ynh_die "ynh_add_fail2ban_config expects a failure regex as second argument and received nothing." + + finalfail2banjailconf="/etc/fail2ban/jail.d/$app.conf" + finalfail2banfilterconf="/etc/fail2ban/filter.d/$app.conf" + ynh_backup_if_checksum_is_different "$finalfail2banjailconf" 1 + ynh_backup_if_checksum_is_different "$finalfail2banfilterconf" 1 + + sudo tee $finalfail2banjailconf <&2 + unset YNH_FORCE_UPGRADE + elif [ "$package_check" != "0" ] + then + echo "Upgrade forced for package check." >&2 + else + ynh_die "Up-to-date, nothing to do" 0 + fi + fi +} + +#================================================= + +# Send an email to inform the administrator +# +# usage: ynh_send_readme_to_admin app_message [recipients] +# | arg: app_message - The message to send to the administrator. +# | arg: recipients - The recipients of this email. Use spaces to separate multiples recipients. - default: root +# example: "root admin@domain" +# If you give the name of a YunoHost user, ynh_send_readme_to_admin will find its email adress for you +# example: "root admin@domain user1 user2" +ynh_send_readme_to_admin() { + local app_message="${1:-...No specific informations...}" + local recipients="${2:-root}" + + # Retrieve the email of users + find_mails () { + local list_mails="$1" + local mail + local recipients=" " + # Read each mail in argument + for mail in $list_mails + do + # Keep root or a real email address as it is + if [ "$mail" = "root" ] || echo "$mail" | grep --quiet "@" + then + recipients="$recipients $mail" + else + # But replace an user name without a domain after by its email + if mail=$(ynh_user_get_info "$mail" "mail" 2> /dev/null) + then + recipients="$recipients $mail" + fi + fi + done + echo "$recipients" + } + recipients=$(find_mails "$recipients") + + local mail_subject="☁️🆈🅽🅷☁️: \`$app\` was just installed!" + + local mail_message="This is an automated message from your beloved YunoHost server. + +Specific informations for the application $app. + +$app_message + +--- +Automatic diagnosis data from YunoHost + +$(yunohost tools diagnosis | grep -B 100 "services:" | sed '/services:/d')" + + # Send the email to the recipients + echo "$mail_message" | mail -a "Content-Type: text/plain; charset=UTF-8" -s "$mail_subject" "$recipients" +} #================================================= #============= FUTURE YUNOHOST HELPER ============ diff --git a/scripts/_sed b/scripts/_sed new file mode 100644 index 0000000..cc76ab9 --- /dev/null +++ b/scripts/_sed @@ -0,0 +1,51 @@ +#!/bin/bash + +# https://github.com/YunoHost/yunohost/pull/394 + +# Substitute/replace a string (or expression) by another in a file +# +# usage: ynh_replace_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. +# +# As this helper is based on sed command, regular expressions and +# references to sub-expressions can be used +# (see sed manual page for more information) +ynh_replace_string () { + local delimit=@ + local match_string=$1 + 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 password by another in a file +# +# usage: ynh_replace_password_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_password_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//\\/"\\\\"} + + # Escape the & character, who has a special function in sed. + match_string=${match_string//&/"\&"} + replace_string=${replace_string//&/"\&"} + + ynh_replace_string "$match_string" "$replace_string" "$workfile" +} diff --git a/scripts/change_url b/scripts/change_url index 8262d0e..52411cb 100644 --- a/scripts/change_url +++ b/scripts/change_url @@ -8,6 +8,7 @@ source _common.sh source /usr/share/yunohost/helpers +source _sed #================================================= # RETRIEVE ARGUMENTS @@ -59,11 +60,7 @@ fi ynh_clean_setup () { # Nettoyage des résidus d'installation non pris en charge par le script remove. - if test -n "$PID_TAIL" - then - SUPPRESS_WARNING kill -s 15 $PID_TAIL # Arrête l'exécution de tail. - ynh_secure_remove "$tempfile" - fi + ynh_clean_check_starting } # Exit if an error occurs during the execution of the script ynh_abort_if_errors @@ -136,21 +133,5 @@ systemctl reload nginx # START AND CHECK LUTIM BOOTING #================================================= -tempfile="$(mktemp)" -tail -f -n1 /var/log/$app/production.log > "$tempfile" & # Suit le démarrage dans le log -PID_TAIL=$! # Récupère le PID de la commande tail, qui est passée en arrière plan. -systemctl restart $app # Démarre lutim - -for i in `seq 1 60` -do # La boucle attend le démarrage de lutim. Ou 1 minute. Cette boucle évite simplement un 502 au début, car le démarrage est parfois long... - if grep -q "Manager.*started" "$tempfile"; then - cat "$tempfile" - WARNING echo "Le service $app a démarré correctement." - break # Si le log annonce le démarrage de lutim, sort de la boucle. - fi - WARNING echo -n "." - sleep 1 -done -echo "" -QUIET kill -s 15 $PID_TAIL # Arrête l'exécution de tail. -ynh_secure_remove "$tempfile" +# Wait for lutim fully started +ynh_check_starting "Manager.*started" "/var/log/$app/production.log" "120" diff --git a/scripts/install b/scripts/install index f519d18..5d39039 100644 --- a/scripts/install +++ b/scripts/install @@ -17,11 +17,7 @@ source _variables ynh_clean_setup () { # Nettoyage des résidus d'installation non pris en charge par le script remove. - if test -n "$PID_TAIL" - then - SUPPRESS_WARNING kill -s 15 $PID_TAIL # Arrête l'exécution de tail. - ynh_secure_remove "$tempfile" - fi + ynh_clean_check_starting } ynh_abort_if_errors @@ -67,7 +63,7 @@ ynh_app_setting_set $app always_encrypt $always_encrypt port=$(ynh_find_port 8095) # Cherche un port libre. # Ouvre le port dans le firewall -ALL_QUIET yunohost firewall allow --no-upnp TCP $port +ynh_exec_fully_quiet yunohost firewall allow --no-upnp TCP $port ynh_app_setting_set $app port $port #================================================= @@ -156,19 +152,6 @@ ln -s /var/log/$app/production.log "$final_path/log/production.log" chown -R $app: $final_path -#================================================= -# START LUTIM -#================================================= - -systemctl start lutim -# Set right permissions on new files created at first start -chown -R $app: $final_path - -# Check lutim starting -tempfile="$(mktemp)" -tail -f -n1 /var/log/$app/production.log > "$tempfile" & # Suit le démarrage dans le log -PID_TAIL=$! # Récupère le PID de la commande tail, qui est passée en arrière plan. - #================================================= # GENERIC FINALISATION #================================================= @@ -208,15 +191,18 @@ systemctl reload nginx # CHECK LUTIM BOOTING #================================================= -for i in `seq 1 60` -do # La boucle attend le démarrage de lutim. Ou 1 minute. Cette boucle évite simplement un 502 au début, car le démarrage est parfois long... - if grep -q "Manager.*started" "$tempfile"; then - WARNING echo "Le service $app a démarré correctement." - break # Si le log annonce le démarrage de lutim, sort de la boucle. - fi - WARNING echo -n "." - sleep 1 -done -echo "" -QUIET kill -s 15 $PID_TAIL # Arrête l'exécution de tail. -ynh_secure_remove "$tempfile" +# Wait for lutim fully started +ynh_check_starting "Manager.*started" "/var/log/$app/production.log" "120" + +# Set right permissions on new files created at first start +chown -R $app: $final_path + +#================================================= +# SEND A README FOR THE ADMIN +#================================================= + +message="You can find a config file at $final_path/lutim.conf + +If you facing an issue or want to improve this app, please open a new issue in this project: https://github.com/YunoHost-Apps/lutim_ynh" + +ynh_send_readme_to_admin "$message" "root" diff --git a/scripts/remove b/scripts/remove index 62d564c..6fe12f3 100644 --- a/scripts/remove +++ b/scripts/remove @@ -31,7 +31,7 @@ ynh_remove_systemd_config if yunohost service status | grep -q $app # Test l'existence du service dans Yunohost then - echo "Remove $app service" + ynh_print_info "Remove $app service" >&2 yunohost service remove $app fi diff --git a/scripts/restore b/scripts/restore index b8fa25f..b7b3821 100644 --- a/scripts/restore +++ b/scripts/restore @@ -20,6 +20,10 @@ source ../settings/scripts/_variables # MANAGE SCRIPT FAILURE #================================================= +ynh_clean_setup () { +# Nettoyage des résidus d'installation non pris en charge par le script remove. + ynh_clean_check_starting +} # Exit if an error occurs during the execution of the script ynh_abort_if_errors @@ -37,7 +41,7 @@ path_url=$(ynh_app_setting_get $app path) # CHECK IF THE APP CAN BE RESTORED #================================================= -yunohost app checkurl "${domain}${path_url}" -a "$app" \ +ynh_webpath_available $domain $path_url \ || ynh_die "Path not available: ${domain}${path_url}" test ! -d $final_path \ || ynh_die "There is already a directory: $final_path " @@ -124,20 +128,15 @@ systemctl reload nginx # START AND CHECK LUTIM BOOTING #================================================= -tempfile="$(mktemp)" -tail -f -n1 /var/log/$app/production.log > "$tempfile" & # Suit le démarrage dans le log -PID_TAIL=$! # Récupère le PID de la commande tail, qui est passée en arrière plan. -systemctl restart $app # Démarre lutim +# Wait for lutim fully started +ynh_check_starting "Manager.*started" "/var/log/$app/production.log" "120" -for i in `seq 1 60` -do # La boucle attend le démarrage de lutim. Ou 1 minute. Cette boucle évite simplement un 502 au début, car le démarrage est parfois long... - if grep -q "Manager.*started" "$tempfile"; then - WARNING echo "Le service $app a démarré correctement." - break # Si le log annonce le démarrage de lutim, sort de la boucle. - fi - WARNING echo -n "." - sleep 1 -done -echo "" -QUIET kill -s 15 $PID_TAIL # Arrête l'exécution de tail. -ynh_secure_remove "$tempfile" +#================================================= +# SEND A README FOR THE ADMIN +#================================================= + +message="You can find a config file at $final_path/lutim.conf + +If you facing an issue or want to improve this app, please open a new issue in this project: https://github.com/YunoHost-Apps/lutim_ynh" + +ynh_send_readme_to_admin "$message" "root" diff --git a/scripts/upgrade b/scripts/upgrade index 0d7acb1..93bb749 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -25,6 +25,12 @@ port=$(ynh_app_setting_get $app port) always_encrypt=$(ynh_app_setting_get $app always_encrypt) final_path=$(ynh_app_setting_get $app final_path) +#================================================= +# CHECK VERSION +#================================================= + +ynh_abort_if_up_to_date + #================================================= # FIX OLD THINGS #================================================= @@ -59,11 +65,7 @@ fi ynh_backup_before_upgrade ynh_clean_setup () { # Nettoyage des résidus d'installation non pris en charge par le script remove. - if test -n "$PID_TAIL" - then - SUPPRESS_WARNING kill -s 15 $PID_TAIL # Arrête l'exécution de tail. - ynh_secure_remove "$tempfile" - fi + ynh_clean_check_starting # restore it if the upgrade fails ynh_restore_upgradebackup } @@ -174,21 +176,5 @@ systemctl reload nginx # START AND CHECK LUTIM BOOTING #================================================= -tempfile="$(mktemp)" -tail -f -n1 /var/log/$app/production.log > "$tempfile" & # Suit le démarrage dans le log -PID_TAIL=$! # Récupère le PID de la commande tail, qui est passée en arrière plan. -systemctl restart $app # Démarre lutim - -for i in `seq 1 60` -do # La boucle attend le démarrage de lutim. Ou 1 minute. Cette boucle évite simplement un 502 au début, car le démarrage est parfois long... - if grep -q "Manager.*started" "$tempfile"; then - cat "$tempfile" - WARNING echo "Le service $app a démarré correctement." - break # Si le log annonce le démarrage de lutim, sort de la boucle. - fi - WARNING echo -n "." - sleep 1 -done -echo "" -QUIET kill -s 15 $PID_TAIL # Arrête l'exécution de tail. -ynh_secure_remove "$tempfile" +# Wait for lutim fully started +ynh_check_starting "Manager.*started" "/var/log/$app/production.log" "120"