diff --git a/README.md b/README.md index 9738ebf..e130197 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Etherpad with mypads plugin for YunoHost -[![Integration level](https://dash.yunohost.org/integration/etherpad_mypads.svg)](https://ci-apps.yunohost.org/jenkins/job/etherpad_mypads%20%28Community%29/lastBuild/consoleFull) +[![Integration level](https://dash.yunohost.org/integration/etherpad_mypads.svg)](https://ci-apps.yunohost.org/jenkins/job/etherpad_mypads%20%28Official%29/lastBuild/consoleFull) [![Install Etherpad with YunoHost](https://install-app.yunohost.org/install-with-yunohost.png)](https://install-app.yunohost.org/?app=etherpad_mypads) *[Lire ce readme en français.](./README_fr.md)* @@ -40,8 +40,8 @@ Supported, with LDAP. #### Supported architectures -* x86-64b - [![Build Status](https://ci-apps.yunohost.org/jenkins/job/etherpad_mypads%20(Community)/badge/icon)](https://ci-apps.yunohost.org/jenkins/job/etherpad_mypads%20(Community)/) -* ARMv8-A - [![Build Status](https://ci-apps-arm.yunohost.org/jenkins/job/etherpad_mypads%20(Community)%20(%7EARM%7E)/badge/icon)](https://ci-apps-arm.yunohost.org/jenkins/job/etherpad_mypads%20(Community)%20(%7EARM%7E)/) +* x86-64b - [![Build Status](https://ci-apps.yunohost.org/jenkins/job/etherpad_mypads%20(Official)/badge/icon)](https://ci-apps.yunohost.org/jenkins/job/etherpad_mypads%20(Official)/) +* ARMv8-A - [![Build Status](https://ci-apps-arm.yunohost.org/jenkins/job/etherpad_mypads%20(Official)%20(%7EARM%7E)/badge/icon)](https://ci-apps-arm.yunohost.org/jenkins/job/etherpad_mypads%20(Official)%20(%7EARM%7E)/) ## Limitations diff --git a/README_fr.md b/README_fr.md index a661fb5..4d5e6c8 100644 --- a/README_fr.md +++ b/README_fr.md @@ -1,6 +1,6 @@ # Etherpad avec plugin mypads pour YunoHost -[![Niveau d'intégration](https://dash.yunohost.org/integration/etherpad_mypads.svg)](https://ci-apps.yunohost.org/jenkins/job/etherpad_mypads%20%28Community%29/lastBuild/consoleFull) +[![Niveau d'intégration](https://dash.yunohost.org/integration/etherpad_mypads.svg)](https://ci-apps.yunohost.org/jenkins/job/etherpad_mypads%20%28Official%29/lastBuild/consoleFull) [![Installer Etherpad avec YunoHost](https://install-app.yunohost.org/install-with-yunohost.png)](https://install-app.yunohost.org/?app=etherpad_mypads) *[Read this readme in english.](./README.md)* @@ -40,8 +40,8 @@ Supportée, avec LDAP. #### Architectures supportées. -* x86-64b - [![Build Status](https://ci-apps.yunohost.org/jenkins/job/etherpad_mypads%20(Community)/badge/icon)](https://ci-apps.yunohost.org/jenkins/job/etherpad_mypads%20(Community)/) -* ARMv8-A - [![Build Status](https://ci-apps-arm.yunohost.org/jenkins/job/etherpad_mypads%20(Community)%20(%7EARM%7E)/badge/icon)](https://ci-apps-arm.yunohost.org/jenkins/job/etherpad_mypads%20(Community)%20(%7EARM%7E)/) +* x86-64b - [![Build Status](https://ci-apps.yunohost.org/jenkins/job/etherpad_mypads%20(Official)/badge/icon)](https://ci-apps.yunohost.org/jenkins/job/etherpad_mypads%20(Official)/) +* ARMv8-A - [![Build Status](https://ci-apps-arm.yunohost.org/jenkins/job/etherpad_mypads%20(Official)%20(%7EARM%7E)/badge/icon)](https://ci-apps-arm.yunohost.org/jenkins/job/etherpad_mypads%20(Official)%20(%7EARM%7E)/) ## Limitations diff --git a/manifest.json b/manifest.json index 9f8a5c1..9289ca0 100644 --- a/manifest.json +++ b/manifest.json @@ -6,7 +6,7 @@ "en": "Framapad clone, a online editor providing collaborative editing in real-time.", "fr": "Clone de Framapad, un éditeur en ligne fournissant l'édition collaborative en temps réel." }, - "version": "1.6.5~ynh2", + "version": "1.6.5~ynh4", "url": "https://framapad.org", "license": "Apache-2.0", "maintainer": { @@ -14,7 +14,7 @@ "email": "maniackc_dev@crudelis.fr" }, "requirements": { - "yunohost": ">= 2.7.10" + "yunohost": ">= 2.7.12" }, "multi_instance": true, "services": [ diff --git a/scripts/_common.sh b/scripts/_common.sh index e47feeb..44a54cc 100755 --- a/scripts/_common.sh +++ b/scripts/_common.sh @@ -26,239 +26,41 @@ CHECK_SIZE () { # Vérifie avant chaque backup que l'espace est suffisant # EXPERIMENTAL HELPERS #================================================= -n_install_dir="/opt/node_n" -node_version_path="$n_install_dir/n/versions/node" -# N_PREFIX is the directory of n, it needs to be loaded as a environment variable. -export N_PREFIX="$n_install_dir" - -# Install Node version management -# -# [internal] -# -# usage: ynh_install_n -ynh_install_n () { - echo "Installation of N - Node.js version management" >&2 - # Build an app.src for n - mkdir -p "../conf" - echo "SOURCE_URL=https://github.com/tj/n/archive/v2.1.7.tar.gz -SOURCE_SUM=2ba3c9d4dd3c7e38885b37e02337906a1ee91febe6d5c9159d89a9050f2eea8f" > "../conf/n.src" - # Download and extract n - ynh_setup_source "$n_install_dir/git" n - # Install n - (cd "$n_install_dir/git" - PREFIX=$N_PREFIX make install 2>&1) -} - -# Load the version of node for an app, and set variables. -# -# ynh_use_nodejs has to be used in any app scripts before using node for the first time. -# -# 2 variables are available: -# - $nodejs_path: The absolute path of node for the chosen version. -# - $nodejs_version: Just the version number of node for this app. Stored as 'nodejs_version' in settings.yml. -# And 2 alias stored in variables: -# - $nodejs_use_version: An old variable, not used anymore. Keep here to not break old apps -# NB: $PATH will contain the path to node, it has to be propagated to any other shell which needs to use it. -# That's means it has to be added to any systemd script. -# -# usage: ynh_use_nodejs -ynh_use_nodejs () { - nodejs_version=$(ynh_app_setting_get $app nodejs_version) - - nodejs_use_version="echo \"Deprecated command, should be removed\"" - - # Get the absolute path of this version of node - nodejs_path="$node_version_path/$nodejs_version/bin" - - # Load the path of this version of node in $PATH - [[ :$PATH: == *":$nodejs_path"* ]] || PATH="$nodejs_path:$PATH" -} - -# Install a specific version of nodejs -# -# n (Node version management) uses the PATH variable to store the path of the version of node it is going to use. -# That's how it changes the version -# -# ynh_install_nodejs will install the version of node provided as argument by using n. -# -# usage: ynh_install_nodejs [nodejs_version] -# | arg: nodejs_version - Version of node to install. -# If possible, prefer to use major version number (e.g. 8 instead of 8.10.0). -# The crontab will handle the update of minor versions when needed. -ynh_install_nodejs () { - # Use n, https://github.com/tj/n to manage the nodejs versions - nodejs_version="$1" - - # Create $n_install_dir - mkdir -p "$n_install_dir" - - # Load n path in PATH - CLEAR_PATH="$n_install_dir/bin:$PATH" - # Remove /usr/local/bin in PATH in case of node prior installation - PATH=$(echo $CLEAR_PATH | sed 's@/usr/local/bin:@@') - - # Move an existing node binary, to avoid to block n. - test -x /usr/bin/node && mv /usr/bin/node /usr/bin/node_n - test -x /usr/bin/npm && mv /usr/bin/npm /usr/bin/npm_n - - # If n is not previously setup, install it - if ! test $(n --version > /dev/null 2>&1) - then - ynh_install_n - fi - - # Modify the default N_PREFIX in n script - ynh_replace_string "^N_PREFIX=\${N_PREFIX-.*}$" "N_PREFIX=\${N_PREFIX-$N_PREFIX}" "$n_install_dir/bin/n" - - # Restore /usr/local/bin in PATH - PATH=$CLEAR_PATH - - # And replace the old node binary. - test -x /usr/bin/node_n && mv /usr/bin/node_n /usr/bin/node - test -x /usr/bin/npm_n && mv /usr/bin/npm_n /usr/bin/npm - - # Install the requested version of nodejs - n $nodejs_version - - # Find the last "real" version for this major version of node. - real_nodejs_version=$(find $node_version_path/$nodejs_version* -maxdepth 0 | sort --version-sort | tail --lines=1) - real_nodejs_version=$(basename $real_nodejs_version) - - # Create a symbolic link for this major version if the file doesn't already exist - if [ ! -e "$node_version_path/$nodejs_version" ] - then - ln --symbolic --force --no-target-directory $node_version_path/$real_nodejs_version $node_version_path/$nodejs_version - fi - - # Store the ID of this app and the version of node requested for it - echo "$YNH_APP_ID:$nodejs_version" | tee --append "$n_install_dir/ynh_app_version" - - # Store nodejs_version into the config of this app - ynh_app_setting_set $app nodejs_version $nodejs_version - - # Build the update script and set the cronjob - ynh_cron_upgrade_node - - ynh_use_nodejs -} - -# Remove the version of node used by the app. -# -# This helper will check if another app uses the same version of node, -# if not, this version of node will be removed. -# If no other app uses node, n will be also removed. -# -# usage: ynh_remove_nodejs -ynh_remove_nodejs () { - nodejs_version=$(ynh_app_setting_get $app nodejs_version) - - # Remove the line for this app - sed --in-place "/$YNH_APP_ID:$nodejs_version/d" "$n_install_dir/ynh_app_version" - - # If no other app uses this version of nodejs, remove it. - if ! grep --quiet "$nodejs_version" "$n_install_dir/ynh_app_version" - then - $n_install_dir/bin/n rm $nodejs_version - fi - - # If no other app uses n, remove n - if [ ! -s "$n_install_dir/ynh_app_version" ] - then - ynh_secure_remove "$n_install_dir" - ynh_secure_remove "/usr/local/n" - fi -} - -# Set a cron design to update your node versions -# -# [internal] -# -# This cron will check and update all minor node versions used by your apps. -# -# usage: ynh_cron_upgrade_node -ynh_cron_upgrade_node () { - # Build the update script - cat > "$n_install_dir/node_update.sh" << EOF -#!/bin/bash - -version_path="$node_version_path" -n_install_dir="$n_install_dir" - -# Log the date -date - -# List all real installed version of node -all_real_version="\$(find \$version_path/* -maxdepth 0 -type d | sed "s@\$version_path/@@g")" - -# Keep only the major version number of each line -all_real_version=\$(echo "\$all_real_version" | sed 's/\..*\$//') - -# Remove double entries -all_real_version=\$(echo "\$all_real_version" | sort --unique) - -# Read each major version -while read version -do - echo "Update of the version \$version" - sudo \$n_install_dir/bin/n \$version - - # Find the last "real" version for this major version of node. - real_nodejs_version=\$(find \$version_path/\$version* -maxdepth 0 | sort --version-sort | tail --lines=1) - real_nodejs_version=\$(basename \$real_nodejs_version) - - # Update the symbolic link for this version - sudo ln --symbolic --force --no-target-directory \$version_path/\$real_nodejs_version \$version_path/\$version -done <<< "\$(echo "\$all_real_version")" -EOF - - chmod +x "$n_install_dir/node_update.sh" - - # Build the cronjob - cat > "/etc/cron.daily/node_update" << EOF -#!/bin/bash - -$n_install_dir/node_update.sh >> $n_install_dir/node_update.log -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] [Service name] # # | 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 -# | arg: Service name -# /var/log/$app/$app.log will be used if no other log is defined. +# | arg: Log file - The log file to watch; specify "systemd" to read systemd journal for specified service +# /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. +# | arg: Service name + ynh_check_starting () { local line_to_match="$1" - local service_name="${4:-$app}" local app_log="${2:-/var/log/$service_name/$service_name.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 - } + local service_name="${4:-$app}" echo "Starting of $service_name" >&2 systemctl stop $service_name local templog="$(mktemp)" # Following the starting of the app in its log - tail -F -n0 "$app_log" > "$templog" & - # Get the PID of the tail command + if [ "$app_log" == "systemd" ] ; then + # Read the systemd journal + journalctl -u $service_name -f --since=-45 > "$templog" & + else + # Read the specified log file + tail -F -n0 "$app_log" > "$templog" & + fi + # Get the PID of the last command local pid_tail=$! systemctl start $service_name 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 + # Read the log until the sentence is found, which means the app finished starting. Or run until the timeout. if grep --quiet "$line_to_match" "$templog" then echo "The service $service_name has correctly started." >&2 @@ -269,12 +71,22 @@ ynh_check_starting () { done if [ $i -eq $timeout ] then - echo "The service $service_name didn't fully started before the timeout." >&2 + echo "The service $service_name didn't fully start before the timeout." >&2 fi echo "" ynh_clean_check_starting } +# Clean temporary process and file used by ynh_check_starting +# (usually used in ynh_clean_setup scripts) +# +# usage: ynh_clean_check_starting + +ynh_clean_check_starting () { + # Stop the execution of tail. + kill -s 15 $pid_tail 2>&1 + ynh_secure_remove "$templog" 2>&1 +} #================================================= @@ -385,7 +197,7 @@ EOF ynh_remove_fail2ban_config () { ynh_secure_remove "/etc/fail2ban/jail.d/$app.conf" ynh_secure_remove "/etc/fail2ban/filter.d/$app.conf" - sudo systemctl restart fail2ban + systemctl restart fail2ban } #================================================= @@ -398,7 +210,39 @@ ynh_remove_fail2ban_config () { ynh_read_manifest () { manifest="$1" key="$2" - python3 -c "import sys, json;print(json.load(open('$manifest'))['$key'])" + python3 -c "import sys, json;print(json.load(open('$manifest', encoding='utf-8'))['$key'])" +} + +# Read the upstream version from the manifest +# The version number in the manifest is defined by ~ynh +# For example : 4.3-2~ynh3 +# This include the number before ~ynh +# In the last example it return 4.3-2 +# +# usage: ynh_app_upstream_version +ynh_app_upstream_version () { + 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_key=$(ynh_read_manifest "$manifest_path" "version") + echo "${version_key/~ynh*/}" +} + +# Read package version from the manifest +# The version number in the manifest is defined by ~ynh +# For example : 4.3-2~ynh3 +# This include the number after ~ynh +# In the last example it return 3 +# +# usage: ynh_app_package_version +ynh_app_package_version () { + 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_key=$(ynh_read_manifest "$manifest_path" "version") + echo "${version_key/*~ynh/}" } # Exit without error if the package is up to date @@ -496,7 +340,20 @@ $(yunohost tools diagnosis | grep -B 100 "services:" | sed '/services:/d')" } #================================================= -#============= FUTURE YUNOHOST HELPER ============ + +# Reload (or other actions) a service and print a log in case of failure. +# +# usage: ynh_system_reload service_name [action] +# | arg: service_name - Name of the service to reload +# | arg: action - Action to perform with systemctl. Default: reload +ynh_system_reload () { + local service_name=$1 + local action=${2:-reload} + + # Reload, restart or start and print the log if the service fail to start or reload + systemctl $action $service_name || ( journalctl --lines=20 -u $service_name >&2 && false) +} + #================================================= # Delete a file checksum from the app settings @@ -509,3 +366,66 @@ ynh_delete_file_checksum () { local checksum_setting_name=checksum_${1//[\/ ]/_} # Replace all '/' and ' ' by '_' ynh_app_setting_delete $app $checksum_setting_name } + +#================================================= + +ynh_maintenance_mode_ON () { + # Create an html to serve as maintenance notice + echo " + + + +Your app $app is currently under maintenance! + + + +

Your app $app is currently under maintenance!

+

This app has been put under maintenance by your administrator at $(date)

+

Please wait until the maintenance operation is done. This page will be reloaded as soon as your app will be back.

+ + +" > "/var/www/html/maintenance.$app.html" + + # Create a new nginx config file to redirect all access to the app to the maintenance notice instead. + echo "# All request to the app will be redirected to ${path_url}_maintenance and fall on the maintenance notice +rewrite ^${path_url}/(.*)$ ${path_url}_maintenance/? redirect; +# Use another location, to not be in conflict with the original config file +location ${path_url}_maintenance/ { +alias /var/www/html/ ; + +try_files maintenance.$app.html =503; + +# Include SSOWAT user panel. +include conf.d/yunohost_panel.conf.inc; +}" > "/etc/nginx/conf.d/$domain.d/maintenance.$app.conf" + + # The current config file will redirect all requests to the root of the app. + # To keep the full path, we can use the following rewrite rule: + # rewrite ^${path_url}/(.*)$ ${path_url}_maintenance/\$1? redirect; + # The difference will be in the $1 at the end, which keep the following queries. + # But, if it works perfectly for a html request, there's an issue with any php files. + # This files are treated as simple files, and will be downloaded by the browser. + # Would be really be nice to be able to fix that issue. So that, when the page is reloaded after the maintenance, the user will be redirected to the real page he was. + + systemctl reload nginx +} + +ynh_maintenance_mode_OFF () { + # Rewrite the nginx config file to redirect from ${path_url}_maintenance to the real url of the app. + echo "rewrite ^${path_url}_maintenance/(.*)$ ${path_url}/\$1 redirect;" > "/etc/nginx/conf.d/$domain.d/maintenance.$app.conf" + systemctl reload nginx + + # Sleep 4 seconds to let the browser reload the pages and redirect the user to the app. + sleep 4 + + # Then remove the temporary files used for the maintenance. + rm "/var/www/html/maintenance.$app.html" + rm "/etc/nginx/conf.d/$domain.d/maintenance.$app.conf" + + systemctl reload nginx +} diff --git a/scripts/_variables b/scripts/_variables index 5fe186f..c5103fb 100644 --- a/scripts/_variables +++ b/scripts/_variables @@ -11,4 +11,4 @@ nodejs_version=4 # Version of mypads # This variable is mostly used to force an upgrade of the package in case of new versions of mypads. -mypads_version=1.4.5 +mypads_version=1.4.6 diff --git a/scripts/change_url b/scripts/change_url index 06a5b58..3b4ec90 100644 --- a/scripts/change_url +++ b/scripts/change_url @@ -32,6 +32,14 @@ test -n "$new_path" || new_path="/" new_path=$(ynh_normalize_url_path $new_path) old_path=$(ynh_normalize_url_path $old_path) +#================================================= +# ACTIVATE MAINTENANCE MODE +#================================================= + +path_url=$old_path +domain=$old_domain +ynh_maintenance_mode_ON + #================================================= # CHECK WHICH PARTS SHOULD BE CHANGED #================================================= @@ -115,7 +123,7 @@ fi # RELOAD NGINX #================================================= -systemctl reload nginx +ynh_system_reload nginx #================================================= # CHECK ETHERPAD STARTING @@ -123,3 +131,11 @@ systemctl reload nginx # Wait for etherpad fully started ynh_check_starting "You can access your Etherpad instance at" "/var/log/$app/etherpad.log" "120" + +#================================================= +# DEACTIVE MAINTENANCE MODE +#================================================= + +path_url=$old_path +domain=$old_domain +ynh_maintenance_mode_OFF diff --git a/scripts/install b/scripts/install index 27a4853..929c3af 100644 --- a/scripts/install +++ b/scripts/install @@ -73,6 +73,12 @@ ynh_app_setting_set $app export $export ynh_app_setting_set $app mypads $mypads ynh_app_setting_set $app useldap $useldap +#================================================= +# ACTIVATE MAINTENANCE MODE +#================================================= + +ynh_maintenance_mode_ON + #================================================= # STANDARD MODIFICATIONS #================================================= @@ -270,7 +276,7 @@ fi # RELOAD NGINX #================================================= -systemctl reload nginx +ynh_system_reload nginx #================================================= # CHECK ETHERPAD STARTING @@ -288,6 +294,12 @@ then ynh_check_starting "You can access your Etherpad instance at" "/var/log/$app/etherpad.log" "120" fi +#================================================= +# DEACTIVE MAINTENANCE MODE +#================================================= + +ynh_maintenance_mode_OFF + #================================================= # SEND A README FOR THE ADMIN #================================================= diff --git a/scripts/restore b/scripts/restore index abea9fe..bae61cd 100644 --- a/scripts/restore +++ b/scripts/restore @@ -51,6 +51,12 @@ ynh_webpath_available $domain $path_url \ test ! -d $final_path \ || ynh_die "There is already a directory: $final_path " +#================================================= +# ACTIVATE MAINTENANCE MODE +#================================================= + +ynh_maintenance_mode_ON + #================================================= # STANDARD RESTORE STEPS #================================================= @@ -139,13 +145,13 @@ systemctl enable $app.service ynh_restore_file "/etc/fail2ban/jail.d/$app.conf" ynh_restore_file "/etc/fail2ban/filter.d/$app.conf" -systemctl restart fail2ban +ynh_system_reload fail2ban restart #================================================= # RELOAD NGINX #================================================= -systemctl reload nginx +ynh_system_reload nginx #================================================= # CHECK ETHERPAD STARTING @@ -154,6 +160,12 @@ systemctl reload nginx # Wait for etherpad to be fully started ynh_check_starting "You can access your Etherpad instance at" "/var/log/$app/etherpad.log" "120" +#================================================= +# DEACTIVE MAINTENANCE MODE +#================================================= + +ynh_maintenance_mode_OFF + #================================================= # SEND A README FOR THE ADMIN #================================================= diff --git a/scripts/upgrade b/scripts/upgrade index 29ce234..7198bcb 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -104,11 +104,17 @@ ynh_clean_setup () { # Exit if an error occurs during the execution of the script ynh_abort_if_errors +#================================================= +# ACTIVATE MAINTENANCE MODE +#================================================= + +ynh_maintenance_mode_ON + #================================================= # STOP ETHERPAD #================================================= -systemctl stop $app +ynh_system_reload $app stop #================================================= # STANDARD UPGRADE STEPS @@ -260,7 +266,7 @@ fi # RELOAD NGINX #================================================= -systemctl reload nginx +ynh_system_reload nginx #================================================= # CHECK ETHERPAD STARTING @@ -268,3 +274,9 @@ systemctl reload nginx # Wait for etherpad to be fully started ynh_check_starting "You can access your Etherpad instance at" "/var/log/$app/etherpad.log" "120" + +#================================================= +# DEACTIVE MAINTENANCE MODE +#================================================= + +ynh_maintenance_mode_OFF