Merge branch 'stretch-unstable' into permission_protection

This commit is contained in:
Josué Tille 2020-04-28 14:04:29 +02:00
commit 73e2ede910
No known key found for this signature in database
GPG key ID: 716A6C99B04194EF
38 changed files with 2392 additions and 1973 deletions

View file

@ -92,3 +92,10 @@ test-user-group:
script:
- cd src/yunohost
- py.test tests/test_user-group.py
test-regenconf:
extends: .tests
stage: tests
script:
- cd src/yunohost
- py.test tests/test_regenconf.py

View file

@ -415,6 +415,10 @@ domain:
list:
action_help: List domains
api: GET /domains
arguments:
--exclude-subdomains:
help: Filter out domains that are obviously subdomains of other declared domains
action: store_true
### domain_add()
add:
@ -572,6 +576,9 @@ app:
help: Also return a list of app categories
action: store_true
fetchlist:
deprecated: true
### app_list()
list:
action_help: List installed apps
@ -581,6 +588,12 @@ app:
full: --full
help: Display all details, including the app manifest and various other infos
action: store_true
-i:
full: --installed
help: Dummy argument, does nothing anymore (still there only for backward compatibility)
action: store_true
filter:
nargs: '?'
### app_info()
info:

View file

@ -5,6 +5,7 @@
# [internal]
#
# usage: ynh_wait_dpkg_free
# | exit: Return 1 if dpkg is broken
#
# Requires YunoHost version 3.3.1 or higher.
ynh_wait_dpkg_free() {
@ -27,7 +28,7 @@ ynh_wait_dpkg_free() {
while read dpkg_file <&9
do
# Check if the name of this file contains only numbers.
if echo "$dpkg_file" | grep -Pq "^[[:digit:]]+$"
if echo "$dpkg_file" | grep --perl-regexp --quiet "^[[:digit:]]+$"
then
# If so, that a remaining of dpkg.
ynh_print_err "E: dpkg was interrupted, you must manually run 'sudo dpkg --configure -a' to correct the problem."
@ -45,20 +46,20 @@ ynh_wait_dpkg_free() {
# example: ynh_package_is_installed --package=yunohost && echo "ok"
#
# usage: ynh_package_is_installed --package=name
# | arg: -p, --package - the package name to check
# | arg: -p, --package= - the package name to check
#
# Requires YunoHost version 2.2.4 or higher.
ynh_package_is_installed() {
# Declare an array to define the options of this helper.
local legacy_args=p
declare -Ar args_array=( [p]=package= )
local -A args_array=( [p]=package= )
local package
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
ynh_wait_dpkg_free
dpkg-query -W -f '${Status}' "$package" 2>/dev/null \
| grep -c "ok installed" &>/dev/null
dpkg-query --show --showformat='${Status}' "$package" 2>/dev/null \
| grep --count "ok installed" &>/dev/null
}
# Get the version of an installed package
@ -66,20 +67,21 @@ ynh_package_is_installed() {
# example: version=$(ynh_package_version --package=yunohost)
#
# usage: ynh_package_version --package=name
# | arg: -p, --package - the package name to get version
# | arg: -p, --package= - the package name to get version
# | ret: the version or an empty string
#
# Requires YunoHost version 2.2.4 or higher.
ynh_package_version() {
# Declare an array to define the options of this helper.
local legacy_args=p
declare -Ar args_array=( [p]=package= )
local -A args_array=( [p]=package= )
local package
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
if ynh_package_is_installed "$package"; then
dpkg-query -W -f '${Version}' "$package" 2>/dev/null
if ynh_package_is_installed "$package"
then
dpkg-query --show --showformat='${Version}' "$package" 2>/dev/null
else
echo ''
fi
@ -94,7 +96,7 @@ ynh_package_version() {
# Requires YunoHost version 2.4.0.3 or higher.
ynh_apt() {
ynh_wait_dpkg_free
LC_ALL=C DEBIAN_FRONTEND=noninteractive apt-get -y $@
LC_ALL=C DEBIAN_FRONTEND=noninteractive apt-get --assume-yes $@
}
# Update package index files
@ -113,8 +115,8 @@ ynh_package_update() {
#
# Requires YunoHost version 2.2.4 or higher.
ynh_package_install() {
ynh_apt --no-remove -o Dpkg::Options::=--force-confdef \
-o Dpkg::Options::=--force-confold install $@
ynh_apt --no-remove --option Dpkg::Options::=--force-confdef \
--option Dpkg::Options::=--force-confold install $@
}
# Remove package(s)
@ -163,8 +165,8 @@ ynh_package_install_from_equivs () {
local controlfile=$1
# retrieve package information
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
local pkgname=$(grep '^Package: ' $controlfile | cut --delimiter=' ' --fields=2) # Retrieve the name of the debian package
local pkgversion=$(grep '^Version: ' $controlfile | cut --delimiter=' ' --fields=2) # And its version number
[[ -z "$pkgname" || -z "$pkgversion" ]] \
&& ynh_die --message="Invalid control file" # Check if this 2 variables aren't empty.
@ -172,7 +174,7 @@ ynh_package_install_from_equivs () {
ynh_package_update
# Build and install the package
local TMPDIR=$(mktemp -d)
local TMPDIR=$(mktemp --directory)
# Force the compatibility level at 10, levels below are deprecated
echo 10 > /usr/share/equivs/template/debian/compat
@ -185,21 +187,21 @@ ynh_package_install_from_equivs () {
cp "$controlfile" "${TMPDIR}/control"
(cd "$TMPDIR"
LC_ALL=C equivs-build ./control 1> /dev/null
dpkg --force-depends -i "./${pkgname}_${pkgversion}_all.deb" 2>&1)
dpkg --force-depends --install "./${pkgname}_${pkgversion}_all.deb" 2>&1)
# If install fails we use "apt-get check" to try to debug and diagnose possible unmet dependencies
# Note the use of { } which allows to group commands without starting a subshell (otherwise the ynh_die wouldn't exit the current shell).
# Be careful with the syntax : the semicolon + space at the end is important!
ynh_package_install -f || \
ynh_package_install --fix-broken || \
{ # If the installation failed
# Get the list of dependencies from the deb
local dependencies="$(dpkg --info "$TMPDIR/${pkgname}_${pkgversion}_all.deb" | grep Depends | \
sed 's/^ Depends: //' | sed 's/,//g')"
sed 's/^ Depends: //' | sed 's/,//g')"
# Fake an install of those dependencies to see the errors
# The sed command here is, Print only from '--fix-broken' to the end.
ynh_package_install $dependencies --dry-run | sed -n '/--fix-broken/,$p' >&2
ynh_package_install $dependencies --dry-run | sed --quiet '/--fix-broken/,$p' >&2
ynh_die --message="Unable to install dependencies"; }
[[ -n "$TMPDIR" ]] && rm -rf $TMPDIR # Remove the temp dir.
[[ -n "$TMPDIR" ]] && rm --recursive --force $TMPDIR # Remove the temp dir.
# check if the package is actually installed
ynh_package_is_installed "$pkgname"
@ -222,10 +224,10 @@ ynh_install_app_dependencies () {
local dependencies=${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
manifest_path="../settings/manifest.json" # Into the restore script, the manifest is not at the same place
fi
local version=$(grep '\"version\": ' "$manifest_path" | cut -d '"' -f 4) # Retrieve the version number in the manifest file.
local version=$(grep '\"version\": ' "$manifest_path" | cut --delimiter='"' --fields=4) # Retrieve the version number in the manifest file.
if [ ${#version} -eq 0 ]; then
version="1.0"
fi
@ -251,16 +253,16 @@ ynh_install_app_dependencies () {
# https://github.com/YunoHost/issues/issues/1407
#
# If we require to install php dependency
if echo $dependencies | grep -q 'php';
if echo $dependencies | grep --quiet 'php'
then
# And we have packages from sury installed (7.0.33-10+weirdshiftafter instead of 7.0.33-0 on debian)
if dpkg --list | grep "php7.0" | grep -q -v "7.0.33-0+deb9"
if dpkg --list | grep "php7.0" | grep --quiet --invert-match "7.0.33-0+deb9"
then
# And sury ain't already installed
if ! grep -nrq "sury" /etc/apt/sources.list*
if ! grep --line-number --recursive --quiet "sury" /etc/apt/sources.list*
then
# Re-add sury
ynh_install_extra_repo --repo="https://packages.sury.org/php/ $(lsb_release -sc) main" --key="https://packages.sury.org/php/apt.gpg" --name=extra_php_version
ynh_install_extra_repo --repo="https://packages.sury.org/php/ $(ynh_get_debian_release) main" --key="https://packages.sury.org/php/apt.gpg" --name=extra_php_version
# Pin this sury repository to prevent sury of doing shit
ynh_pin_repo --package="*" --pin="origin \"packages.sury.org\"" --priority=200 --name=extra_php_version
@ -287,34 +289,34 @@ EOF
# Add dependencies to install with ynh_install_app_dependencies
#
# [internal]
#
# usage: ynh_add_app_dependencies --package=phpversion [--replace]
# | arg: -p, --package - Packages to add as dependencies for the app.
# | arg: -r, --replace - Replace dependencies instead of adding to existing ones.
# | arg: -p, --package= - Packages to add as dependencies for the app.
# | arg: -r, --replace - Replace dependencies instead of adding to existing ones.
#
# Requires YunoHost version 3.8.1 or higher.
ynh_add_app_dependencies () {
# Declare an array to define the options of this helper.
local legacy_args=pr
declare -Ar args_array=( [p]=package= [r]=replace)
local package
local replace
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
replace=${replace:-0}
# Declare an array to define the options of this helper.
local legacy_args=pr
local -A args_array=( [p]=package= [r]=replace)
local package
local replace
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
replace=${replace:-0}
local current_dependencies=""
if [ $replace -eq 0 ]
then
local dep_app=${app//_/-} # Replace all '_' by '-'
if ynh_package_is_installed --package="${dep_app}-ynh-deps"
then
current_dependencies="$(dpkg-query --show --showformat='${Depends}' ${dep_app}-ynh-deps) "
fi
local current_dependencies=""
if [ $replace -eq 0 ]
then
local dep_app=${app//_/-} # Replace all '_' by '-'
if ynh_package_is_installed --package="${dep_app}-ynh-deps"
then
current_dependencies="$(dpkg-query --show --showformat='${Depends}' ${dep_app}-ynh-deps) "
fi
current_dependencies=${current_dependencies// | /|}
fi
current_dependencies=${current_dependencies// | /|}
fi
ynh_install_app_dependencies "${current_dependencies}${package}"
ynh_install_app_dependencies "${current_dependencies}${package}"
}
# Remove fake package and its dependencies
@ -334,36 +336,38 @@ ynh_remove_app_dependencies () {
# Install packages from an extra repository properly.
#
# usage: ynh_install_extra_app_dependencies --repo="repo" --package="dep1 dep2" [--key=key_url] [--name=name]
# | arg: -r, --repo - Complete url of the extra repository.
# | arg: -p, --package - The packages to install from this extra repository
# | arg: -k, --key - url to get the public key.
# | arg: -n, --name - Name for the files for this repo, $app as default value.
# | arg: -r, --repo= - Complete url of the extra repository.
# | arg: -p, --package= - The packages to install from this extra repository
# | arg: -k, --key= - url to get the public key.
# | arg: -n, --name= - Name for the files for this repo, $app as default value.
#
# Requires YunoHost version 3.8.1 or higher.
ynh_install_extra_app_dependencies () {
# Declare an array to define the options of this helper.
local legacy_args=rpkn
declare -Ar args_array=( [r]=repo= [p]=package= [k]=key= [n]=name= )
local repo
local package
local key
local name
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
name="${name:-$app}"
key=${key:-}
# Declare an array to define the options of this helper.
local legacy_args=rpkn
local -A args_array=( [r]=repo= [p]=package= [k]=key= [n]=name= )
local repo
local package
local key
local name
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
name="${name:-$app}"
key=${key:-}
# Set a key only if asked
if [ -n "$key" ]
then
key="--key=$key"
fi
# Add an extra repository for those packages
ynh_install_extra_repo --repo="$repo" $key --priority=995 --name=$name
# Set a key only if asked
if [ -n "$key" ]
then
key="--key=$key"
fi
# Add an extra repository for those packages
ynh_install_extra_repo --repo="$repo" $key --priority=995 --name=$name
# Install requested dependencies from this extra repository.
ynh_add_app_dependencies --package="$package"
# Install requested dependencies from this extra repository.
ynh_add_app_dependencies --package="$package"
# Remove this extra repository after packages are installed
ynh_remove_extra_repo --name=$app
# Remove this extra repository after packages are installed
ynh_remove_extra_repo --name=$app
}
# Add an extra repository correctly, pin it and get the key.
@ -371,72 +375,74 @@ ynh_install_extra_app_dependencies () {
# [internal]
#
# usage: ynh_install_extra_repo --repo="repo" [--key=key_url] [--priority=priority_value] [--name=name] [--append]
# | arg: -r, --repo - Complete url of the extra repository.
# | arg: -k, --key - url to get the public key.
# | arg: -p, --priority - Priority for the pin
# | arg: -n, --name - Name for the files for this repo, $app as default value.
# | arg: -a, --append - Do not overwrite existing files.
# | arg: -r, --repo= - Complete url of the extra repository.
# | arg: -k, --key= - url to get the public key.
# | arg: -p, --priority= - Priority for the pin
# | arg: -n, --name= - Name for the files for this repo, $app as default value.
# | arg: -a, --append - Do not overwrite existing files.
#
# Requires YunoHost version 3.8.1 or higher.
ynh_install_extra_repo () {
# Declare an array to define the options of this helper.
local legacy_args=rkpna
declare -Ar args_array=( [r]=repo= [k]=key= [p]=priority= [n]=name= [a]=append )
local repo
local key
local priority
local name
local append
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
name="${name:-$app}"
append=${append:-0}
key=${key:-}
priority=${priority:-}
# Declare an array to define the options of this helper.
local legacy_args=rkpna
local -A args_array=( [r]=repo= [k]=key= [p]=priority= [n]=name= [a]=append )
local repo
local key
local priority
local name
local append
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
name="${name:-$app}"
append=${append:-0}
key=${key:-}
priority=${priority:-}
if [ $append -eq 1 ]
then
append="--append"
wget_append="tee -a"
else
append=""
wget_append="tee"
fi
if [ $append -eq 1 ]
then
append="--append"
wget_append="tee --append"
else
append=""
wget_append="tee"
fi
# Split the repository into uri, suite and components.
# Remove "deb " at the beginning of the repo.
repo="${repo#deb }"
# Split the repository into uri, suite and components.
# Remove "deb " at the beginning of the repo.
repo="${repo#deb }"
# Get the uri
local uri="$(echo "$repo" | awk '{ print $1 }')"
# Get the uri
local uri="$(echo "$repo" | awk '{ print $1 }')"
# Get the suite
local suite="$(echo "$repo" | awk '{ print $2 }')"
# Get the suite
local suite="$(echo "$repo" | awk '{ print $2 }')"
# Get the components
local component="${repo##$uri $suite }"
# Get the components
local component="${repo##$uri $suite }"
# Add the repository into sources.list.d
ynh_add_repo --uri="$uri" --suite="$suite" --component="$component" --name="$name" $append
# Add the repository into sources.list.d
ynh_add_repo --uri="$uri" --suite="$suite" --component="$component" --name="$name" $append
# Pin the new repo with the default priority, so it won't be used for upgrades.
# Build $pin from the uri without http and any sub path
local pin="${uri#*://}"
pin="${pin%%/*}"
# Set a priority only if asked
if [ -n "$priority" ]
then
priority="--priority=$priority"
fi
ynh_pin_repo --package="*" --pin="origin \"$pin\"" $priority --name="$name" $append
# Pin the new repo with the default priority, so it won't be used for upgrades.
# Build $pin from the uri without http and any sub path
local pin="${uri#*://}"
pin="${pin%%/*}"
# Set a priority only if asked
if [ -n "$priority" ]
then
priority="--priority=$priority"
fi
ynh_pin_repo --package="*" --pin="origin \"$pin\"" $priority --name="$name" $append
# Get the public key for the repo
if [ -n "$key" ]
then
mkdir -p "/etc/apt/trusted.gpg.d"
wget -q "$key" -O - | gpg --dearmor | $wget_append /etc/apt/trusted.gpg.d/$name.gpg > /dev/null
fi
# Get the public key for the repo
if [ -n "$key" ]
then
mkdir --parents "/etc/apt/trusted.gpg.d"
wget --quiet "$key" --output-document=- | gpg --dearmor | $wget_append /etc/apt/trusted.gpg.d/$name.gpg > /dev/null
fi
# Update the list of package with the new repo
ynh_package_update
# Update the list of package with the new repo
ynh_package_update
}
# Remove an extra repository and the assiociated configuration.
@ -444,23 +450,25 @@ ynh_install_extra_repo () {
# [internal]
#
# usage: ynh_remove_extra_repo [--name=name]
# | arg: -n, --name - Name for the files for this repo, $app as default value.
# | arg: -n, --name= - Name for the files for this repo, $app as default value.
#
# Requires YunoHost version 3.8.1 or higher.
ynh_remove_extra_repo () {
# Declare an array to define the options of this helper.
local legacy_args=n
declare -Ar args_array=( [n]=name= )
local name
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
name="${name:-$app}"
# Declare an array to define the options of this helper.
local legacy_args=n
local -A args_array=( [n]=name= )
local name
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
name="${name:-$app}"
ynh_secure_remove "/etc/apt/sources.list.d/$name.list"
ynh_secure_remove "/etc/apt/preferences.d/$name"
ynh_secure_remove "/etc/apt/trusted.gpg.d/$name.gpg"
ynh_secure_remove "/etc/apt/trusted.gpg.d/$name.asc"
ynh_secure_remove "/etc/apt/sources.list.d/$name.list"
ynh_secure_remove "/etc/apt/preferences.d/$name"
ynh_secure_remove "/etc/apt/trusted.gpg.d/$name.gpg"
ynh_secure_remove "/etc/apt/trusted.gpg.d/$name.asc"
# Update the list of package to exclude the old repo
ynh_package_update
# Update the list of package to exclude the old repo
ynh_package_update
}
# Add a repository.
@ -468,41 +476,42 @@ ynh_remove_extra_repo () {
# [internal]
#
# usage: ynh_add_repo --uri=uri --suite=suite --component=component [--name=name] [--append]
# | arg: -u, --uri - Uri of the repository.
# | arg: -s, --suite - Suite of the repository.
# | arg: -c, --component - Component of the repository.
# | arg: -n, --name - Name for the files for this repo, $app as default value.
# | arg: -a, --append - Do not overwrite existing files.
# | arg: -u, --uri= - Uri of the repository.
# | arg: -s, --suite= - Suite of the repository.
# | arg: -c, --component= - Component of the repository.
# | arg: -n, --name= - Name for the files for this repo, $app as default value.
# | arg: -a, --append - Do not overwrite existing files.
#
# Example for a repo like deb http://forge.yunohost.org/debian/ stretch stable
# uri suite component
# ynh_add_repo --uri=http://forge.yunohost.org/debian/ --suite=stretch --component=stable
#
# Requires YunoHost version 3.8.1 or higher.
ynh_add_repo () {
# Declare an array to define the options of this helper.
local legacy_args=uscna
declare -Ar args_array=( [u]=uri= [s]=suite= [c]=component= [n]=name= [a]=append )
local uri
local suite
local component
local name
local append
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
name="${name:-$app}"
append=${append:-0}
# Declare an array to define the options of this helper.
local legacy_args=uscna
local -A args_array=( [u]=uri= [s]=suite= [c]=component= [n]=name= [a]=append )
local uri
local suite
local component
local name
local append
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
name="${name:-$app}"
append=${append:-0}
if [ $append -eq 1 ]
then
append="tee -a"
else
append="tee"
fi
if [ $append -eq 1 ]
then
append="tee --append"
else
append="tee"
fi
mkdir -p "/etc/apt/sources.list.d"
# Add the new repo in sources.list.d
echo "deb $uri $suite $component" \
| $append "/etc/apt/sources.list.d/$name.list"
mkdir --parents "/etc/apt/sources.list.d"
# Add the new repo in sources.list.d
echo "deb $uri $suite $component" \
| $append "/etc/apt/sources.list.d/$name.list"
}
# Pin a repository.
@ -510,41 +519,42 @@ ynh_add_repo () {
# [internal]
#
# usage: ynh_pin_repo --package=packages --pin=pin_filter [--priority=priority_value] [--name=name] [--append]
# | arg: -p, --package - Packages concerned by the pin. Or all, *.
# | arg: -i, --pin - Filter for the pin.
# | arg: -p, --priority - Priority for the pin
# | arg: -n, --name - Name for the files for this repo, $app as default value.
# | arg: -a, --append - Do not overwrite existing files.
# | arg: -p, --package= - Packages concerned by the pin. Or all, *.
# | arg: -i, --pin= - Filter for the pin.
# | arg: -p, --priority= - Priority for the pin
# | arg: -n, --name= - Name for the files for this repo, $app as default value.
# | arg: -a, --append - Do not overwrite existing files.
#
# See https://manpages.debian.org/stretch/apt/apt_preferences.5.en.html#How_APT_Interprets_Priorities for information about pinning.
#
# Requires YunoHost version 3.8.1 or higher.
ynh_pin_repo () {
# Declare an array to define the options of this helper.
local legacy_args=pirna
declare -Ar args_array=( [p]=package= [i]=pin= [r]=priority= [n]=name= [a]=append )
local package
local pin
local priority
local name
local append
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
package="${package:-*}"
priority=${priority:-50}
name="${name:-$app}"
append=${append:-0}
# Declare an array to define the options of this helper.
local legacy_args=pirna
local -A args_array=( [p]=package= [i]=pin= [r]=priority= [n]=name= [a]=append )
local package
local pin
local priority
local name
local append
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
package="${package:-*}"
priority=${priority:-50}
name="${name:-$app}"
append=${append:-0}
if [ $append -eq 1 ]
then
append="tee -a"
else
append="tee"
fi
if [ $append -eq 1 ]
then
append="tee --append"
else
append="tee"
fi
mkdir -p "/etc/apt/preferences.d"
echo "Package: $package
mkdir --parents "/etc/apt/preferences.d"
echo "Package: $package
Pin: $pin
Pin-Priority: $priority
" \
| $append "/etc/apt/preferences.d/$name"
| $append "/etc/apt/preferences.d/$name"
}

View file

@ -4,6 +4,13 @@ CAN_BIND=${CAN_BIND:-1}
# Add a file or a directory to the list of paths to backup
#
# usage: ynh_backup --src_path=src_path [--dest_path=dest_path] [--is_big] [--not_mandatory]
# | arg: -s, --src_path= - file or directory to bind or symlink or copy. it shouldn't be in the backup dir.
# | arg: -d, --dest_path= - destination file or directory inside the backup dir
# | arg: -b, --is_big - Indicate data are big (mail, video, image ...)
# | arg: -m, --not_mandatory - Indicate that if the file is missing, the backup can ignore it.
# | arg: arg - Deprecated arg
#
# This helper can be used both in a system backup hook, and in an app backup script
#
# Details: ynh_backup writes SRC and the relative DEST into a CSV file. And it
@ -11,13 +18,6 @@ CAN_BIND=${CAN_BIND:-1}
#
# If DEST is ended by a slash it complete this path with the basename of SRC.
#
# usage: ynh_backup --src_path=src_path [--dest_path=dest_path] [--is_big] [--not_mandatory]
# | arg: -s, --src_path - file or directory to bind or symlink or copy. it shouldn't be in the backup dir.
# | arg: -d, --dest_path - destination file or directory inside the backup dir
# | arg: -b, --is_big - Indicate data are big (mail, video, image ...)
# | arg: -m, --not_mandatory - Indicate that if the file is missing, the backup can ignore it.
# | arg: arg - Deprecated arg
#
# Example in the context of a wordpress app
#
# ynh_backup "/etc/nginx/conf.d/$domain.d/$app.conf"
@ -41,21 +41,22 @@ CAN_BIND=${CAN_BIND:-1}
# # => "/etc/nginx/conf.d/$domain.d/$app.conf","apps/wordpress/conf/$app.conf"
#
# Requires YunoHost version 2.4.0 or higher.
# Requires YunoHost version 3.5.0 or higher for the argument --not_mandatory
ynh_backup() {
# TODO find a way to avoid injection by file strange naming !
# Declare an array to define the options of this helper.
local legacy_args=sdbm
declare -Ar args_array=( [s]=src_path= [d]=dest_path= [b]=is_big [m]=not_mandatory )
local -A args_array=( [s]=src_path= [d]=dest_path= [b]=is_big [m]=not_mandatory )
local src_path
local dest_path
local is_big
local not_mandatory
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local dest_path="${dest_path:-}"
local is_big="${is_big:-0}"
local not_mandatory="${not_mandatory:-0}"
dest_path="${dest_path:-}"
is_big="${is_big:-0}"
not_mandatory="${not_mandatory:-0}"
BACKUP_CORE_ONLY=${BACKUP_CORE_ONLY:-0}
test -n "${app:-}" && do_not_backup_data=$(ynh_app_setting_get --app=$app --key=do_not_backup_data)
@ -64,7 +65,8 @@ ynh_backup() {
# don't backup big data items
if [ $is_big -eq 1 ] && ( [ ${do_not_backup_data:-0} -eq 1 ] || [ $BACKUP_CORE_ONLY -eq 1 ] )
then
if [ $BACKUP_CORE_ONLY -eq 1 ]; then
if [ $BACKUP_CORE_ONLY -eq 1 ]
then
ynh_print_warn --message="$src_path will not be saved, because 'BACKUP_CORE_ONLY' is set."
else
ynh_print_warn --message="$src_path will not be saved, because 'do_not_backup_data' is set."
@ -76,22 +78,23 @@ ynh_backup() {
# Format correctly source and destination paths
# ==============================================================================
# Be sure the source path is not empty
[[ -e "${src_path}" ]] || {
if [ ! -e "$src_path" ]
then
ynh_print_warn --message="Source path '${src_path}' does not exist"
if [ "$not_mandatory" == "0" ]
then
# This is a temporary fix for fail2ban config files missing after the migration to stretch.
if echo "${src_path}" | grep --quiet "/etc/fail2ban"
then
touch "${src_path}"
ynh_print_info --message="The missing file will be replaced by a dummy one for the backup !!!"
else
return 1
fi
# This is a temporary fix for fail2ban config files missing after the migration to stretch.
if echo "${src_path}" | grep --quiet "/etc/fail2ban"
then
touch "${src_path}"
ynh_print_info --message="The missing file will be replaced by a dummy one for the backup !!!"
else
return 1
fi
else
return 0
return 0
fi
}
fi
# Transform the source path as an absolute path
# If it's a dir remove the ending /
@ -100,12 +103,13 @@ ynh_backup() {
# If there is no destination path, initialize it with the source path
# relative to "/".
# eg: src_path=/etc/yunohost -> dest_path=etc/yunohost
if [[ -z "$dest_path" ]]; then
if [[ -z "$dest_path" ]]
then
dest_path="${src_path#/}"
else
if [[ "${dest_path:0:1}" == "/" ]]; then
if [[ "${dest_path:0:1}" == "/" ]]
then
# If the destination path is an absolute path, transform it as a path
# relative to the current working directory ($YNH_CWD)
@ -117,20 +121,23 @@ ynh_backup() {
dest_path="${dest_path#$YNH_CWD/}"
# Case where $2 is an absolute dir but doesn't begin with $YNH_CWD
[[ "${dest_path:0:1}" == "/" ]] \
&& dest_path="${dest_path#/}"
if [[ "${dest_path:0:1}" == "/" ]]; then
dest_path="${dest_path#/}"
fi
fi
# Complete dest_path if ended by a /
[[ "${dest_path: -1}" == "/" ]] \
&& dest_path="${dest_path}/$(basename $src_path)"
if [[ "${dest_path: -1}" == "/" ]]; then
dest_path="${dest_path}/$(basename $src_path)"
fi
fi
# Check if dest_path already exists in tmp archive
[[ ! -e "${dest_path}" ]] || {
if [[ -e "${dest_path}" ]]
then
ynh_print_err --message="Destination path '${dest_path}' already exist"
return 1
}
fi
# Add the relative current working directory to the destination path
local rel_dir="${YNH_CWD#$YNH_BACKUP_DIR}"
@ -142,15 +149,15 @@ ynh_backup() {
# ==============================================================================
# Write file to backup into backup_list
# ==============================================================================
local src=$(echo "${src_path}" | sed -r 's/"/\"\"/g')
local dest=$(echo "${dest_path}" | sed -r 's/"/\"\"/g')
local src=$(echo "${src_path}" | sed --regexp-extended 's/"/\"\"/g')
local dest=$(echo "${dest_path}" | sed --regexp-extended 's/"/\"\"/g')
echo "\"${src}\",\"${dest}\"" >> "${YNH_BACKUP_CSV}"
# ==============================================================================
# Create the parent dir of the destination path
# It's for retro compatibility, some script consider ynh_backup creates this dir
mkdir -p $(dirname "$YNH_BACKUP_DIR/${dest_path}")
mkdir --parents $(dirname "$YNH_BACKUP_DIR/${dest_path}")
}
# Restore all files that were previously backuped in a core backup script or app backup script
@ -164,10 +171,11 @@ ynh_restore () {
REL_DIR="${REL_DIR%/}/"
# For each destination path begining by $REL_DIR
cat ${YNH_BACKUP_CSV} | tr -d $'\r' | grep -ohP "^\".*\",\"$REL_DIR.*\"$" | \
while read line; do
local ORIGIN_PATH=$(echo "$line" | grep -ohP "^\"\K.*(?=\",\".*\"$)")
local ARCHIVE_PATH=$(echo "$line" | grep -ohP "^\".*\",\"$REL_DIR\K.*(?=\"$)")
cat ${YNH_BACKUP_CSV} | tr --delete $'\r' | grep --only-matching --no-filename --perl-regexp "^\".*\",\"$REL_DIR.*\"$" | \
while read line
do
local ORIGIN_PATH=$(echo "$line" | grep --only-matching --no-filename --perl-regexp "^\"\K.*(?=\",\".*\"$)")
local ARCHIVE_PATH=$(echo "$line" | grep --only-matching --no-filename --perl-regexp "^\".*\",\"$REL_DIR\K.*(?=\"$)")
ynh_restore_file --origin_path="$ARCHIVE_PATH" --dest_path="$ORIGIN_PATH"
done
}
@ -199,9 +207,9 @@ with open(sys.argv[1], 'r') as backup_file:
# the right place.
#
# usage: ynh_restore_file --origin_path=origin_path [--dest_path=dest_path] [--not_mandatory]
# | arg: -o, --origin_path - Path where was located the file or the directory before to be backuped or relative path to $YNH_CWD where it is located in the backup archive
# | arg: -d, --dest_path - Path where restore the file or the dir, if unspecified, the destination will be ORIGIN_PATH or if the ORIGIN_PATH doesn't exist in the archive, the destination will be searched into backup.csv
# | arg: -m, --not_mandatory - Indicate that if the file is missing, the restore process can ignore it.
# | arg: -o, --origin_path= - Path where was located the file or the directory before to be backuped or relative path to $YNH_CWD where it is located in the backup archive
# | arg: -d, --dest_path= - Path where restore the file or the dir, if unspecified, the destination will be ORIGIN_PATH or if the ORIGIN_PATH doesn't exist in the archive, the destination will be searched into backup.csv
# | arg: -m, --not_mandatory - Indicate that if the file is missing, the restore process can ignore it.
#
# examples:
# ynh_restore_file "/etc/nginx/conf.d/$domain.d/$app.conf"
@ -217,24 +225,25 @@ with open(sys.argv[1], 'r') as backup_file:
# /etc/nginx/conf.d/$domain.d/$app.conf
#
# Requires YunoHost version 2.6.4 or higher.
# Requires YunoHost version 3.5.0 or higher for the argument --not_mandatory
ynh_restore_file () {
# Declare an array to define the options of this helper.
local legacy_args=odm
declare -Ar args_array=( [o]=origin_path= [d]=dest_path= [m]=not_mandatory )
local -A args_array=( [o]=origin_path= [d]=dest_path= [m]=not_mandatory )
local origin_path
local archive_path
local dest_path
local not_mandatory
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local origin_path="/${origin_path#/}"
local archive_path="$YNH_CWD${origin_path}"
origin_path="/${origin_path#/}"
# Default value for dest_path = /$origin_path
local dest_path="${dest_path:-$origin_path}"
local not_mandatory="${not_mandatory:-0}"
dest_path="${dest_path:-$origin_path}"
not_mandatory="${not_mandatory:-0}"
local archive_path="$YNH_CWD${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
if [ ! -d "$archive_path" ] && [ ! -f "$archive_path" ] && [ ! -L "$archive_path" ]
then
if [ "$not_mandatory" == "0" ]
then
archive_path="$YNH_BACKUP_DIR/$(_get_archive_path \"$origin_path\")"
@ -247,10 +256,10 @@ ynh_restore_file () {
if [[ -e "${dest_path}" ]]
then
# Check if the file/dir size is less than 500 Mo
if [[ $(du -sb ${dest_path} | cut -d"/" -f1) -le "500000000" ]]
if [[ $(du --summarize --bytes ${dest_path} | cut --delimiter="/" --fields=1) -le "500000000" ]]
then
local backup_file="/home/yunohost.conf/backup/${dest_path}.backup.$(date '+%Y%m%d.%H%M%S')"
mkdir -p "$(dirname "$backup_file")"
mkdir --parents "$(dirname "$backup_file")"
mv "${dest_path}" "$backup_file" # Move the current file or directory
else
ynh_secure_remove --file=${dest_path}
@ -258,15 +267,17 @@ ynh_restore_file () {
fi
# Restore origin_path into dest_path
mkdir -p $(dirname "$dest_path")
mkdir --parents $(dirname "$dest_path")
# Do a copy if it's just a mounting point
if mountpoint -q $YNH_BACKUP_DIR; then
if [[ -d "${archive_path}" ]]; then
if mountpoint --quiet $YNH_BACKUP_DIR
then
if [[ -d "${archive_path}" ]]
then
archive_path="${archive_path}/."
mkdir -p "$dest_path"
mkdir --parents "$dest_path"
fi
cp -a "$archive_path" "${dest_path}"
cp --archive "$archive_path" "${dest_path}"
# Do a move if YNH_BACKUP_DIR is already a copy
else
mv "$archive_path" "${dest_path}"
@ -287,22 +298,22 @@ ynh_bind_or_cp() {
# Calculate and store a file checksum into the app settings
#
# $app should be defined when calling this helper
#
# usage: ynh_store_file_checksum --file=file
# | arg: -f, --file - The file on which the checksum will performed, then stored.
# | arg: -f, --file= - The file on which the checksum will performed, then stored.
#
# $app should be defined when calling this helper
#
# Requires YunoHost version 2.6.4 or higher.
ynh_store_file_checksum () {
# Declare an array to define the options of this helper.
local legacy_args=f
declare -Ar args_array=( [f]=file= )
local -A args_array=( [f]=file= )
local file
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local checksum_setting_name=checksum_${file//[\/ ]/_} # Replace all '/' and ' ' by '_'
ynh_app_setting_set --app=$app --key=$checksum_setting_name --value=$(md5sum "$file" | cut -d' ' -f1)
ynh_app_setting_set --app=$app --key=$checksum_setting_name --value=$(md5sum "$file" | cut --delimiter=' ' --fields=1)
# If backup_file_checksum isn't empty, ynh_backup_if_checksum_is_different has made a backup
if [ -n "${backup_file_checksum-}" ]
@ -321,14 +332,14 @@ ynh_store_file_checksum () {
# modified config files.
#
# usage: ynh_backup_if_checksum_is_different --file=file
# | arg: -f, --file - The file on which the checksum test will be perfomed.
# | arg: -f, --file= - The file on which the checksum test will be perfomed.
# | ret: the name of a backup file, or nothing
#
# Requires YunoHost version 2.6.4 or higher.
ynh_backup_if_checksum_is_different () {
# Declare an array to define the options of this helper.
local legacy_args=f
declare -Ar args_array=( [f]=file= )
local -A args_array=( [f]=file= )
local file
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
@ -339,11 +350,11 @@ ynh_backup_if_checksum_is_different () {
backup_file_checksum=""
if [ -n "$checksum_value" ]
then # Proceed only if a value was stored into the app settings
if [ -e $file ] && ! echo "$checksum_value $file" | md5sum -c --status
if [ -e $file ] && ! echo "$checksum_value $file" | md5sum --check --status
then # If the checksum is now different
backup_file_checksum="/home/yunohost.conf/backup/$file.backup.$(date '+%Y%m%d.%H%M%S')"
mkdir -p "$(dirname "$backup_file_checksum")"
cp -a "$file" "$backup_file_checksum" # Backup the current file
mkdir --parents "$(dirname "$backup_file_checksum")"
cp --archive "$file" "$backup_file_checksum" # Backup the current file
ynh_print_warn "File $file has been manually modified since the installation or last upgrade. So it has been duplicated in $backup_file_checksum"
echo "$backup_file_checksum" # Return the name of the backup file
fi
@ -352,16 +363,16 @@ ynh_backup_if_checksum_is_different () {
# Delete a file checksum from the app settings
#
# $app should be defined when calling this helper
# usage: ynh_delete_file_checksum --file=file
# | arg: -f, --file= - The file for which the checksum will be deleted
#
# usage: ynh_remove_file_checksum file
# | arg: -f, --file= - The file for which the checksum will be deleted
# $app should be defined when calling this helper
#
# Requires YunoHost version 3.3.1 or higher.
ynh_delete_file_checksum () {
# Declare an array to define the options of this helper.
local legacy_args=f
declare -Ar args_array=( [f]=file= )
local -A args_array=( [f]=file= )
local file
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
@ -373,11 +384,11 @@ ynh_delete_file_checksum () {
# Make a backup in case of failed upgrade
#
# usage:
# ynh_backup_before_upgrade
# ynh_clean_setup () {
# ynh_restore_upgradebackup
# }
# ynh_abort_if_errors
# ynh_backup_before_upgrade
# ynh_clean_setup () {
# ynh_restore_upgradebackup
# }
# ynh_abort_if_errors
#
# Requires YunoHost version 2.7.2 or higher.
ynh_backup_before_upgrade () {
@ -394,7 +405,7 @@ ynh_backup_before_upgrade () {
if [ "$NO_BACKUP_UPGRADE" -eq 0 ]
then
# Check if a backup already exists with the prefix 1
if yunohost backup list | grep -q $app_bck-pre-upgrade1
if yunohost backup list | grep --quiet $app_bck-pre-upgrade1
then
# Prefix becomes 2 to preserve the previous backup
backup_number=2
@ -406,7 +417,7 @@ ynh_backup_before_upgrade () {
if [ "$?" -eq 0 ]
then
# If the backup succeeded, remove the previous backup
if yunohost backup list | grep -q $app_bck-pre-upgrade$old_backup_number
if yunohost backup list | grep --quiet $app_bck-pre-upgrade$old_backup_number
then
# Remove the previous backup only if it exists
yunohost backup delete $app_bck-pre-upgrade$old_backup_number > /dev/null
@ -422,11 +433,11 @@ ynh_backup_before_upgrade () {
# Restore a previous backup if the upgrade process failed
#
# usage:
# ynh_backup_before_upgrade
# ynh_clean_setup () {
# ynh_restore_upgradebackup
# }
# ynh_abort_if_errors
# ynh_backup_before_upgrade
# ynh_clean_setup () {
# ynh_restore_upgradebackup
# }
# ynh_abort_if_errors
#
# Requires YunoHost version 2.7.2 or higher.
ynh_restore_upgradebackup () {
@ -438,7 +449,7 @@ ynh_restore_upgradebackup () {
if [ "$NO_BACKUP_UPGRADE" -eq 0 ]
then
# Check if an existing backup can be found before removing and restoring the application.
if yunohost backup list | grep -q $app_bck-pre-upgrade$backup_number
if yunohost backup list | grep --quiet $app_bck-pre-upgrade$backup_number
then
# Remove the application then restore it
yunohost app remove $app

View file

@ -63,52 +63,54 @@
#
# Requires YunoHost version 3.5.0 or higher.
ynh_add_fail2ban_config () {
# Declare an array to define the options of this helper.
local legacy_args=lrmptv
declare -Ar args_array=( [l]=logpath= [r]=failregex= [m]=max_retry= [p]=ports= [t]=use_template [v]=others_var=)
local logpath
local failregex
local max_retry
local ports
local others_var
local use_template
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
use_template="${use_template:-0}"
max_retry=${max_retry:-3}
ports=${ports:-http,https}
# Declare an array to define the options of this helper.
local legacy_args=lrmptv
local -A args_array=( [l]=logpath= [r]=failregex= [m]=max_retry= [p]=ports= [t]=use_template [v]=others_var=)
local logpath
local failregex
local max_retry
local ports
local others_var
local use_template
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
max_retry=${max_retry:-3}
ports=${ports:-http,https}
others_var=${others_var:-}
use_template="${use_template:-0}"
finalfail2banjailconf="/etc/fail2ban/jail.d/$app.conf"
finalfail2banfilterconf="/etc/fail2ban/filter.d/$app.conf"
ynh_backup_if_checksum_is_different "$finalfail2banjailconf"
ynh_backup_if_checksum_is_different "$finalfail2banfilterconf"
finalfail2banjailconf="/etc/fail2ban/jail.d/$app.conf"
finalfail2banfilterconf="/etc/fail2ban/filter.d/$app.conf"
ynh_backup_if_checksum_is_different "$finalfail2banjailconf"
ynh_backup_if_checksum_is_different "$finalfail2banfilterconf"
if [ $use_template -eq 1 ]
then
# Usage 2, templates
cp ../conf/f2b_jail.conf $finalfail2banjailconf
cp ../conf/f2b_filter.conf $finalfail2banfilterconf
if [ -n "${app:-}" ]
if [ $use_template -eq 1 ]
then
ynh_replace_string "__APP__" "$app" "$finalfail2banjailconf"
ynh_replace_string "__APP__" "$app" "$finalfail2banfilterconf"
fi
# Usage 2, templates
cp ../conf/f2b_jail.conf $finalfail2banjailconf
cp ../conf/f2b_filter.conf $finalfail2banfilterconf
# Replace all other variable given as arguments
for var_to_replace in ${others_var:-}; do
# ${var_to_replace^^} make the content of the variable on upper-cases
# ${!var_to_replace} get the content of the variable named $var_to_replace
ynh_replace_string --match_string="__${var_to_replace^^}__" --replace_string="${!var_to_replace}" --target_file="$finalfail2banjailconf"
ynh_replace_string --match_string="__${var_to_replace^^}__" --replace_string="${!var_to_replace}" --target_file="$finalfail2banfilterconf"
done
if [ -n "${app:-}" ]
then
ynh_replace_string "__APP__" "$app" "$finalfail2banjailconf"
ynh_replace_string "__APP__" "$app" "$finalfail2banfilterconf"
fi
else
# Usage 1, no template. Build a config file from scratch.
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."
# Replace all other variable given as arguments
for var_to_replace in $others_var
do
# ${var_to_replace^^} make the content of the variable on upper-cases
# ${!var_to_replace} get the content of the variable named $var_to_replace
ynh_replace_string --match_string="__${var_to_replace^^}__" --replace_string="${!var_to_replace}" --target_file="$finalfail2banjailconf"
ynh_replace_string --match_string="__${var_to_replace^^}__" --replace_string="${!var_to_replace}" --target_file="$finalfail2banfilterconf"
done
tee $finalfail2banjailconf <<EOF
else
# Usage 1, no template. Build a config file from scratch.
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."
tee $finalfail2banjailconf <<EOF
[$app]
enabled = true
port = $ports
@ -124,19 +126,20 @@ before = common.conf
failregex = $failregex
ignoreregex =
EOF
fi
fi
# Common to usage 1 and 2.
ynh_store_file_checksum "$finalfail2banjailconf"
ynh_store_file_checksum "$finalfail2banfilterconf"
# Common to usage 1 and 2.
ynh_store_file_checksum "$finalfail2banjailconf"
ynh_store_file_checksum "$finalfail2banfilterconf"
ynh_systemd_action --service_name=fail2ban --action=reload
ynh_systemd_action --service_name=fail2ban --action=reload --line_match="(Started|Reloaded) Fail2Ban Service" --log_path=systemd
local fail2ban_error="$(journalctl -u fail2ban | tail -n50 | grep "WARNING.*$app.*")"
if [[ -n "$fail2ban_error" ]]; then
ynh_print_err --message="Fail2ban failed to load the jail for $app"
ynh_print_warn --message="${fail2ban_error#*WARNING}"
fi
local fail2ban_error="$(journalctl --unit=fail2ban | tail --lines=50 | grep "WARNING.*$app.*")"
if [[ -n "$fail2ban_error" ]]
then
ynh_print_err --message="Fail2ban failed to load the jail for $app"
ynh_print_warn --message="${fail2ban_error#*WARNING}"
fi
}
# Remove the dedicated fail2ban config (jail and filter conf files)
@ -145,7 +148,7 @@ EOF
#
# Requires YunoHost version 3.5.0 or higher.
ynh_remove_fail2ban_config () {
ynh_secure_remove "/etc/fail2ban/jail.d/$app.conf"
ynh_secure_remove "/etc/fail2ban/filter.d/$app.conf"
ynh_systemd_action --service_name=fail2ban --action=reload
ynh_secure_remove "/etc/fail2ban/jail.d/$app.conf"
ynh_secure_remove "/etc/fail2ban/filter.d/$app.conf"
ynh_systemd_action --service_name=fail2ban --action=reload
}

View file

@ -6,7 +6,7 @@
#
# example: function my_helper()
# {
# declare -Ar args_array=( [a]=arg1= [b]=arg2= [c]=arg3 )
# local -A args_array=( [a]=arg1= [b]=arg2= [c]=arg3 )
# local arg1
# local arg2
# local arg3
@ -22,13 +22,13 @@
# This helper need an array, named "args_array" with all the arguments used by the helper
# that want to use ynh_handle_getopts_args
# Be carreful, this array has to be an associative array, as the following example:
# declare -Ar args_array=( [a]=arg1 [b]=arg2= [c]=arg3 )
# local -A args_array=( [a]=arg1 [b]=arg2= [c]=arg3 )
# Let's explain this array:
# a, b and c are short options, -a, -b and -c
# arg1, arg2 and arg3 are the long options associated to the previous short ones. --arg1, --arg2 and --arg3
# For each option, a short and long version has to be defined.
# Let's see something more significant
# declare -Ar args_array=( [u]=user [f]=finalpath= [d]=database )
# local -A args_array=( [u]=user [f]=finalpath= [d]=database )
#
# NB: Because we're using 'declare' without -g, the array will be declared as a local variable.
#
@ -46,107 +46,108 @@
#
# Requires YunoHost version 3.2.2 or higher.
ynh_handle_getopts_args () {
# Manage arguments only if there's some provided
set +x
if [ $# -ne 0 ]
then
# Store arguments in an array to keep each argument separated
local arguments=("$@")
# Manage arguments only if there's some provided
set +o xtrace # set +x
if [ $# -ne 0 ]
then
# Store arguments in an array to keep each argument separated
local arguments=("$@")
# For each option in the array, reduce to short options for getopts (e.g. for [u]=user, --user will be -u)
# And built parameters string for getopts
# ${!args_array[@]} is the list of all option_flags in the array (An option_flag is 'u' in [u]=user, user is a value)
local getopts_parameters=""
local option_flag=""
for option_flag in "${!args_array[@]}"
do
# Concatenate each option_flags of the array to build the string of arguments for getopts
# Will looks like 'abcd' for -a -b -c -d
# If the value of an option_flag finish by =, it's an option with additionnal values. (e.g. --user bob or -u bob)
# Check the last character of the value associate to the option_flag
if [ "${args_array[$option_flag]: -1}" = "=" ]
then
# For an option with additionnal values, add a ':' after the letter for getopts.
getopts_parameters="${getopts_parameters}${option_flag}:"
else
getopts_parameters="${getopts_parameters}${option_flag}"
fi
# Check each argument given to the function
local arg=""
# ${#arguments[@]} is the size of the array
for arg in `seq 0 $(( ${#arguments[@]} - 1 ))`
do
# Escape options' values starting with -. Otherwise the - will be considered as another option.
arguments[arg]="${arguments[arg]//--${args_array[$option_flag]}-/--${args_array[$option_flag]}\\TOBEREMOVED\\-}"
# And replace long option (value of the option_flag) by the short option, the option_flag itself
# (e.g. for [u]=user, --user will be -u)
# Replace long option with =
arguments[arg]="${arguments[arg]//--${args_array[$option_flag]}/-${option_flag} }"
# And long option without =
arguments[arg]="${arguments[arg]//--${args_array[$option_flag]%=}/-${option_flag}}"
done
done
# For each option in the array, reduce to short options for getopts (e.g. for [u]=user, --user will be -u)
# And built parameters string for getopts
# ${!args_array[@]} is the list of all option_flags in the array (An option_flag is 'u' in [u]=user, user is a value)
local getopts_parameters=""
local option_flag=""
for option_flag in "${!args_array[@]}"
do
# Concatenate each option_flags of the array to build the string of arguments for getopts
# Will looks like 'abcd' for -a -b -c -d
# If the value of an option_flag finish by =, it's an option with additionnal values. (e.g. --user bob or -u bob)
# Check the last character of the value associate to the option_flag
if [ "${args_array[$option_flag]: -1}" = "=" ]
then
# For an option with additionnal values, add a ':' after the letter for getopts.
getopts_parameters="${getopts_parameters}${option_flag}:"
else
getopts_parameters="${getopts_parameters}${option_flag}"
fi
# Check each argument given to the function
local arg=""
# ${#arguments[@]} is the size of the array
for arg in `seq 0 $(( ${#arguments[@]} - 1 ))`
do
# Escape options' values starting with -. Otherwise the - will be considered as another option.
arguments[arg]="${arguments[arg]//--${args_array[$option_flag]}-/--${args_array[$option_flag]}\\TOBEREMOVED\\-}"
# And replace long option (value of the option_flag) by the short option, the option_flag itself
# (e.g. for [u]=user, --user will be -u)
# Replace long option with =
arguments[arg]="${arguments[arg]//--${args_array[$option_flag]}/-${option_flag} }"
# And long option without =
arguments[arg]="${arguments[arg]//--${args_array[$option_flag]%=}/-${option_flag}}"
done
done
# Read and parse all the arguments
# Use a function here, to use standart arguments $@ and be able to use shift.
parse_arg () {
# Read all arguments, until no arguments are left
while [ $# -ne 0 ]
do
# Initialize the index of getopts
OPTIND=1
# Parse with getopts only if the argument begin by -, that means the argument is an option
# getopts will fill $parameter with the letter of the option it has read.
local parameter=""
getopts ":$getopts_parameters" parameter || true
# Read and parse all the arguments
# Use a function here, to use standart arguments $@ and be able to use shift.
parse_arg () {
# Read all arguments, until no arguments are left
while [ $# -ne 0 ]
do
# Initialize the index of getopts
OPTIND=1
# Parse with getopts only if the argument begin by -, that means the argument is an option
# getopts will fill $parameter with the letter of the option it has read.
local parameter=""
getopts ":$getopts_parameters" parameter || true
if [ "$parameter" = "?" ]
then
ynh_die --message="Invalid argument: -${OPTARG:-}"
elif [ "$parameter" = ":" ]
then
ynh_die --message="-$OPTARG parameter requires an argument."
else
local shift_value=1
# Use the long option, corresponding to the short option read by getopts, as a variable
# (e.g. for [u]=user, 'user' will be used as a variable)
# Also, remove '=' at the end of the long option
# The variable name will be stored in 'option_var'
local option_var="${args_array[$parameter]%=}"
# If this option doesn't take values
# if there's a '=' at the end of the long option name, this option takes values
if [ "${args_array[$parameter]: -1}" != "=" ]
then
# 'eval ${option_var}' will use the content of 'option_var'
eval ${option_var}=1
else
# Read all other arguments to find multiple value for this option.
# Load args in a array
local all_args=("$@")
if [ "$parameter" = "?" ]
then
ynh_die --message="Invalid argument: -${OPTARG:-}"
elif [ "$parameter" = ":" ]
then
ynh_die --message="-$OPTARG parameter requires an argument."
else
local shift_value=1
# Use the long option, corresponding to the short option read by getopts, as a variable
# (e.g. for [u]=user, 'user' will be used as a variable)
# Also, remove '=' at the end of the long option
# The variable name will be stored in 'option_var'
local option_var="${args_array[$parameter]%=}"
# If this option doesn't take values
# if there's a '=' at the end of the long option name, this option takes values
if [ "${args_array[$parameter]: -1}" != "=" ]
then
# 'eval ${option_var}' will use the content of 'option_var'
eval ${option_var}=1
else
# Read all other arguments to find multiple value for this option.
# Load args in a array
local all_args=("$@")
# If the first argument is longer than 2 characters,
# There's a value attached to the option, in the same array cell
if [ ${#all_args[0]} -gt 2 ]; then
# Remove the option and the space, so keep only the value itself.
all_args[0]="${all_args[0]#-${parameter} }"
# Reduce the value of shift, because the option has been removed manually
shift_value=$(( shift_value - 1 ))
fi
# If the first argument is longer than 2 characters,
# There's a value attached to the option, in the same array cell
if [ ${#all_args[0]} -gt 2 ]
then
# Remove the option and the space, so keep only the value itself.
all_args[0]="${all_args[0]#-${parameter} }"
# Reduce the value of shift, because the option has been removed manually
shift_value=$(( shift_value - 1 ))
fi
# Declare the content of option_var as a variable.
eval ${option_var}=""
# Then read the array value per value
local i
for i in `seq 0 $(( ${#all_args[@]} - 1 ))`
do
# If this argument is an option, end here.
if [ "${all_args[$i]:0:1}" == "-" ]
then
# Ignore the first value of the array, which is the option itself
if [ "$i" -ne 0 ]; then
break
fi
else
# Declare the content of option_var as a variable.
eval ${option_var}=""
# Then read the array value per value
local i
for i in `seq 0 $(( ${#all_args[@]} - 1 ))`
do
# If this argument is an option, end here.
if [ "${all_args[$i]:0:1}" == "-" ]
then
# Ignore the first value of the array, which is the option itself
if [ "$i" -ne 0 ]; then
break
fi
else
# Ignore empty parameters
if [ -n "${all_args[$i]}" ]
then
@ -171,52 +172,53 @@ ynh_handle_getopts_args () {
eval ${option_var}+='"${all_args[$i]}"'
fi
shift_value=$(( shift_value + 1 ))
fi
done
fi
fi
fi
done
fi
fi
# Shift the parameter and its argument(s)
shift $shift_value
done
}
# Shift the parameter and its argument(s)
shift $shift_value
done
}
# LEGACY MODE
# Check if there's getopts arguments
if [ "${arguments[0]:0:1}" != "-" ]
then
# If not, enter in legacy mode and manage the arguments as positionnal ones..
# Dot not echo, to prevent to go through a helper output. But print only in the log.
set -x; echo "! Helper used in legacy mode !" > /dev/null; set +x
local i
for i in `seq 0 $(( ${#arguments[@]} -1 ))`
do
# Try to use legacy_args as a list of option_flag of the array args_array
# Otherwise, fallback to getopts_parameters to get the option_flag. But an associative arrays isn't always sorted in the correct order...
# Remove all ':' in getopts_parameters
getopts_parameters=${legacy_args:-${getopts_parameters//:}}
# Get the option_flag from getopts_parameters, by using the option_flag according to the position of the argument.
option_flag=${getopts_parameters:$i:1}
if [ -z "$option_flag" ]; then
ynh_print_warn --message="Too many arguments ! \"${arguments[$i]}\" will be ignored."
continue
fi
# Use the long option, corresponding to the option_flag, as a variable
# (e.g. for [u]=user, 'user' will be used as a variable)
# Also, remove '=' at the end of the long option
# The variable name will be stored in 'option_var'
local option_var="${args_array[$option_flag]%=}"
# LEGACY MODE
# Check if there's getopts arguments
if [ "${arguments[0]:0:1}" != "-" ]
then
# If not, enter in legacy mode and manage the arguments as positionnal ones..
# Dot not echo, to prevent to go through a helper output. But print only in the log.
set -x; echo "! Helper used in legacy mode !" > /dev/null; set +x
local i
for i in `seq 0 $(( ${#arguments[@]} -1 ))`
do
# Try to use legacy_args as a list of option_flag of the array args_array
# Otherwise, fallback to getopts_parameters to get the option_flag. But an associative arrays isn't always sorted in the correct order...
# Remove all ':' in getopts_parameters
getopts_parameters=${legacy_args:-${getopts_parameters//:}}
# Get the option_flag from getopts_parameters, by using the option_flag according to the position of the argument.
option_flag=${getopts_parameters:$i:1}
if [ -z "$option_flag" ]
then
ynh_print_warn --message="Too many arguments ! \"${arguments[$i]}\" will be ignored."
continue
fi
# Use the long option, corresponding to the option_flag, as a variable
# (e.g. for [u]=user, 'user' will be used as a variable)
# Also, remove '=' at the end of the long option
# The variable name will be stored in 'option_var'
local option_var="${args_array[$option_flag]%=}"
# Store each value given as argument in the corresponding variable
# The values will be stored in the same order than $args_array
eval ${option_var}+='"${arguments[$i]}"'
done
unset legacy_args
else
# END LEGACY MODE
# Call parse_arg and pass the modified list of args as an array of arguments.
parse_arg "${arguments[@]}"
fi
fi
set -x
# Store each value given as argument in the corresponding variable
# The values will be stored in the same order than $args_array
eval ${option_var}+='"${arguments[$i]}"'
done
unset legacy_args
else
# END LEGACY MODE
# Call parse_arg and pass the modified list of args as an array of arguments.
parse_arg "${arguments[@]}"
fi
fi
set -o xtrace # set -x
}

View file

@ -3,63 +3,66 @@
# Get the total or free amount of RAM+swap on the system
#
# usage: ynh_get_ram [--free|--total] [--ignore_swap|--only_swap]
# | arg: -f, --free - Count free RAM+swap
# | arg: -t, --total - Count total RAM+swap
# | arg: -s, --ignore_swap - Ignore swap, consider only real RAM
# | arg: -o, --only_swap - Ignore real RAM, consider only swap
# | arg: -f, --free - Count free RAM+swap
# | arg: -t, --total - Count total RAM+swap
# | arg: -s, --ignore_swap - Ignore swap, consider only real RAM
# | arg: -o, --only_swap - Ignore real RAM, consider only swap
# | ret: the amount of free ram
#
# Requires YunoHost version 3.8.1 or higher.
ynh_get_ram () {
# Declare an array to define the options of this helper.
local legacy_args=ftso
declare -Ar args_array=( [f]=free [t]=total [s]=ignore_swap [o]=only_swap )
local free
local total
local ignore_swap
local only_swap
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
ignore_swap=${ignore_swap:-0}
only_swap=${only_swap:-0}
free=${free:-0}
total=${total:-0}
# Declare an array to define the options of this helper.
local legacy_args=ftso
local -A args_array=( [f]=free [t]=total [s]=ignore_swap [o]=only_swap )
local free
local total
local ignore_swap
local only_swap
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
ignore_swap=${ignore_swap:-0}
only_swap=${only_swap:-0}
free=${free:-0}
total=${total:-0}
local total_ram=$(vmstat --stats --unit M | grep "total memory" | awk '{print $1}')
local total_swap=$(vmstat --stats --unit M | grep "total swap" | awk '{print $1}')
local total_ram_swap=$(( total_ram + total_swap ))
local total_ram=$(vmstat --stats --unit M | grep "total memory" | awk '{print $1}')
local total_swap=$(vmstat --stats --unit M | grep "total swap" | awk '{print $1}')
local total_ram_swap=$(( total_ram + total_swap ))
local free_ram=$(vmstat --stats --unit M | grep "free memory" | awk '{print $1}')
local free_swap=$(vmstat --stats --unit M | grep "free swap" | awk '{print $1}')
local free_ram_swap=$(( free_ram + free_swap ))
local free_ram=$(vmstat --stats --unit M | grep "free memory" | awk '{print $1}')
local free_swap=$(vmstat --stats --unit M | grep "free swap" | awk '{print $1}')
local free_ram_swap=$(( free_ram + free_swap ))
# Use the total amount of ram
if [ $free -eq 1 ]
then
# Use the total amount of free ram
local ram=$free_ram_swap
if [ $ignore_swap -eq 1 ]
then
# Use only the amount of free ram
ram=$free_ram
elif [ $only_swap -eq 1 ]
then
# Use only the amount of free swap
ram=$free_swap
fi
elif [ $total -eq 1 ]
then
local ram=$total_ram_swap
if [ $ignore_swap -eq 1 ]
then
# Use only the amount of free ram
ram=$total_ram
elif [ $only_swap -eq 1 ]
then
# Use only the amount of free swap
ram=$total_swap
fi
else
ynh_print_warn --message="You have to choose --free or --total when using ynh_get_ram"
ram=0
fi
# Use the total amount of ram
if [ $free -eq 1 ]
then
# Use the total amount of free ram
local ram=$free_ram_swap
if [ $ignore_swap -eq 1 ]
then
# Use only the amount of free ram
ram=$free_ram
elif [ $only_swap -eq 1 ]
then
# Use only the amount of free swap
ram=$free_swap
fi
elif [ $total -eq 1 ]
then
local ram=$total_ram_swap
if [ $ignore_swap -eq 1 ]
then
# Use only the amount of free ram
ram=$total_ram
elif [ $only_swap -eq 1 ]
then
# Use only the amount of free swap
ram=$total_swap
fi
else
ynh_print_warn --message="You have to choose --free or --total when using ynh_get_ram"
ram=0
fi
echo $ram
}
@ -67,15 +70,18 @@ ynh_get_ram () {
# Return 0 or 1 depending if the system has a given amount of RAM+swap free or total
#
# usage: ynh_require_ram --required=RAM required in Mb [--free|--total] [--ignore_swap|--only_swap]
# | arg: -r, --required - The amount to require, in Mb
# | arg: -f, --free - Count free RAM+swap
# | arg: -t, --total - Count total RAM+swap
# | arg: -s, --ignore_swap - Ignore swap, consider only real RAM
# | arg: -o, --only_swap - Ignore real RAM, consider only swap
# | arg: -r, --required= - The amount to require, in Mb
# | arg: -f, --free - Count free RAM+swap
# | arg: -t, --total - Count total RAM+swap
# | arg: -s, --ignore_swap - Ignore swap, consider only real RAM
# | arg: -o, --only_swap - Ignore real RAM, consider only swap
# | exit: Return 1 if the ram is under the requirement, 0 otherwise.
#
# Requires YunoHost version 3.8.1 or higher.
ynh_require_ram () {
# Declare an array to define the options of this helper.
local legacy_args=rftso
declare -Ar args_array=( [r]=required= [f]=free [t]=total [s]=ignore_swap [o]=only_swap )
local -A args_array=( [r]=required= [f]=free [t]=total [s]=ignore_swap [o]=only_swap )
local required
local free
local total

View file

@ -3,30 +3,34 @@
# Print a message to stderr and exit
#
# usage: ynh_die --message=MSG [--ret_code=RETCODE]
# | arg: -m, --message= - Message to display
# | arg: -c, --ret_code= - Exit code to exit with
#
# Requires YunoHost version 2.4.0 or higher.
ynh_die() {
# Declare an array to define the options of this helper.
local legacy_args=mc
declare -Ar args_array=( [m]=message= [c]=ret_code= )
local message
local ret_code
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=mc
local -A args_array=( [m]=message= [c]=ret_code= )
local message
local ret_code
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
ret_code=${ret_code:-1}
echo "$message" 1>&2
exit "${ret_code:-1}"
echo "$message" 1>&2
exit "$ret_code"
}
# Display a message in the 'INFO' logging category
#
# usage: ynh_print_info --message="Some message"
# | arg: -m, --message= - Message to display
#
# Requires YunoHost version 3.2.0 or higher.
ynh_print_info() {
# Declare an array to define the options of this helper.
local legacy_args=m
declare -Ar args_array=( [m]=message= )
local -A args_array=( [m]=message= )
local message
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
@ -45,12 +49,12 @@ ynh_print_info() {
#
# Requires YunoHost version 2.6.4 or higher.
ynh_no_log() {
local ynh_cli_log=/var/log/yunohost/yunohost-cli.log
cp -a ${ynh_cli_log} ${ynh_cli_log}-move
eval $@
local exit_code=$?
mv ${ynh_cli_log}-move ${ynh_cli_log}
return $?
local ynh_cli_log=/var/log/yunohost/yunohost-cli.log
cp --archive ${ynh_cli_log} ${ynh_cli_log}-move
eval $@
local exit_code=$?
mv ${ynh_cli_log}-move ${ynh_cli_log}
return $exit_code
}
# Main printer, just in case in the future we have to change anything about that.
@ -59,121 +63,116 @@ ynh_no_log() {
#
# Requires YunoHost version 3.2.0 or higher.
ynh_print_log () {
echo -e "${1}"
echo -e "${1}"
}
# Print a warning on stderr
#
# usage: ynh_print_warn --message="Text to print"
# | arg: -m, --message - The text to print
# | arg: -m, --message= - The text to print
#
# Requires YunoHost version 3.2.0 or higher.
ynh_print_warn () {
# Declare an array to define the options of this helper.
local legacy_args=m
declare -Ar args_array=( [m]=message= )
local message
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=m
local -A args_array=( [m]=message= )
local message
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
ynh_print_log "\e[93m\e[1m[WARN]\e[0m ${message}" >&2
ynh_print_log "\e[93m\e[1m[WARN]\e[0m ${message}" >&2
}
# Print an error on stderr
#
# usage: ynh_print_err --message="Text to print"
# | arg: -m, --message - The text to print
# | arg: -m, --message= - The text to print
#
# Requires YunoHost version 3.2.0 or higher.
ynh_print_err () {
# Declare an array to define the options of this helper.
local legacy_args=m
declare -Ar args_array=( [m]=message= )
local message
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=m
local -A args_array=( [m]=message= )
local message
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
ynh_print_log "\e[91m\e[1m[ERR]\e[0m ${message}" >&2
ynh_print_log "\e[91m\e[1m[ERR]\e[0m ${message}" >&2
}
# Execute a command and print the result as an error
#
# usage: ynh_exec_err your_command
# usage: ynh_exec_err "your_command | other_command"
# | arg: command - command to execute
#
# When using pipes, double quotes are required - otherwise, this helper will run the first command, and the whole output will be sent through the next pipe.
#
# If the command to execute uses double quotes, they have to be escaped or they will be interpreted and removed.
#
# | arg: command - command to execute
#
# Requires YunoHost version 3.2.0 or higher.
ynh_exec_err () {
ynh_print_err "$(eval $@)"
ynh_print_err "$(eval $@)"
}
# Execute a command and print the result as a warning
#
# usage: ynh_exec_warn your_command
# usage: ynh_exec_warn "your_command | other_command"
# | arg: command - command to execute
#
# When using pipes, double quotes are required - otherwise, this helper will run the first command, and the whole output will be sent through the next pipe.
#
# If the command to execute uses double quotes, they have to be escaped or they will be interpreted and removed.
#
# | arg: command - command to execute
#
# Requires YunoHost version 3.2.0 or higher.
ynh_exec_warn () {
ynh_print_warn "$(eval $@)"
ynh_print_warn "$(eval $@)"
}
# Execute a command and force the result to be printed on stdout
#
# usage: ynh_exec_warn_less your_command
# usage: ynh_exec_warn_less "your_command | other_command"
# | arg: command - command to execute
#
# When using pipes, double quotes are required - otherwise, this helper will run the first command, and the whole output will be sent through the next pipe.
#
# If the command to execute uses double quotes, they have to be escaped or they will be interpreted and removed.
#
# | arg: command - command to execute
#
# Requires YunoHost version 3.2.0 or higher.
ynh_exec_warn_less () {
eval $@ 2>&1
eval $@ 2>&1
}
# Execute a command and redirect stdout in /dev/null
#
# usage: ynh_exec_quiet your_command
# usage: ynh_exec_quiet "your_command | other_command"
# | arg: command - command to execute
#
# When using pipes, double quotes are required - otherwise, this helper will run the first command, and the whole output will be sent through the next pipe.
#
# If the command to execute uses double quotes, they have to be escaped or they will be interpreted and removed.
#
# | arg: command - command to execute
#
# Requires YunoHost version 3.2.0 or higher.
ynh_exec_quiet () {
eval $@ > /dev/null
eval $@ > /dev/null
}
# Execute a command and redirect stdout and stderr in /dev/null
#
# usage: ynh_exec_fully_quiet your_command
# usage: ynh_exec_fully_quiet "your_command | other_command"
# | arg: command - command to execute
#
# When using pipes, double quotes are required - otherwise, this helper will run the first command, and the whole output will be sent through the next pipe.
#
# If the command to execute uses double quotes, they have to be escaped or they will be interpreted and removed.
#
# | arg: command - command to execute
#
# Requires YunoHost version 3.2.0 or higher.
ynh_exec_fully_quiet () {
eval $@ > /dev/null 2>&1
eval $@ > /dev/null 2>&1
}
# Remove any logs for all the following commands.
@ -184,7 +183,7 @@ ynh_exec_fully_quiet () {
#
# Requires YunoHost version 3.2.0 or higher.
ynh_print_OFF () {
exec {BASH_XTRACEFD}>/dev/null
exec {BASH_XTRACEFD}>/dev/null
}
# Restore the logging after ynh_print_OFF
@ -193,9 +192,9 @@ ynh_print_OFF () {
#
# Requires YunoHost version 3.2.0 or higher.
ynh_print_ON () {
exec {BASH_XTRACEFD}>&1
# Print an echo only for the log, to be able to know that ynh_print_ON has been called.
echo ynh_print_ON > /dev/null
exec {BASH_XTRACEFD}>&1
# Print an echo only for the log, to be able to know that ynh_print_ON has been called.
echo ynh_print_ON > /dev/null
}
# Initial definitions for ynh_script_progression
@ -216,86 +215,87 @@ base_time=$(date +%s)
# usage: ynh_script_progression --message=message [--weight=weight] [--time]
# | arg: -m, --message= - The text to print
# | arg: -w, --weight= - The weight for this progression. This value is 1 by default. Use a bigger value for a longer part of the script.
# | arg: -t, --time= - Print the execution time since the last call to this helper. Especially usefull to define weights. The execution time is given for the duration since the previous call. So the weight should be applied to this previous call.
# | arg: -l, --last= - Use for the last call of the helper, to fill te progression bar.
# | arg: -t, --time - Print the execution time since the last call to this helper. Especially usefull to define weights. The execution time is given for the duration since the previous call. So the weight should be applied to this previous call.
# | arg: -l, --last - Use for the last call of the helper, to fill te progression bar.
#
# Requires YunoHost version 3.5.0 or higher.
ynh_script_progression () {
set +x
# Declare an array to define the options of this helper.
local legacy_args=mwtl
declare -Ar args_array=( [m]=message= [w]=weight= [t]=time [l]=last )
local message
local weight
local time
local last
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
set +x
weight=${weight:-1}
time=${time:-0}
last=${last:-0}
set +o xtrace # set +x
# Declare an array to define the options of this helper.
local legacy_args=mwtl
local -A args_array=( [m]=message= [w]=weight= [t]=time [l]=last )
local message
local weight
local time
local last
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Re-disable xtrace, ynh_handle_getopts_args set it back
set +o xtrace # set +x
weight=${weight:-1}
time=${time:-0}
last=${last:-0}
# Get execution time since the last $base_time
local exec_time=$(( $(date +%s) - $base_time ))
base_time=$(date +%s)
# Get execution time since the last $base_time
local exec_time=$(( $(date +%s) - $base_time ))
base_time=$(date +%s)
# Compute $max_progression (if we didn't already)
if [ "$max_progression" = -1 ]
then
# Get the number of occurrences of 'ynh_script_progression' in the script. Except those are commented.
local helper_calls="$(grep --count "^[^#]*ynh_script_progression" $0)"
# Get the number of call with a weight value
local weight_calls=$(grep --perl-regexp --count "^[^#]*ynh_script_progression.*(--weight|-w )" $0)
# Compute $max_progression (if we didn't already)
if [ "$max_progression" = -1 ]
then
# Get the number of occurrences of 'ynh_script_progression' in the script. Except those are commented.
local helper_calls="$(grep --count "^[^#]*ynh_script_progression" $0)"
# Get the number of call with a weight value
local weight_calls=$(grep --perl-regexp --count "^[^#]*ynh_script_progression.*(--weight|-w )" $0)
# Get the weight of each occurrences of 'ynh_script_progression' in the script using --weight
local weight_valuesA="$(grep --perl-regexp "^[^#]*ynh_script_progression.*--weight" $0 | sed 's/.*--weight[= ]\([[:digit:]]*\).*/\1/g')"
# Get the weight of each occurrences of 'ynh_script_progression' in the script using -w
local weight_valuesB="$(grep --perl-regexp "^[^#]*ynh_script_progression.*-w " $0 | sed 's/.*-w[= ]\([[:digit:]]*\).*/\1/g')"
# Each value will be on a different line.
# Remove each 'end of line' and replace it by a '+' to sum the values.
local weight_values=$(( $(echo "$weight_valuesA" | tr '\n' '+') + $(echo "$weight_valuesB" | tr '\n' '+') 0 ))
# Get the weight of each occurrences of 'ynh_script_progression' in the script using --weight
local weight_valuesA="$(grep --perl-regexp "^[^#]*ynh_script_progression.*--weight" $0 | sed 's/.*--weight[= ]\([[:digit:]]*\).*/\1/g')"
# Get the weight of each occurrences of 'ynh_script_progression' in the script using -w
local weight_valuesB="$(grep --perl-regexp "^[^#]*ynh_script_progression.*-w " $0 | sed 's/.*-w[= ]\([[:digit:]]*\).*/\1/g')"
# Each value will be on a different line.
# Remove each 'end of line' and replace it by a '+' to sum the values.
local weight_values=$(( $(echo "$weight_valuesA" | tr '\n' '+') + $(echo "$weight_valuesB" | tr '\n' '+') 0 ))
# max_progression is a total number of calls to this helper.
# Less the number of calls with a weight value.
# Plus the total of weight values
max_progression=$(( $helper_calls - $weight_calls + $weight_values ))
fi
# max_progression is a total number of calls to this helper.
# Less the number of calls with a weight value.
# Plus the total of weight values
max_progression=$(( $helper_calls - $weight_calls + $weight_values ))
fi
# Increment each execution of ynh_script_progression in this script by the weight of the previous call.
increment_progression=$(( $increment_progression + $previous_weight ))
# Store the weight of the current call in $previous_weight for next call
previous_weight=$weight
# Increment each execution of ynh_script_progression in this script by the weight of the previous call.
increment_progression=$(( $increment_progression + $previous_weight ))
# Store the weight of the current call in $previous_weight for next call
previous_weight=$weight
# Reduce $increment_progression to the size of the scale
if [ $last -eq 0 ]
then
local effective_progression=$(( $increment_progression * $progress_scale / $max_progression ))
# If last is specified, fill immediately the progression_bar
else
local effective_progression=$progress_scale
fi
# Reduce $increment_progression to the size of the scale
if [ $last -eq 0 ]
then
local effective_progression=$(( $increment_progression * $progress_scale / $max_progression ))
# If last is specified, fill immediately the progression_bar
else
local effective_progression=$progress_scale
fi
# Build $progression_bar from progress_string(0,1,2) according to $effective_progression and the weight of the current task
# expected_progression is the progression expected after the current task
local expected_progression="$(( ( $increment_progression + $weight ) * $progress_scale / $max_progression - $effective_progression ))"
if [ $last -eq 1 ]
then
expected_progression=0
fi
# left_progression is the progression not yet done
local left_progression="$(( $progress_scale - $effective_progression - $expected_progression ))"
# Build the progression bar with $effective_progression, work done, $expected_progression, current work and $left_progression, work to be done.
local progression_bar="${progress_string2:0:$effective_progression}${progress_string1:0:$expected_progression}${progress_string0:0:$left_progression}"
# Build $progression_bar from progress_string(0,1,2) according to $effective_progression and the weight of the current task
# expected_progression is the progression expected after the current task
local expected_progression="$(( ( $increment_progression + $weight ) * $progress_scale / $max_progression - $effective_progression ))"
if [ $last -eq 1 ]
then
expected_progression=0
fi
# left_progression is the progression not yet done
local left_progression="$(( $progress_scale - $effective_progression - $expected_progression ))"
# Build the progression bar with $effective_progression, work done, $expected_progression, current work and $left_progression, work to be done.
local progression_bar="${progress_string2:0:$effective_progression}${progress_string1:0:$expected_progression}${progress_string0:0:$left_progression}"
local print_exec_time=""
if [ $time -eq 1 ]
then
print_exec_time=" [$(date +%Hh%Mm,%Ss --date="0 + $exec_time sec")]"
fi
local print_exec_time=""
if [ $time -eq 1 ]
then
print_exec_time=" [$(date +%Hh%Mm,%Ss --date="0 + $exec_time sec")]"
fi
ynh_print_info "[$progression_bar] > ${message}${print_exec_time}"
set -x
ynh_print_info "[$progression_bar] > ${message}${print_exec_time}"
set -o xtrace # set -x
}
# Return data to the Yunohost core for later processing
@ -316,63 +316,62 @@ ynh_return () {
#
# Requires YunoHost version 3.5.0 or higher.
ynh_debug () {
# Disable set xtrace for the helper itself, to not pollute the debug log
set +x
# Declare an array to define the options of this helper.
local legacy_args=mt
declare -Ar args_array=( [m]=message= [t]=trace= )
local message
local trace
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Redisable xtrace, ynh_handle_getopts_args set it back
set +x
message=${message:-}
trace=${trace:-}
# Disable set xtrace for the helper itself, to not pollute the debug log
set +o xtrace # set +x
# Declare an array to define the options of this helper.
local legacy_args=mt
local -A args_array=( [m]=message= [t]=trace= )
local message
local trace
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Re-disable xtrace, ynh_handle_getopts_args set it back
set +o xtrace # set +x
message=${message:-}
trace=${trace:-}
if [ -n "$message" ]
then
ynh_print_log "\e[34m\e[1m[DEBUG]\e[0m ${message}" >&2
fi
if [ -n "$message" ]
then
ynh_print_log "\e[34m\e[1m[DEBUG]\e[0m ${message}" >&2
fi
if [ "$trace" == "1" ]
then
ynh_debug --message="Enable debugging"
set +x
# Get the current file descriptor of xtrace
old_bash_xtracefd=$BASH_XTRACEFD
# Add the current file name and the line number of any command currently running while tracing.
PS4='$(basename ${BASH_SOURCE[0]})-L${LINENO}: '
# Force xtrace to stderr
BASH_XTRACEFD=2
# Force stdout to stderr
exec 1>&2
fi
if [ "$trace" == "0" ]
then
ynh_debug --message="Disable debugging"
set +x
# Put xtrace back to its original fild descriptor
BASH_XTRACEFD=$old_bash_xtracefd
# Restore stdout
exec 1>&1
fi
# Renable set xtrace
set -x
if [ "$trace" == "1" ]
then
ynh_debug --message="Enable debugging"
set +o xtrace # set +x
# Get the current file descriptor of xtrace
old_bash_xtracefd=$BASH_XTRACEFD
# Add the current file name and the line number of any command currently running while tracing.
PS4='$(basename ${BASH_SOURCE[0]})-L${LINENO}: '
# Force xtrace to stderr
BASH_XTRACEFD=2
# Force stdout to stderr
exec 1>&2
fi
if [ "$trace" == "0" ]
then
ynh_debug --message="Disable debugging"
set +o xtrace # set +x
# Put xtrace back to its original fild descriptor
BASH_XTRACEFD=$old_bash_xtracefd
# Restore stdout
exec 1>&1
fi
# Renable set xtrace
set -o xtrace # set -x
}
# Execute a command and print the result as debug
#
# usage: ynh_debug_exec your_command
# usage: ynh_debug_exec "your_command | other_command"
# | arg: command - command to execute
#
# When using pipes, double quotes are required - otherwise, this helper will run the first command, and the whole output will be sent through the next pipe.
#
# If the command to execute uses double quotes, they have to be escaped or they will be interpreted and removed.
#
# | arg: command - command to execute
#
# Requires YunoHost version 3.5.0 or higher.
ynh_debug_exec () {
ynh_debug --message="$(eval $@)"
ynh_debug --message="$(eval $@)"
}

View file

@ -3,9 +3,9 @@
# Use logrotate to manage the logfile
#
# usage: ynh_use_logrotate [--logfile=/log/file] [--nonappend] [--specific_user=user/group]
# | arg: -l, --logfile - absolute path of logfile
# | arg: -n, --nonappend - (optional) Replace the config file instead of appending this new config.
# | arg: -u, --specific_user : run logrotate as the specified user and group. If not specified logrotate is runned as root.
# | arg: -l, --logfile= - absolute path of logfile
# | arg: -n, --nonappend - (optional) Replace the config file instead of appending this new config.
# | arg: -u, --specific_user= - run logrotate as the specified user and group. If not specified logrotate is runned as root.
#
# If no --logfile is provided, /var/log/${app} will be used as default.
# logfile can be just a directory, or a full path to a logfile :
@ -16,82 +16,88 @@
# the same logrotate config file. Unless you use the option --non-append
#
# Requires YunoHost version 2.6.4 or higher.
# Requires YunoHost version 3.2.0 or higher for the argument --specific_user
ynh_use_logrotate () {
# Declare an array to define the options of this helper.
local legacy_args=lnuya
declare -Ar args_array=( [l]=logfile= [n]=nonappend [u]=specific_user= [y]=non [a]=append )
# [y]=non [a]=append are only for legacy purpose, to not fail on the old option '--non-append'
local logfile
local nonappend
local specific_user
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local logfile="${logfile:-}"
local nonappend="${nonappend:-0}"
local specific_user="${specific_user:-}"
# Declare an array to define the options of this helper.
local legacy_args=lnuya
local -A args_array=( [l]=logfile= [n]=nonappend [u]=specific_user= [y]=non [a]=append )
# [y]=non [a]=append are only for legacy purpose, to not fail on the old option '--non-append'
local logfile
local nonappend
local specific_user
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
logfile="${logfile:-}"
nonappend="${nonappend:-0}"
specific_user="${specific_user:-}"
# LEGACY CODE - PRE GETOPTS
if [ $# -gt 0 ] && [ "$1" == "--non-append" ]; then
nonappend=1
# Destroy this argument for the next command.
shift
elif [ $# -gt 1 ] && [ "$2" == "--non-append" ]; then
nonappend=1
fi
# LEGACY CODE - PRE GETOPTS
if [ $# -gt 0 ] && [ "$1" == "--non-append" ]
then
nonappend=1
# Destroy this argument for the next command.
shift
elif [ $# -gt 1 ] && [ "$2" == "--non-append" ]
then
nonappend=1
fi
if [ $# -gt 0 ] && [ "$(echo ${1:0:1})" != "-" ]; then
# If the given logfile parameter already exists as a file, or if it ends up with ".log",
# we just want to manage a single file
if [ -f "$1" ] || [ "$(echo ${1##*.})" == "log" ]; then
local logfile=$1
# Otherwise we assume we want to manage a directory and all its .log file inside
else
local logfile=$1/*.log
fi
fi
# LEGACY CODE
if [ $# -gt 0 ] && [ "$(echo ${1:0:1})" != "-" ]
then
# If the given logfile parameter already exists as a file, or if it ends up with ".log",
# we just want to manage a single file
if [ -f "$1" ] || [ "$(echo ${1##*.})" == "log" ]
then
local logfile=$1
# Otherwise we assume we want to manage a directory and all its .log file inside
else
local logfile=$1/*.log
fi
fi
# LEGACY CODE
local customtee="tee -a"
if [ "$nonappend" -eq 1 ]; then
customtee="tee"
fi
if [ -n "$logfile" ]
then
if [ ! -f "$1" ] && [ "$(echo ${logfile##*.})" != "log" ]; then # Keep only the extension to check if it's a logfile
local logfile="$logfile/*.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
fi
local su_directive=""
if [[ -n $specific_user ]]; then
su_directive=" # Run logorotate as specific user - group
su ${specific_user%/*} ${specific_user#*/}"
fi
local customtee="tee --append"
if [ "$nonappend" -eq 1 ]; then
customtee="tee"
fi
if [ -n "$logfile" ]
then
if [ ! -f "$1" ] && [ "$(echo ${logfile##*.})" != "log" ]; then # Keep only the extension to check if it's a logfile
local logfile="$logfile/*.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
fi
local su_directive=""
if [[ -n $specific_user ]]
then
su_directive=" # Run logorotate as specific user - group
su ${specific_user%/*} ${specific_user#*/}"
fi
cat > ./${app}-logrotate << EOF # Build a config file for logrotate
cat > ./${app}-logrotate << EOF # Build a config file for logrotate
$logfile {
# Rotate if the logfile exceeds 100Mo
size 100M
# Keep 12 old log maximum
rotate 12
# Compress the logs with gzip
compress
# Compress the log at the next cycle. So keep always 2 non compressed logs
delaycompress
# Copy and truncate the log to allow to continue write on it. Instead of move the log.
copytruncate
# Do not do an error if the log is missing
missingok
# Not rotate if the log is empty
notifempty
# Keep old logs in the same dir
noolddir
$su_directive
# Rotate if the logfile exceeds 100Mo
size 100M
# Keep 12 old log maximum
rotate 12
# Compress the logs with gzip
compress
# Compress the log at the next cycle. So keep always 2 non compressed logs
delaycompress
# Copy and truncate the log to allow to continue write on it. Instead of move the log.
copytruncate
# Do not do an error if the log is missing
missingok
# Not rotate if the log is empty
notifempty
# Keep old logs in the same dir
noolddir
$su_directive
}
EOF
mkdir -p $(dirname "$logfile") # Create the log directory, if not exist
cat ${app}-logrotate | $customtee /etc/logrotate.d/$app > /dev/null # Append this config to the existing config file, or replace the whole config file (depending on $customtee)
mkdir --parents $(dirname "$logfile") # Create the log directory, if not exist
cat ${app}-logrotate | $customtee /etc/logrotate.d/$app > /dev/null # Append this config to the existing config file, or replace the whole config file (depending on $customtee)
}
# Remove the app's logrotate config.
@ -100,7 +106,7 @@ EOF
#
# Requires YunoHost version 2.6.4 or higher.
ynh_remove_logrotate () {
if [ -e "/etc/logrotate.d/$app" ]; then
rm "/etc/logrotate.d/$app"
fi
if [ -e "/etc/logrotate.d/$app" ]; then
rm "/etc/logrotate.d/$app"
fi
}

View file

@ -4,19 +4,19 @@ MYSQL_ROOT_PWD_FILE=/etc/yunohost/mysql
# Open a connection as a user
#
# example: ynh_mysql_connect_as 'user' 'pass' <<< "UPDATE ...;"
# example: ynh_mysql_connect_as 'user' 'pass' < /path/to/file.sql
# example: ynh_mysql_connect_as --user="user" --password="pass" <<< "UPDATE ...;"
# example: ynh_mysql_connect_as --user="user" --password="pass" < /path/to/file.sql
#
# usage: ynh_mysql_connect_as --user=user --password=password [--database=database]
# | arg: -u, --user - the user name to connect as
# | arg: -p, --password - the user password
# | arg: -d, --database - the database to connect to
# | arg: -u, --user= - the user name to connect as
# | arg: -p, --password= - the user password
# | arg: -d, --database= - the database to connect to
#
# Requires YunoHost version 2.2.4 or higher.
ynh_mysql_connect_as() {
# Declare an array to define the options of this helper.
local legacy_args=upd
declare -Ar args_array=( [u]=user= [p]=password= [d]=database= )
local -A args_array=( [u]=user= [p]=password= [d]=database= )
local user
local password
local database
@ -24,20 +24,20 @@ ynh_mysql_connect_as() {
ynh_handle_getopts_args "$@"
database="${database:-}"
mysql -u "$user" --password="$password" -B "$database"
mysql --user="$user" --password="$password" --batch "$database"
}
# Execute a command as root user
#
# usage: ynh_mysql_execute_as_root --sql=sql [--database=database]
# | arg: -s, --sql - the SQL command to execute
# | arg: -d, --database - the database to connect to
# | arg: -s, --sql= - the SQL command to execute
# | arg: -d, --database= - the database to connect to
#
# Requires YunoHost version 2.2.4 or higher.
ynh_mysql_execute_as_root() {
# Declare an array to define the options of this helper.
local legacy_args=sd
declare -Ar args_array=( [s]=sql= [d]=database= )
local -A args_array=( [s]=sql= [d]=database= )
local sql
local database
# Manage arguments with getopts
@ -51,14 +51,14 @@ ynh_mysql_execute_as_root() {
# Execute a command from a file as root user
#
# usage: ynh_mysql_execute_file_as_root --file=file [--database=database]
# | arg: -f, --file - the file containing SQL commands
# | arg: -d, --database - the database to connect to
# | arg: -f, --file= - the file containing SQL commands
# | arg: -d, --database= - the database to connect to
#
# Requires YunoHost version 2.2.4 or higher.
ynh_mysql_execute_file_as_root() {
# Declare an array to define the options of this helper.
local legacy_args=fd
declare -Ar args_array=( [f]=file= [d]=database= )
local -A args_array=( [f]=file= [d]=database= )
local file
local database
# Manage arguments with getopts
@ -85,9 +85,12 @@ ynh_mysql_create_db() {
local sql="CREATE DATABASE ${db};"
# grant all privilegies to user
if [[ $# -gt 1 ]]; then
if [[ $# -gt 1 ]]
then
sql+=" GRANT ALL PRIVILEGES ON ${db}.* TO '${2}'@'localhost'"
[[ -n ${3:-} ]] && sql+=" IDENTIFIED BY '${3}'"
if [[ -n ${3:-} ]]; then
sql+=" IDENTIFIED BY '${3}'"
fi
sql+=" WITH GRANT OPTION;"
fi
@ -111,22 +114,22 @@ ynh_mysql_drop_db() {
# Dump a database
#
# example: ynh_mysql_dump_db 'roundcube' > ./dump.sql
# example: ynh_mysql_dump_db --database=roundcube > ./dump.sql
#
# usage: ynh_mysql_dump_db --database=database
# | arg: -d, --database - the database name to dump
# | arg: -d, --database= - the database name to dump
# | ret: the mysqldump output
#
# Requires YunoHost version 2.2.4 or higher.
ynh_mysql_dump_db() {
# Declare an array to define the options of this helper.
local legacy_args=d
declare -Ar args_array=( [d]=database= )
local -A args_array=( [d]=database= )
local database
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
mysqldump -u "root" -p"$(cat $MYSQL_ROOT_PWD_FILE)" --single-transaction --skip-dump-date "$database"
mysqldump --user="root" --password="$(cat $MYSQL_ROOT_PWD_FILE)" --single-transaction --skip-dump-date "$database"
}
# Create a user
@ -146,24 +149,25 @@ ynh_mysql_create_user() {
# Check if a mysql user exists
#
# usage: ynh_mysql_user_exists --user=user
# | arg: -u, --user - the user for which to check existence
# | arg: -u, --user= - the user for which to check existence
# | exit: Return 1 if the user doesn't exist, 0 otherwise.
#
# Requires YunoHost version 2.2.4 or higher.
ynh_mysql_user_exists()
{
# Declare an array to define the options of this helper.
local legacy_args=u
declare -Ar args_array=( [u]=user= )
local user
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=u
local -A args_array=( [u]=user= )
local user
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
if [[ -z $(ynh_mysql_execute_as_root --sql="SELECT User from mysql.user WHERE User = '$user';") ]]
then
return 1
else
return 0
fi
if [[ -z $(ynh_mysql_execute_as_root --sql="SELECT User from mysql.user WHERE User = '$user';") ]]
then
return 1
else
return 0
fi
}
# Drop a user
@ -180,59 +184,59 @@ ynh_mysql_drop_user() {
# Create a database, an user and its password. Then store the password in the app's config
#
# usage: ynh_mysql_setup_db --db_user=user --db_name=name [--db_pwd=pwd]
# | arg: -u, --db_user= - Owner of the database
# | arg: -n, --db_name= - Name of the database
# | arg: -p, --db_pwd= - Password of the database. If not provided, a password will be generated
#
# After executing this helper, the password of the created database will be available in $db_pwd
# It will also be stored as "mysqlpwd" into the app settings.
#
# usage: ynh_mysql_setup_db --db_user=user --db_name=name [--db_pwd=pwd]
# | arg: -u, --db_user - Owner of the database
# | arg: -n, --db_name - Name of the database
# | arg: -p, --db_pwd - Password of the database. If not provided, a password will be generated
#
# Requires YunoHost version 2.6.4 or higher.
ynh_mysql_setup_db () {
# Declare an array to define the options of this helper.
local legacy_args=unp
declare -Ar args_array=( [u]=db_user= [n]=db_name= [p]=db_pwd= )
local db_user
local db_name
db_pwd=""
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=unp
local -A args_array=( [u]=db_user= [n]=db_name= [p]=db_pwd= )
local db_user
local db_name
db_pwd=""
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local new_db_pwd=$(ynh_string_random) # Generate a random password
# If $db_pwd is not provided, use new_db_pwd instead for db_pwd
db_pwd="${db_pwd:-$new_db_pwd}"
local new_db_pwd=$(ynh_string_random) # Generate a random password
# If $db_pwd is not provided, use new_db_pwd instead for db_pwd
db_pwd="${db_pwd:-$new_db_pwd}"
ynh_mysql_create_db "$db_name" "$db_user" "$db_pwd" # Create the database
ynh_app_setting_set --app=$app --key=mysqlpwd --value=$db_pwd # Store the password in the app's config
ynh_mysql_create_db "$db_name" "$db_user" "$db_pwd" # Create the database
ynh_app_setting_set --app=$app --key=mysqlpwd --value=$db_pwd # Store the password in the app's config
}
# Remove a database if it exists, and the associated user
#
# usage: ynh_mysql_remove_db --db_user=user --db_name=name
# | arg: -u, --db_user - Owner of the database
# | arg: -n, --db_name - Name of the database
# | arg: -u, --db_user= - Owner of the database
# | arg: -n, --db_name= - Name of the database
#
# Requires YunoHost version 2.6.4 or higher.
ynh_mysql_remove_db () {
# Declare an array to define the options of this helper.
local legacy_args=un
declare -Ar args_array=( [u]=db_user= [n]=db_name= )
local db_user
local db_name
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=un
local -A args_array=( [u]=db_user= [n]=db_name= )
local db_user
local db_name
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local mysql_root_password=$(cat $MYSQL_ROOT_PWD_FILE)
if mysqlshow -u root -p$mysql_root_password | grep -q "^| $db_name"; then # Check if the database exists
ynh_mysql_drop_db $db_name # Remove the database
else
ynh_print_warn --message="Database $db_name not found"
fi
local mysql_root_password=$(cat $MYSQL_ROOT_PWD_FILE)
if mysqlshow --user=root --password=$mysql_root_password | grep --quiet "^| $db_name"
then # Check if the database exists
ynh_mysql_drop_db $db_name # Remove the database
else
ynh_print_warn --message="Database $db_name not found"
fi
# Remove mysql user if it exists
if ynh_mysql_user_exists --user=$db_user; then
ynh_mysql_drop_user $db_user
fi
# Remove mysql user if it exists
if ynh_mysql_user_exists --user=$db_user; then
ynh_mysql_drop_user $db_user
fi
}

View file

@ -5,23 +5,24 @@
# example: port=$(ynh_find_port --port=8080)
#
# usage: ynh_find_port --port=begin_port
# | arg: -p, --port - port to start to search
# | arg: -p, --port= - port to start to search
# | ret: the port number
#
# Requires YunoHost version 2.6.4 or higher.
ynh_find_port () {
# Declare an array to define the options of this helper.
local legacy_args=p
declare -Ar args_array=( [p]=port= )
local port
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=p
local -A args_array=( [p]=port= )
local port
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
test -n "$port" || ynh_die --message="The argument of ynh_find_port must be a valid port."
while ss -nltu | awk '{print$5}' | grep -q -E ":$port$" # Check if the port is free
do
port=$((port+1)) # Else, pass to next port
done
echo $port
test -n "$port" || ynh_die --message="The argument of ynh_find_port must be a valid port."
while ! ynh_port_available --port=$port
do
port=$((port+1)) # Else, pass to next port
done
echo $port
}
# Test if a port is available
@ -29,18 +30,19 @@ ynh_find_port () {
# example: ynh_port_available --port=1234 || ynh_die "Port 1234 is needs to be available for this app"
#
# usage: ynh_find_port --port=XYZ
# | arg: -p, --port - port to check
# | arg: -p, --port= - port to check
# | exit: Return 1 if the port is already used by another process.
#
# Requires YunoHost version 3.7.x or higher.
# Requires YunoHost version 3.8.0 or higher.
ynh_port_available () {
# Declare an array to define the options of this helper.
local legacy_args=p
declare -Ar args_array=( [p]=port= )
local port
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=p
local -A args_array=( [p]=port= )
local port
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
if ss -nltu | grep -q -w :$port
if ss --numeric --listening --tcp --udp | awk '{print$5}' | grep --quiet --extended-regexp ":$port$" # Check if the port is free
then
return 1
else
@ -51,6 +53,8 @@ ynh_port_available () {
# Validate an IP address
#
# [internal]
#
# usage: ynh_validate_ip --family=family --ip_address=ip_address
# | ret: 0 for valid ip addresses, 1 otherwise
#
@ -59,17 +63,17 @@ ynh_port_available () {
# Requires YunoHost version 2.2.4 or higher.
ynh_validate_ip()
{
# http://stackoverflow.com/questions/319279/how-to-validate-ip-address-in-python#319298
# http://stackoverflow.com/questions/319279/how-to-validate-ip-address-in-python#319298
# Declare an array to define the options of this helper.
local legacy_args=fi
declare -Ar args_array=( [f]=family= [i]=ip_address= )
local family
local ip_address
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=fi
local -A args_array=( [f]=family= [i]=ip_address= )
local family
local ip_address
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
[ "$family" == "4" ] || [ "$family" == "6" ] || return 1
[ "$family" == "4" ] || [ "$family" == "6" ] || return 1
python /dev/stdin << EOF
import socket
@ -88,19 +92,20 @@ EOF
# example: ynh_validate_ip4 111.222.333.444
#
# usage: ynh_validate_ip4 --ip_address=ip_address
# | arg: -i, --ip_address= - the ipv4 address to check
# | ret: 0 for valid ipv4 addresses, 1 otherwise
#
# Requires YunoHost version 2.2.4 or higher.
ynh_validate_ip4()
{
# Declare an array to define the options of this helper.
local legacy_args=i
declare -Ar args_array=( [i]=ip_address= )
local ip_address
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=i
local -A args_array=( [i]=ip_address= )
local ip_address
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
ynh_validate_ip 4 $ip_address
ynh_validate_ip --family=4 --ip_address=$ip_address
}
@ -109,17 +114,18 @@ ynh_validate_ip4()
# example: ynh_validate_ip6 2000:dead:beef::1
#
# usage: ynh_validate_ip6 --ip_address=ip_address
# | arg: -i, --ip_address= - the ipv6 address to check
# | ret: 0 for valid ipv6 addresses, 1 otherwise
#
# Requires YunoHost version 2.2.4 or higher.
ynh_validate_ip6()
{
# Declare an array to define the options of this helper.
local legacy_args=i
declare -Ar args_array=( [i]=ip_address= )
local ip_address
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=i
local -A args_array=( [i]=ip_address= )
local ip_address
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
ynh_validate_ip 6 $ip_address
ynh_validate_ip --family=6 --ip_address=$ip_address
}

View file

@ -19,52 +19,54 @@
# __PORT_2__ by $port_2
#
# Requires YunoHost version 2.7.2 or higher.
# Requires YunoHost version 2.7.13 or higher for dynamic variables
ynh_add_nginx_config () {
finalnginxconf="/etc/nginx/conf.d/$domain.d/$app.conf"
local others_var=${1:-}
ynh_backup_if_checksum_is_different --file="$finalnginxconf"
cp ../conf/nginx.conf "$finalnginxconf"
finalnginxconf="/etc/nginx/conf.d/$domain.d/$app.conf"
local others_var=${1:-}
ynh_backup_if_checksum_is_different --file="$finalnginxconf"
cp ../conf/nginx.conf "$finalnginxconf"
# To avoid a break by set -u, use a void substitution ${var:-}. If the variable is not set, it's simply set with an empty variable.
# 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 '/'
local path_url_slash_less=${path_url%/}
ynh_replace_string --match_string="__PATH__/" --replace_string="$path_url_slash_less/" --target_file="$finalnginxconf"
ynh_replace_string --match_string="__PATH__" --replace_string="$path_url" --target_file="$finalnginxconf"
fi
if test -n "${domain:-}"; then
ynh_replace_string --match_string="__DOMAIN__" --replace_string="$domain" --target_file="$finalnginxconf"
fi
if test -n "${port:-}"; then
ynh_replace_string --match_string="__PORT__" --replace_string="$port" --target_file="$finalnginxconf"
fi
if test -n "${app:-}"; then
ynh_replace_string --match_string="__NAME__" --replace_string="$app" --target_file="$finalnginxconf"
fi
if test -n "${final_path:-}"; then
ynh_replace_string --match_string="__FINALPATH__" --replace_string="$final_path" --target_file="$finalnginxconf"
fi
ynh_replace_string --match_string="__PHPVERSION__" --replace_string="$YNH_PHP_VERSION" --target_file="$finalnginxconf"
# To avoid a break by set -u, use a void substitution ${var:-}. If the variable is not set, it's simply set with an empty variable.
# 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 '/'
local path_url_slash_less=${path_url%/}
ynh_replace_string --match_string="__PATH__/" --replace_string="$path_url_slash_less/" --target_file="$finalnginxconf"
ynh_replace_string --match_string="__PATH__" --replace_string="$path_url" --target_file="$finalnginxconf"
fi
if test -n "${domain:-}"; then
ynh_replace_string --match_string="__DOMAIN__" --replace_string="$domain" --target_file="$finalnginxconf"
fi
if test -n "${port:-}"; then
ynh_replace_string --match_string="__PORT__" --replace_string="$port" --target_file="$finalnginxconf"
fi
if test -n "${app:-}"; then
ynh_replace_string --match_string="__NAME__" --replace_string="$app" --target_file="$finalnginxconf"
fi
if test -n "${final_path:-}"; then
ynh_replace_string --match_string="__FINALPATH__" --replace_string="$final_path" --target_file="$finalnginxconf"
fi
ynh_replace_string --match_string="__PHPVERSION__" --replace_string="$YNH_PHP_VERSION" --target_file="$finalnginxconf"
# Replace all other variable given as arguments
for var_to_replace in $others_var
do
# ${var_to_replace^^} make the content of the variable on upper-cases
# ${!var_to_replace} get the content of the variable named $var_to_replace
ynh_replace_string --match_string="__${var_to_replace^^}__" --replace_string="${!var_to_replace}" --target_file="$finalnginxconf"
done
if [ "${path_url:-}" != "/" ]
then
ynh_replace_string --match_string="^#sub_path_only" --replace_string="" --target_file="$finalnginxconf"
else
ynh_replace_string --match_string="^#root_path_only" --replace_string="" --target_file="$finalnginxconf"
fi
# Replace all other variable given as arguments
for var_to_replace in $others_var
do
# ${var_to_replace^^} make the content of the variable on upper-cases
# ${!var_to_replace} get the content of the variable named $var_to_replace
ynh_replace_string --match_string="__${var_to_replace^^}__" --replace_string="${!var_to_replace}" --target_file="$finalnginxconf"
done
ynh_store_file_checksum --file="$finalnginxconf"
if [ "${path_url:-}" != "/" ]
then
ynh_replace_string --match_string="^#sub_path_only" --replace_string="" --target_file="$finalnginxconf"
else
ynh_replace_string --match_string="^#root_path_only" --replace_string="" --target_file="$finalnginxconf"
fi
ynh_systemd_action --service_name=nginx --action=reload
ynh_store_file_checksum --file="$finalnginxconf"
ynh_systemd_action --service_name=nginx --action=reload
}
# Remove the dedicated nginx config
@ -73,6 +75,6 @@ ynh_add_nginx_config () {
#
# Requires YunoHost version 2.7.2 or higher.
ynh_remove_nginx_config () {
ynh_secure_remove --file="/etc/nginx/conf.d/$domain.d/$app.conf"
ynh_systemd_action --service_name=nginx --action=reload
ynh_secure_remove --file="/etc/nginx/conf.d/$domain.d/$app.conf"
ynh_systemd_action --service_name=nginx --action=reload
}

View file

@ -13,16 +13,16 @@ export N_PREFIX="$n_install_dir"
#
# Requires YunoHost version 2.7.12 or higher.
ynh_install_n () {
ynh_print_info --message="Installation of N - Node.js version management"
# Build an app.src for n
mkdir -p "../conf"
echo "SOURCE_URL=https://github.com/tj/n/archive/v4.1.0.tar.gz
ynh_print_info --message="Installation of N - Node.js version management"
# Build an app.src for n
mkdir --parents "../conf"
echo "SOURCE_URL=https://github.com/tj/n/archive/v4.1.0.tar.gz
SOURCE_SUM=3983fa3f00d4bf85ba8e21f1a590f6e28938093abe0bb950aeea52b1717471fc" > "../conf/n.src"
# Download and extract n
ynh_setup_source --dest_dir="$n_install_dir/git" --source_id=n
# Install n
(cd "$n_install_dir/git"
PREFIX=$N_PREFIX make install 2>&1)
# Download and extract n
ynh_setup_source --dest_dir="$n_install_dir/git" --source_id=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.
@ -41,95 +41,97 @@ SOURCE_SUM=3983fa3f00d4bf85ba8e21f1a590f6e28938093abe0bb950aeea52b1717471fc" > "
#
# Requires YunoHost version 2.7.12 or higher.
ynh_use_nodejs () {
nodejs_version=$(ynh_app_setting_get --app=$app --key=nodejs_version)
nodejs_version=$(ynh_app_setting_get --app=$app --key=nodejs_version)
nodejs_use_version="echo \"Deprecated command, should be removed\""
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"
# 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"
# Load the path of this version of node in $PATH
if [[ :$PATH: != *":$nodejs_path"* ]]; then
PATH="$nodejs_path:$PATH"
fi
}
# 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=nodejs_version
# | arg: -n, --nodejs_version - Version of node to install. When possible, your should prefer to use major version number (e.g. 8 instead of 8.10.0). The crontab will then handle the update of minor versions when needed.
# | arg: -n, --nodejs_version= - Version of node to install. When possible, your should prefer to use major version number (e.g. 8 instead of 8.10.0). The crontab will then handle the update of minor versions when needed.
#
# 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
#
# Requires YunoHost version 2.7.12 or higher.
ynh_install_nodejs () {
# Use n, https://github.com/tj/n to manage the nodejs versions
# Use n, https://github.com/tj/n to manage the nodejs versions
# Declare an array to define the options of this helper.
local legacy_args=n
declare -Ar args_array=( [n]=nodejs_version= )
local nodejs_version
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=n
local -A args_array=( [n]=nodejs_version= )
local nodejs_version
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Create $n_install_dir
mkdir -p "$n_install_dir"
# Create $n_install_dir
mkdir --parents "$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:@@')
# 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
# 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
# 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 --match_string="^N_PREFIX=\${N_PREFIX-.*}$" --replace_string="N_PREFIX=\${N_PREFIX-$N_PREFIX}" --target_file="$n_install_dir/bin/n"
# Modify the default N_PREFIX in n script
ynh_replace_string --match_string="^N_PREFIX=\${N_PREFIX-.*}$" --replace_string="N_PREFIX=\${N_PREFIX-$N_PREFIX}" --target_file="$n_install_dir/bin/n"
# Restore /usr/local/bin in PATH
PATH=$CLEAR_PATH
# 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
# 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
uname=$(uname -m)
if [[ $uname =~ aarch64 || $uname =~ arm64 ]]
then
n $nodejs_version --arch=arm64
else
n $nodejs_version
fi
# Install the requested version of nodejs
uname=$(uname --machine)
if [[ $uname =~ aarch64 || $uname =~ arm64 ]]
then
n $nodejs_version --arch=arm64
else
n $nodejs_version
fi
# 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)
# 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
# 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_INSTANCE_NAME:$nodejs_version" | tee --append "$n_install_dir/ynh_app_version"
# Store the ID of this app and the version of node requested for it
echo "$YNH_APP_INSTANCE_NAME:$nodejs_version" | tee --append "$n_install_dir/ynh_app_version"
# Store nodejs_version into the config of this app
ynh_app_setting_set --app=$app --key=nodejs_version --value=$nodejs_version
# Store nodejs_version into the config of this app
ynh_app_setting_set --app=$app --key=nodejs_version --value=$nodejs_version
# Build the update script and set the cronjob
ynh_cron_upgrade_node
# Build the update script and set the cronjob
ynh_cron_upgrade_node
ynh_use_nodejs
ynh_use_nodejs
}
# Remove the version of node used by the app.
@ -142,25 +144,25 @@ ynh_install_nodejs () {
#
# Requires YunoHost version 2.7.12 or higher.
ynh_remove_nodejs () {
nodejs_version=$(ynh_app_setting_get --app=$app --key=nodejs_version)
nodejs_version=$(ynh_app_setting_get --app=$app --key=nodejs_version)
# Remove the line for this app
sed --in-place "/$YNH_APP_INSTANCE_NAME:$nodejs_version/d" "$n_install_dir/ynh_app_version"
# Remove the line for this app
sed --in-place "/$YNH_APP_INSTANCE_NAME:$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 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 --file="$n_install_dir"
ynh_secure_remove --file="/usr/local/n"
sed --in-place "/N_PREFIX/d" /root/.bashrc
rm -f /etc/cron.daily/node_update
fi
# If no other app uses n, remove n
if [ ! -s "$n_install_dir/ynh_app_version" ]
then
ynh_secure_remove --file="$n_install_dir"
ynh_secure_remove --file="/usr/local/n"
sed --in-place "/N_PREFIX/d" /root/.bashrc
rm --force /etc/cron.daily/node_update
fi
}
# Set a cron design to update your node versions
@ -173,8 +175,8 @@ ynh_remove_nodejs () {
#
# Requires YunoHost version 2.7.12 or higher.
ynh_cron_upgrade_node () {
# Build the update script
cat > "$n_install_dir/node_update.sh" << EOF
# Build the update script
cat > "$n_install_dir/node_update.sh" << EOF
#!/bin/bash
version_path="$node_version_path"
@ -195,26 +197,26 @@ 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
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)
# 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
# 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"
chmod +x "$n_install_dir/node_update.sh"
# Build the cronjob
cat > "/etc/cron.daily/node_update" << EOF
# 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"
chmod +x "/etc/cron.daily/node_update"
}

View file

@ -8,16 +8,16 @@ YNH_PHP_VERSION=${YNH_PHP_VERSION:-$YNH_DEFAULT_PHP_VERSION}
# Create a dedicated php-fpm config
#
# usage 1: ynh_add_fpm_config [--phpversion=7.X] [--use_template] [--package=packages] [--dedicated_service]
# | arg: -v, --phpversion - Version of php to use.
# | arg: -t, --use_template - Use this helper in template mode.
# | arg: -p, --package - Additionnal php packages to install
# | arg: -d, --dedicated_service - Use a dedicated php-fpm service instead of the common one.
# | arg: -v, --phpversion= - Version of php to use.
# | arg: -t, --use_template - Use this helper in template mode.
# | arg: -p, --package= - Additionnal php packages to install
# | arg: -d, --dedicated_service - Use a dedicated php-fpm service instead of the common one.
#
# -----------------------------------------------------------------------------
#
# usage 2: ynh_add_fpm_config [--phpversion=7.X] --usage=usage --footprint=footprint [--package=packages] [--dedicated_service]
# | arg: -v, --phpversion - Version of php to use.
# | arg: -f, --footprint - Memory footprint of the service (low/medium/high).
# | arg: -v, --phpversion= - Version of php to use.
# | arg: -f, --footprint= - Memory footprint of the service (low/medium/high).
# low - Less than 20Mb of ram by pool.
# medium - Between 20Mb and 40Mb of ram by pool.
# high - More than 40Mb of ram by pool.
@ -25,13 +25,13 @@ YNH_PHP_VERSION=${YNH_PHP_VERSION:-$YNH_DEFAULT_PHP_VERSION}
# To have this value, use the following command and stress the service.
# watch -n0.5 ps -o user,cmd,%cpu,rss -u APP
#
# | arg: -u, --usage - Expected usage of the service (low/medium/high).
# | arg: -u, --usage= - Expected usage of the service (low/medium/high).
# low - Personal usage, behind the sso.
# medium - Low usage, few people or/and publicly accessible.
# high - High usage, frequently visited website.
#
# | arg: -p, --package - Additionnal php packages to install for a specific version of php
# | arg: -d, --dedicated_service - Use a dedicated php-fpm service instead of the common one.
# | arg: -p, --package= - Additionnal php packages to install for a specific version of php
# | arg: -d, --dedicated_service - Use a dedicated php-fpm service instead of the common one.
#
#
# The footprint of the service will be used to defined the maximum footprint we can allow, which is half the maximum RAM.
@ -56,180 +56,184 @@ YNH_PHP_VERSION=${YNH_PHP_VERSION:-$YNH_DEFAULT_PHP_VERSION}
# children ready to answer.
#
# Requires YunoHost version 2.7.2 or higher.
# Requires YunoHost version 3.5.1 or higher for the argument --phpversion
# Requires YunoHost version 3.8.1 or higher for the arguments --use_template, --usage, --footprint, --package and --dedicated_service
ynh_add_fpm_config () {
# Declare an array to define the options of this helper.
local legacy_args=vtufpd
declare -Ar args_array=( [v]=phpversion= [t]=use_template [u]=usage= [f]=footprint= [p]=package= [d]=dedicated_service )
local phpversion
local use_template
local usage
local footprint
local package
local dedicated_service
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
package=${package:-}
# Declare an array to define the options of this helper.
local legacy_args=vtufpd
local -A args_array=( [v]=phpversion= [t]=use_template [u]=usage= [f]=footprint= [p]=package= [d]=dedicated_service )
local phpversion
local use_template
local usage
local footprint
local package
local dedicated_service
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
package=${package:-}
# The default behaviour is to use the template.
use_template="${use_template:-1}"
usage="${usage:-}"
footprint="${footprint:-}"
if [ -n "$usage" ] || [ -n "$footprint" ]; then
use_template=0
fi
# Do not use a dedicated service by default
dedicated_service=${dedicated_service:-0}
# The default behaviour is to use the template.
use_template="${use_template:-1}"
usage="${usage:-}"
footprint="${footprint:-}"
if [ -n "$usage" ] || [ -n "$footprint" ]; then
use_template=0
fi
# Do not use a dedicated service by default
dedicated_service=${dedicated_service:-0}
# Set the default PHP-FPM version by default
phpversion="${phpversion:-$YNH_PHP_VERSION}"
# Set the default PHP-FPM version by default
phpversion="${phpversion:-$YNH_PHP_VERSION}"
# If the requested php version is not the default version for YunoHost
if [ "$phpversion" != "$YNH_DEFAULT_PHP_VERSION" ]
then
# If the argument --package is used, add the packages to ynh_install_php to install them from sury
if [ -n "$package" ]; then
local additionnal_packages="--package=$package"
else
local additionnal_packages=""
fi
# Install this specific version of php.
ynh_install_php --phpversion=$phpversion "$additionnal_packages"
elif [ -n "$package" ]
then
# Install the additionnal packages from the default repository
ynh_add_app_dependencies --package="$package"
fi
# If the requested php version is not the default version for YunoHost
if [ "$phpversion" != "$YNH_DEFAULT_PHP_VERSION" ]
then
# If the argument --package is used, add the packages to ynh_install_php to install them from sury
if [ -n "$package" ]
then
local additionnal_packages="--package=$package"
else
local additionnal_packages=""
fi
# Install this specific version of php.
ynh_install_php --phpversion="$phpversion" "$additionnal_packages"
elif [ -n "$package" ]
then
# Install the additionnal packages from the default repository
ynh_add_app_dependencies --package="$package"
fi
if [ $dedicated_service -eq 1 ]
then
local fpm_service="${app}-phpfpm"
local fpm_config_dir="/etc/php/$phpversion/dedicated-fpm"
else
local fpm_service="php${phpversion}-fpm"
local fpm_config_dir="/etc/php/$phpversion/fpm"
fi
# Configure PHP-FPM 5 on Debian Jessie
if [ "$(ynh_get_debian_release)" == "jessie" ]; then
fpm_config_dir="/etc/php5/fpm"
fpm_service="php5-fpm"
fi
if [ $dedicated_service -eq 1 ]
then
local fpm_service="${app}-phpfpm"
local fpm_config_dir="/etc/php/$phpversion/dedicated-fpm"
else
local fpm_service="php${phpversion}-fpm"
local fpm_config_dir="/etc/php/$phpversion/fpm"
fi
# Configure PHP-FPM 5 on Debian Jessie
if [ "$(ynh_get_debian_release)" == "jessie" ]
then
fpm_config_dir="/etc/php5/fpm"
fpm_service="php5-fpm"
fi
# Create the directory for fpm pools
mkdir -p "$fpm_config_dir/pool.d"
# Create the directory for fpm pools
mkdir --parents "$fpm_config_dir/pool.d"
ynh_app_setting_set --app=$app --key=fpm_config_dir --value="$fpm_config_dir"
ynh_app_setting_set --app=$app --key=fpm_service --value="$fpm_service"
ynh_app_setting_set --app=$app --key=fpm_dedicated_service --value="$dedicated_service"
ynh_app_setting_set --app=$app --key=phpversion --value=$phpversion
finalphpconf="$fpm_config_dir/pool.d/$app.conf"
ynh_app_setting_set --app=$app --key=fpm_config_dir --value="$fpm_config_dir"
ynh_app_setting_set --app=$app --key=fpm_service --value="$fpm_service"
ynh_app_setting_set --app=$app --key=fpm_dedicated_service --value="$dedicated_service"
ynh_app_setting_set --app=$app --key=phpversion --value=$phpversion
finalphpconf="$fpm_config_dir/pool.d/$app.conf"
# Migrate from mutual php service to dedicated one.
if [ $dedicated_service -eq 1 ]
then
local old_fpm_config_dir="/etc/php/$phpversion/fpm"
# If a config file exist in the common pool, move it.
if [ -e "$old_fpm_config_dir/pool.d/$app.conf" ]
then
ynh_print_info --message="Migrate to a dedicated php-fpm service for $app."
# Create a backup of the old file before migration
ynh_backup_if_checksum_is_different --file="$old_fpm_config_dir/pool.d/$app.conf"
# Remove the old php config file
ynh_secure_remove --file="$old_fpm_config_dir/pool.d/$app.conf"
# Reload php to release the socket and allow the dedicated service to use it
ynh_systemd_action --service_name=php${phpversion}-fpm --action=reload
fi
fi
# Migrate from mutual php service to dedicated one.
if [ $dedicated_service -eq 1 ]
then
local old_fpm_config_dir="/etc/php/$phpversion/fpm"
# If a config file exist in the common pool, move it.
if [ -e "$old_fpm_config_dir/pool.d/$app.conf" ]
then
ynh_print_info --message="Migrate to a dedicated php-fpm service for $app."
# Create a backup of the old file before migration
ynh_backup_if_checksum_is_different --file="$old_fpm_config_dir/pool.d/$app.conf"
# Remove the old php config file
ynh_secure_remove --file="$old_fpm_config_dir/pool.d/$app.conf"
# Reload php to release the socket and allow the dedicated service to use it
ynh_systemd_action --service_name=php${phpversion}-fpm --action=reload
fi
fi
ynh_backup_if_checksum_is_different --file="$finalphpconf"
ynh_backup_if_checksum_is_different --file="$finalphpconf"
if [ $use_template -eq 1 ]
then
# Usage 1, use the template in ../conf/php-fpm.conf
cp ../conf/php-fpm.conf "$finalphpconf"
ynh_replace_string --match_string="__NAMETOCHANGE__" --replace_string="$app" --target_file="$finalphpconf"
ynh_replace_string --match_string="__FINALPATH__" --replace_string="$final_path" --target_file="$finalphpconf"
ynh_replace_string --match_string="__USER__" --replace_string="$app" --target_file="$finalphpconf"
ynh_replace_string --match_string="__PHPVERSION__" --replace_string="$phpversion" --target_file="$finalphpconf"
if [ $use_template -eq 1 ]
then
# Usage 1, use the template in ../conf/php-fpm.conf
cp ../conf/php-fpm.conf "$finalphpconf"
ynh_replace_string --match_string="__NAMETOCHANGE__" --replace_string="$app" --target_file="$finalphpconf"
ynh_replace_string --match_string="__FINALPATH__" --replace_string="$final_path" --target_file="$finalphpconf"
ynh_replace_string --match_string="__USER__" --replace_string="$app" --target_file="$finalphpconf"
ynh_replace_string --match_string="__PHPVERSION__" --replace_string="$phpversion" --target_file="$finalphpconf"
else
# Usage 2, generate a php-fpm config file with ynh_get_scalable_phpfpm
else
# Usage 2, generate a php-fpm config file with ynh_get_scalable_phpfpm
# Store settings
ynh_app_setting_set --app=$app --key=fpm_footprint --value=$footprint
ynh_app_setting_set --app=$app --key=fpm_usage --value=$usage
# Store settings
ynh_app_setting_set --app=$app --key=fpm_footprint --value=$footprint
ynh_app_setting_set --app=$app --key=fpm_usage --value=$usage
# Define the values to use for the configuration of php.
ynh_get_scalable_phpfpm --usage=$usage --footprint=$footprint
# Define the values to use for the configuration of php.
ynh_get_scalable_phpfpm --usage=$usage --footprint=$footprint
# Copy the default file
cp "/etc/php/$phpversion/fpm/pool.d/www.conf" "$finalphpconf"
# Copy the default file
cp "/etc/php/$phpversion/fpm/pool.d/www.conf" "$finalphpconf"
# Replace standard variables into the default file
ynh_replace_string --match_string="^\[www\]" --replace_string="[$app]" --target_file="$finalphpconf"
ynh_replace_string --match_string=".*listen = .*" --replace_string="listen = /var/run/php/php$phpversion-fpm-$app.sock" --target_file="$finalphpconf"
ynh_replace_string --match_string="^user = .*" --replace_string="user = $app" --target_file="$finalphpconf"
ynh_replace_string --match_string="^group = .*" --replace_string="group = $app" --target_file="$finalphpconf"
ynh_replace_string --match_string=".*chdir = .*" --replace_string="chdir = $final_path" --target_file="$finalphpconf"
# Replace standard variables into the default file
ynh_replace_string --match_string="^\[www\]" --replace_string="[$app]" --target_file="$finalphpconf"
ynh_replace_string --match_string=".*listen = .*" --replace_string="listen = /var/run/php/php$phpversion-fpm-$app.sock" --target_file="$finalphpconf"
ynh_replace_string --match_string="^user = .*" --replace_string="user = $app" --target_file="$finalphpconf"
ynh_replace_string --match_string="^group = .*" --replace_string="group = $app" --target_file="$finalphpconf"
ynh_replace_string --match_string=".*chdir = .*" --replace_string="chdir = $final_path" --target_file="$finalphpconf"
# Configure fpm children
ynh_replace_string --match_string=".*pm = .*" --replace_string="pm = $php_pm" --target_file="$finalphpconf"
ynh_replace_string --match_string=".*pm.max_children = .*" --replace_string="pm.max_children = $php_max_children" --target_file="$finalphpconf"
ynh_replace_string --match_string=".*pm.max_requests = .*" --replace_string="pm.max_requests = 500" --target_file="$finalphpconf"
ynh_replace_string --match_string=".*request_terminate_timeout = .*" --replace_string="request_terminate_timeout = 1d" --target_file="$finalphpconf"
if [ "$php_pm" = "dynamic" ]
then
ynh_replace_string --match_string=".*pm.start_servers = .*" --replace_string="pm.start_servers = $php_start_servers" --target_file="$finalphpconf"
ynh_replace_string --match_string=".*pm.min_spare_servers = .*" --replace_string="pm.min_spare_servers = $php_min_spare_servers" --target_file="$finalphpconf"
ynh_replace_string --match_string=".*pm.max_spare_servers = .*" --replace_string="pm.max_spare_servers = $php_max_spare_servers" --target_file="$finalphpconf"
elif [ "$php_pm" = "ondemand" ]
then
ynh_replace_string --match_string=".*pm.process_idle_timeout = .*" --replace_string="pm.process_idle_timeout = 10s" --target_file="$finalphpconf"
fi
# Configure fpm children
ynh_replace_string --match_string=".*pm = .*" --replace_string="pm = $php_pm" --target_file="$finalphpconf"
ynh_replace_string --match_string=".*pm.max_children = .*" --replace_string="pm.max_children = $php_max_children" --target_file="$finalphpconf"
ynh_replace_string --match_string=".*pm.max_requests = .*" --replace_string="pm.max_requests = 500" --target_file="$finalphpconf"
ynh_replace_string --match_string=".*request_terminate_timeout = .*" --replace_string="request_terminate_timeout = 1d" --target_file="$finalphpconf"
if [ "$php_pm" = "dynamic" ]
then
ynh_replace_string --match_string=".*pm.start_servers = .*" --replace_string="pm.start_servers = $php_start_servers" --target_file="$finalphpconf"
ynh_replace_string --match_string=".*pm.min_spare_servers = .*" --replace_string="pm.min_spare_servers = $php_min_spare_servers" --target_file="$finalphpconf"
ynh_replace_string --match_string=".*pm.max_spare_servers = .*" --replace_string="pm.max_spare_servers = $php_max_spare_servers" --target_file="$finalphpconf"
elif [ "$php_pm" = "ondemand" ]
then
ynh_replace_string --match_string=".*pm.process_idle_timeout = .*" --replace_string="pm.process_idle_timeout = 10s" --target_file="$finalphpconf"
fi
# Comment unused parameters
if [ "$php_pm" != "dynamic" ]
then
ynh_replace_string --match_string=".*\(pm.start_servers = .*\)" --replace_string=";\1" --target_file="$finalphpconf"
ynh_replace_string --match_string=".*\(pm.min_spare_servers = .*\)" --replace_string=";\1" --target_file="$finalphpconf"
ynh_replace_string --match_string=".*\(pm.max_spare_servers = .*\)" --replace_string=";\1" --target_file="$finalphpconf"
fi
if [ "$php_pm" != "ondemand" ]
then
ynh_replace_string --match_string=".*\(pm.process_idle_timeout = .*\)" --replace_string=";\1" --target_file="$finalphpconf"
fi
# Comment unused parameters
if [ "$php_pm" != "dynamic" ]
then
ynh_replace_string --match_string=".*\(pm.start_servers = .*\)" --replace_string=";\1" --target_file="$finalphpconf"
ynh_replace_string --match_string=".*\(pm.min_spare_servers = .*\)" --replace_string=";\1" --target_file="$finalphpconf"
ynh_replace_string --match_string=".*\(pm.max_spare_servers = .*\)" --replace_string=";\1" --target_file="$finalphpconf"
fi
if [ "$php_pm" != "ondemand" ]
then
ynh_replace_string --match_string=".*\(pm.process_idle_timeout = .*\)" --replace_string=";\1" --target_file="$finalphpconf"
fi
# Concatene the extra config.
if [ -e ../conf/extra_php-fpm.conf ]; then
cat ../conf/extra_php-fpm.conf >> "$finalphpconf"
fi
fi
# Concatene the extra config.
if [ -e ../conf/extra_php-fpm.conf ]; then
cat ../conf/extra_php-fpm.conf >> "$finalphpconf"
fi
fi
chown root: "$finalphpconf"
ynh_store_file_checksum --file="$finalphpconf"
chown root: "$finalphpconf"
ynh_store_file_checksum --file="$finalphpconf"
if [ -e "../conf/php-fpm.ini" ]
then
ynh_print_warn -message="Packagers ! Please do not use a separate php ini file, merge your directives in the pool file instead."
finalphpini="$fpm_config_dir/conf.d/20-$app.ini"
ynh_backup_if_checksum_is_different "$finalphpini"
cp ../conf/php-fpm.ini "$finalphpini"
chown root: "$finalphpini"
ynh_store_file_checksum "$finalphpini"
fi
if [ -e "../conf/php-fpm.ini" ]
then
ynh_print_warn -message="Packagers ! Please do not use a separate php ini file, merge your directives in the pool file instead."
finalphpini="$fpm_config_dir/conf.d/20-$app.ini"
ynh_backup_if_checksum_is_different "$finalphpini"
cp ../conf/php-fpm.ini "$finalphpini"
chown root: "$finalphpini"
ynh_store_file_checksum "$finalphpini"
fi
if [ $dedicated_service -eq 1 ]
then
# Create a dedicated php-fpm.conf for the service
local globalphpconf=$fpm_config_dir/php-fpm-$app.conf
cp /etc/php/${phpversion}/fpm/php-fpm.conf $globalphpconf
if [ $dedicated_service -eq 1 ]
then
# Create a dedicated php-fpm.conf for the service
local globalphpconf=$fpm_config_dir/php-fpm-$app.conf
cp /etc/php/${phpversion}/fpm/php-fpm.conf $globalphpconf
ynh_replace_string --match_string="^[; ]*pid *=.*" --replace_string="pid = /run/php/php${phpversion}-fpm-$app.pid" --target_file="$globalphpconf"
ynh_replace_string --match_string="^[; ]*error_log *=.*" --replace_string="error_log = /var/log/php/fpm-php.$app.log" --target_file="$globalphpconf"
ynh_replace_string --match_string="^[; ]*syslog.ident *=.*" --replace_string="syslog.ident = php-fpm-$app" --target_file="$globalphpconf"
ynh_replace_string --match_string="^[; ]*include *=.*" --replace_string="include = $finalphpconf" --target_file="$globalphpconf"
ynh_replace_string --match_string="^[; ]*pid *=.*" --replace_string="pid = /run/php/php${phpversion}-fpm-$app.pid" --target_file="$globalphpconf"
ynh_replace_string --match_string="^[; ]*error_log *=.*" --replace_string="error_log = /var/log/php/fpm-php.$app.log" --target_file="$globalphpconf"
ynh_replace_string --match_string="^[; ]*syslog.ident *=.*" --replace_string="syslog.ident = php-fpm-$app" --target_file="$globalphpconf"
ynh_replace_string --match_string="^[; ]*include *=.*" --replace_string="include = $finalphpconf" --target_file="$globalphpconf"
# Create a config for a dedicated php-fpm service for the app
echo "[Unit]
# Create a config for a dedicated php-fpm service for the app
echo "[Unit]
Description=PHP $phpversion FastCGI Process Manager for $app
After=network.target
@ -243,18 +247,18 @@ ExecReload=/bin/kill -USR2 \$MAINPID
WantedBy=multi-user.target
" > ../conf/$fpm_service
# Create this dedicated php-fpm service
ynh_add_systemd_config --service=$fpm_service --template=$fpm_service
# Integrate the service in YunoHost admin panel
yunohost service add $fpm_service --log /var/log/php/fpm-php.$app.log --log_type file --description "Php-fpm dedicated to $app"
# Configure log rotate
ynh_use_logrotate --logfile=/var/log/php
# Restart the service, as this service is either stopped or only for this app
ynh_systemd_action --service_name=$fpm_service --action=restart
else
# Reload php, to not impact other parts of the system using php
ynh_systemd_action --service_name=$fpm_service --action=reload
fi
# Create this dedicated php-fpm service
ynh_add_systemd_config --service=$fpm_service --template=$fpm_service
# Integrate the service in YunoHost admin panel
yunohost service add $fpm_service --log /var/log/php/fpm-php.$app.log --log_type file --description "Php-fpm dedicated to $app"
# Configure log rotate
ynh_use_logrotate --logfile=/var/log/php
# Restart the service, as this service is either stopped or only for this app
ynh_systemd_action --service_name=$fpm_service --action=restart
else
# Reload php, to not impact other parts of the system using php
ynh_systemd_action --service_name=$fpm_service --action=reload
fi
}
# Remove the dedicated php-fpm config
@ -263,43 +267,44 @@ WantedBy=multi-user.target
#
# Requires YunoHost version 2.7.2 or higher.
ynh_remove_fpm_config () {
local fpm_config_dir=$(ynh_app_setting_get --app=$app --key=fpm_config_dir)
local fpm_service=$(ynh_app_setting_get --app=$app --key=fpm_service)
local dedicated_service=$(ynh_app_setting_get --app=$app --key=fpm_dedicated_service)
dedicated_service=${dedicated_service:-0}
# Get the version of php used by this app
local phpversion=$(ynh_app_setting_get $app phpversion)
local fpm_config_dir=$(ynh_app_setting_get --app=$app --key=fpm_config_dir)
local fpm_service=$(ynh_app_setting_get --app=$app --key=fpm_service)
local dedicated_service=$(ynh_app_setting_get --app=$app --key=fpm_dedicated_service)
dedicated_service=${dedicated_service:-0}
# Get the version of php used by this app
local phpversion=$(ynh_app_setting_get $app phpversion)
# Assume default PHP-FPM version by default
phpversion="${phpversion:-$YNH_DEFAULT_PHP_VERSION}"
# Assume default PHP-FPM version by default
phpversion="${phpversion:-$YNH_DEFAULT_PHP_VERSION}"
# Assume default php files if not set
if [ -z "$fpm_config_dir" ]; then
fpm_config_dir="/etc/php/$YNH_DEFAULT_PHP_VERSION/fpm"
fpm_service="php$YNH_DEFAULT_PHP_VERSION-fpm"
fi
# Assume default php files if not set
if [ -z "$fpm_config_dir" ]
then
fpm_config_dir="/etc/php/$YNH_DEFAULT_PHP_VERSION/fpm"
fpm_service="php$YNH_DEFAULT_PHP_VERSION-fpm"
fi
if [ $dedicated_service -eq 1 ]
then
# Remove the dedicated service php-fpm service for the app
ynh_remove_systemd_config --service=$fpm_service
# Remove the global php-fpm conf
ynh_secure_remove --file="$fpm_config_dir/php-fpm-$app.conf"
# Remove the service from the list of services known by Yunohost
yunohost service remove $fpm_service
elif ynh_package_is_installed --package="php${phpversion}-fpm"; then
ynh_systemd_action --service_name=$fpm_service --action=reload
fi
if [ $dedicated_service -eq 1 ]
then
# Remove the dedicated service php-fpm service for the app
ynh_remove_systemd_config --service=$fpm_service
# Remove the global php-fpm conf
ynh_secure_remove --file="$fpm_config_dir/php-fpm-$app.conf"
# Remove the service from the list of services known by Yunohost
yunohost service remove $fpm_service
elif ynh_package_is_installed --package="php${phpversion}-fpm"; then
ynh_systemd_action --service_name=$fpm_service --action=reload
fi
ynh_secure_remove --file="$fpm_config_dir/pool.d/$app.conf"
ynh_exec_warn_less ynh_secure_remove --file="$fpm_config_dir/conf.d/20-$app.ini"
ynh_secure_remove --file="$fpm_config_dir/pool.d/$app.conf"
ynh_exec_warn_less ynh_secure_remove --file="$fpm_config_dir/conf.d/20-$app.ini"
# If the php version used is not the default version for YunoHost
if [ "$phpversion" != "$YNH_DEFAULT_PHP_VERSION" ]
then
# Remove this specific version of php
ynh_remove_php
fi
# If the php version used is not the default version for YunoHost
if [ "$phpversion" != "$YNH_DEFAULT_PHP_VERSION" ]
then
# Remove this specific version of php
ynh_remove_php
fi
}
# Install another version of php.
@ -307,53 +312,55 @@ ynh_remove_fpm_config () {
# [internal]
#
# usage: ynh_install_php --phpversion=phpversion [--package=packages]
# | arg: -v, --phpversion - Version of php to install.
# | arg: -p, --package - Additionnal php packages to install
# | arg: -v, --phpversion= - Version of php to install.
# | arg: -p, --package= - Additionnal php packages to install
#
# Requires YunoHost version 3.8.1 or higher.
ynh_install_php () {
# Declare an array to define the options of this helper.
local legacy_args=vp
declare -Ar args_array=( [v]=phpversion= [p]=package= )
local phpversion
local package
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
package=${package:-}
# Declare an array to define the options of this helper.
local legacy_args=vp
local -A args_array=( [v]=phpversion= [p]=package= )
local phpversion
local package
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
package=${package:-}
# Store phpversion into the config of this app
ynh_app_setting_set $app phpversion $phpversion
# Store phpversion into the config of this app
ynh_app_setting_set $app phpversion $phpversion
if [ "$phpversion" == "$YNH_DEFAULT_PHP_VERSION" ]
then
ynh_die "Do not use ynh_install_php to install php$YNH_DEFAULT_PHP_VERSION"
fi
if [ "$phpversion" == "$YNH_DEFAULT_PHP_VERSION" ]
then
ynh_die "Do not use ynh_install_php to install php$YNH_DEFAULT_PHP_VERSION"
fi
# Create the file if doesn't exist already
touch /etc/php/ynh_app_version
# Create the file if doesn't exist already
touch /etc/php/ynh_app_version
# Do not add twice the same line
if ! grep --quiet "$YNH_APP_INSTANCE_NAME:" "/etc/php/ynh_app_version"
then
# Store the ID of this app and the version of php requested for it
echo "$YNH_APP_INSTANCE_NAME:$phpversion" | tee --append "/etc/php/ynh_app_version"
fi
# Do not add twice the same line
if ! grep --quiet "$YNH_APP_INSTANCE_NAME:" "/etc/php/ynh_app_version"
then
# Store the ID of this app and the version of php requested for it
echo "$YNH_APP_INSTANCE_NAME:$phpversion" | tee --append "/etc/php/ynh_app_version"
fi
# Add an extra repository for those packages
ynh_install_extra_repo --repo="https://packages.sury.org/php/ $(lsb_release -sc) main" --key="https://packages.sury.org/php/apt.gpg" --priority=995 --name=extra_php_version
# Add an extra repository for those packages
ynh_install_extra_repo --repo="https://packages.sury.org/php/ $(ynh_get_debian_release) main" --key="https://packages.sury.org/php/apt.gpg" --priority=995 --name=extra_php_version
# Install requested dependencies from this extra repository.
# Install php-fpm first, otherwise php will install apache as a dependency.
ynh_add_app_dependencies --package="php${phpversion}-fpm"
ynh_add_app_dependencies --package="php$phpversion php${phpversion}-common $package"
# Install requested dependencies from this extra repository.
# Install php-fpm first, otherwise php will install apache as a dependency.
ynh_add_app_dependencies --package="php${phpversion}-fpm"
ynh_add_app_dependencies --package="php$phpversion php${phpversion}-common $package"
# Set the default php version back as the default version for php-cli.
update-alternatives --set php /usr/bin/php$YNH_DEFAULT_PHP_VERSION
# Set the default php version back as the default version for php-cli.
update-alternatives --set php /usr/bin/php$YNH_DEFAULT_PHP_VERSION
# Pin this extra repository after packages are installed to prevent sury of doing shit
ynh_pin_repo --package="*" --pin="origin \"packages.sury.org\"" --priority=200 --name=extra_php_version
ynh_pin_repo --package="php${YNH_DEFAULT_PHP_VERSION}*" --pin="origin \"packages.sury.org\"" --priority=600 --name=extra_php_version --append
# Pin this extra repository after packages are installed to prevent sury of doing shit
ynh_pin_repo --package="*" --pin="origin \"packages.sury.org\"" --priority=200 --name=extra_php_version
ynh_pin_repo --package="php${YNH_DEFAULT_PHP_VERSION}*" --pin="origin \"packages.sury.org\"" --priority=600 --name=extra_php_version --append
# Advertise service in admin panel
yunohost service add php${phpversion}-fpm --log "/var/log/php${phpversion}-fpm.log"
# Advertise service in admin panel
yunohost service add php${phpversion}-fpm --log "/var/log/php${phpversion}-fpm.log"
}
# Remove the specific version of php used by the app.
@ -361,36 +368,38 @@ ynh_install_php () {
# [internal]
#
# usage: ynh_install_php
#
# Requires YunoHost version 3.8.1 or higher.
ynh_remove_php () {
# Get the version of php used by this app
local phpversion=$(ynh_app_setting_get $app phpversion)
# Get the version of php used by this app
local phpversion=$(ynh_app_setting_get $app phpversion)
if [ "$phpversion" == "$YNH_DEFAULT_PHP_VERSION" ] || [ -z "$phpversion" ]
then
if [ "$phpversion" == "$YNH_DEFAULT_PHP_VERSION" ]
then
ynh_print_err "Do not use ynh_remove_php to remove php$YNH_DEFAULT_PHP_VERSION !"
fi
return 0
fi
if [ "$phpversion" == "$YNH_DEFAULT_PHP_VERSION" ] || [ -z "$phpversion" ]
then
if [ "$phpversion" == "$YNH_DEFAULT_PHP_VERSION" ]
then
ynh_print_err "Do not use ynh_remove_php to remove php$YNH_DEFAULT_PHP_VERSION !"
fi
return 0
fi
# Create the file if doesn't exist already
touch /etc/php/ynh_app_version
# Create the file if doesn't exist already
touch /etc/php/ynh_app_version
# Remove the line for this app
sed --in-place "/$YNH_APP_INSTANCE_NAME:$phpversion/d" "/etc/php/ynh_app_version"
# Remove the line for this app
sed --in-place "/$YNH_APP_INSTANCE_NAME:$phpversion/d" "/etc/php/ynh_app_version"
# If no other app uses this version of php, remove it.
if ! grep --quiet "$phpversion" "/etc/php/ynh_app_version"
then
# Remove the service from the admin panel
if ynh_package_is_installed --package="php${phpversion}-fpm"; then
yunohost service remove php${phpversion}-fpm
fi
# If no other app uses this version of php, remove it.
if ! grep --quiet "$phpversion" "/etc/php/ynh_app_version"
then
# Remove the service from the admin panel
if ynh_package_is_installed --package="php${phpversion}-fpm"; then
yunohost service remove php${phpversion}-fpm
fi
# Purge php dependencies for this version.
ynh_package_autopurge "php$phpversion php${phpversion}-fpm php${phpversion}-common"
fi
# Purge php dependencies for this version.
ynh_package_autopurge "php$phpversion php${phpversion}-fpm php${phpversion}-common"
fi
}
# Define the values to configure php-fpm
@ -398,7 +407,7 @@ ynh_remove_php () {
# [internal]
#
# usage: ynh_get_scalable_phpfpm --usage=usage --footprint=footprint [--print]
# | arg: -f, --footprint - Memory footprint of the service (low/medium/high).
# | arg: -f, --footprint= - Memory footprint of the service (low/medium/high).
# low - Less than 20Mb of ram by pool.
# medium - Between 20Mb and 40Mb of ram by pool.
# high - More than 40Mb of ram by pool.
@ -406,16 +415,16 @@ ynh_remove_php () {
# To have this value, use the following command and stress the service.
# watch -n0.5 ps -o user,cmd,%cpu,rss -u APP
#
# | arg: -u, --usage - Expected usage of the service (low/medium/high).
# | arg: -u, --usage= - Expected usage of the service (low/medium/high).
# low - Personal usage, behind the sso.
# medium - Low usage, few people or/and publicly accessible.
# high - High usage, frequently visited website.
#
# | arg: -p, --print - Print the result (intended for debug purpose only when packaging the app)
# | arg: -p, --print - Print the result (intended for debug purpose only when packaging the app)
ynh_get_scalable_phpfpm () {
local legacy_args=ufp
# Declare an array to define the options of this helper.
declare -Ar args_array=( [u]=usage= [f]=footprint= [p]=print )
local -A args_array=( [u]=usage= [f]=footprint= [p]=print )
local usage
local footprint
local print
@ -524,18 +533,22 @@ ynh_get_scalable_phpfpm () {
ynh_debug --message="Footprint=${footprint}Mb by pool."
ynh_debug --message="Process manager=$php_pm"
ynh_debug --message="Max RAM=${max_ram}Mb"
if [ "$php_pm" != "static" ]; then
if [ "$php_pm" != "static" ]
then
ynh_debug --message="\nMax estimated footprint=$(( $php_max_children * $footprint ))"
ynh_debug --message="Min estimated footprint=$(( $php_min_spare_servers * $footprint ))"
fi
if [ "$php_pm" = "dynamic" ]; then
if [ "$php_pm" = "dynamic" ]
then
ynh_debug --message="Estimated average footprint=$(( $php_max_spare_servers * $footprint ))"
elif [ "$php_pm" = "static" ]; then
elif [ "$php_pm" = "static" ]
then
ynh_debug --message="Estimated footprint=$(( $php_max_children * $footprint ))"
fi
ynh_debug --message="\nRaw php-fpm values:"
ynh_debug --message="pm.max_children = $php_max_children"
if [ "$php_pm" = "dynamic" ]; then
if [ "$php_pm" = "dynamic" ]
then
ynh_debug --message="pm.start_servers = $php_start_servers"
ynh_debug --message="pm.min_spare_servers = $php_min_spare_servers"
ynh_debug --message="pm.max_spare_servers = $php_max_spare_servers"

View file

@ -9,65 +9,65 @@ PSQL_ROOT_PWD_FILE=/etc/yunohost/psql
# ynh_psql_connect_as 'user' 'pass' < /path/to/file.sql
#
# usage: ynh_psql_connect_as --user=user --password=password [--database=database]
# | arg: -u, --user - the user name to connect as
# | arg: -p, --password - the user password
# | arg: -d, --database - the database to connect to
# | arg: -u, --user= - the user name to connect as
# | arg: -p, --password= - the user password
# | arg: -d, --database= - the database to connect to
#
# Requires YunoHost version 3.5.0 or higher.
ynh_psql_connect_as() {
# Declare an array to define the options of this helper.
local legacy_args=upd
declare -Ar args_array=([u]=user= [p]=password= [d]=database=)
local user
local password
local database
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
database="${database:-}"
# Declare an array to define the options of this helper.
local legacy_args=upd
local -A args_array=([u]=user= [p]=password= [d]=database=)
local user
local password
local database
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
database="${database:-}"
sudo --login --user=postgres PGUSER="$user" PGPASSWORD="$password" psql "$database"
sudo --login --user=postgres PGUSER="$user" PGPASSWORD="$password" psql "$database"
}
# Execute a command as root user
#
# usage: ynh_psql_execute_as_root --sql=sql [--database=database]
# | arg: -s, --sql - the SQL command to execute
# | arg: -d, --database - the database to connect to
# | arg: -s, --sql= - the SQL command to execute
# | arg: -d, --database= - the database to connect to
#
# Requires YunoHost version 3.5.0 or higher.
ynh_psql_execute_as_root() {
# Declare an array to define the options of this helper.
local legacy_args=sd
declare -Ar args_array=([s]=sql= [d]=database=)
local sql
local database
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
database="${database:-}"
# Declare an array to define the options of this helper.
local legacy_args=sd
local -A args_array=([s]=sql= [d]=database=)
local sql
local database
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
database="${database:-}"
ynh_psql_connect_as --user="postgres" --password="$(cat $PSQL_ROOT_PWD_FILE)" \
--database="$database" <<<"$sql"
ynh_psql_connect_as --user="postgres" --password="$(cat $PSQL_ROOT_PWD_FILE)" \
--database="$database" <<<"$sql"
}
# Execute a command from a file as root user
#
# usage: ynh_psql_execute_file_as_root --file=file [--database=database]
# | arg: -f, --file - the file containing SQL commands
# | arg: -d, --database - the database to connect to
# | arg: -f, --file= - the file containing SQL commands
# | arg: -d, --database= - the database to connect to
#
# Requires YunoHost version 3.5.0 or higher.
ynh_psql_execute_file_as_root() {
# Declare an array to define the options of this helper.
local legacy_args=fd
declare -Ar args_array=([f]=file= [d]=database=)
local file
local database
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
database="${database:-}"
# Declare an array to define the options of this helper.
local legacy_args=fd
local -A args_array=([f]=file= [d]=database=)
local file
local database
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
database="${database:-}"
ynh_psql_connect_as --user="postgres" --password="$(cat $PSQL_ROOT_PWD_FILE)" \
--database="$database" <"$file"
ynh_psql_connect_as --user="postgres" --password="$(cat $PSQL_ROOT_PWD_FILE)" \
--database="$database" <"$file"
}
# Create a database and grant optionnaly privilegies to a user
@ -80,17 +80,18 @@ ynh_psql_execute_file_as_root() {
#
# Requires YunoHost version 3.5.0 or higher.
ynh_psql_create_db() {
local db=$1
local user=${2:-}
local db=$1
local user=${2:-}
local sql="CREATE DATABASE ${db};"
local sql="CREATE DATABASE ${db};"
# grant all privilegies to user
if [ -n "$user" ]; then
sql+="GRANT ALL PRIVILEGES ON DATABASE ${db} TO ${user} WITH GRANT OPTION;"
fi
# grant all privilegies to user
if [ -n "$user" ]; then
sql+="ALTER DATABASE ${db} OWNER TO ${user};"
sql+="GRANT ALL PRIVILEGES ON DATABASE ${db} TO ${user} WITH GRANT OPTION;"
fi
ynh_psql_execute_as_root --sql="$sql"
ynh_psql_execute_as_root --sql="$sql"
}
# Drop a database
@ -105,12 +106,12 @@ ynh_psql_create_db() {
#
# Requires YunoHost version 3.5.0 or higher.
ynh_psql_drop_db() {
local db=$1
# First, force disconnection of all clients connected to the database
# https://stackoverflow.com/questions/17449420/postgresql-unable-to-drop-database-because-of-some-auto-connections-to-db
ynh_psql_execute_as_root --sql="REVOKE CONNECT ON DATABASE $db FROM public;" --database="$db"
ynh_psql_execute_as_root --sql="SELECT pg_terminate_backend (pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = '$db' AND pid <> pg_backend_pid();" --database="$db"
sudo --login --user=postgres dropdb $db
local db=$1
# First, force disconnection of all clients connected to the database
# https://stackoverflow.com/questions/17449420/postgresql-unable-to-drop-database-because-of-some-auto-connections-to-db
ynh_psql_execute_as_root --sql="REVOKE CONNECT ON DATABASE $db FROM public;" --database="$db"
ynh_psql_execute_as_root --sql="SELECT pg_terminate_backend (pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = '$db' AND pid <> pg_backend_pid();" --database="$db"
sudo --login --user=postgres dropdb $db
}
# Dump a database
@ -118,19 +119,19 @@ ynh_psql_drop_db() {
# example: ynh_psql_dump_db 'roundcube' > ./dump.sql
#
# usage: ynh_psql_dump_db --database=database
# | arg: -d, --database - the database name to dump
# | arg: -d, --database= - the database name to dump
# | ret: the psqldump output
#
# Requires YunoHost version 3.5.0 or higher.
ynh_psql_dump_db() {
# Declare an array to define the options of this helper.
local legacy_args=d
declare -Ar args_array=([d]=database=)
local database
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=d
local -A args_array=([d]=database=)
local database
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
sudo --login --user=postgres pg_dump "$database"
sudo --login --user=postgres pg_dump "$database"
}
# Create a user
@ -143,47 +144,55 @@ ynh_psql_dump_db() {
#
# Requires YunoHost version 3.5.0 or higher.
ynh_psql_create_user() {
local user=$1
local pwd=$2
ynh_psql_execute_as_root --sql="CREATE USER $user WITH ENCRYPTED PASSWORD '$pwd'"
local user=$1
local pwd=$2
ynh_psql_execute_as_root --sql="CREATE USER $user WITH ENCRYPTED PASSWORD '$pwd'"
}
# Check if a psql user exists
#
# usage: ynh_psql_user_exists --user=user
# | arg: -u, --user - the user for which to check existence
# | arg: -u, --user= - the user for which to check existence
# | exit: Return 1 if the user doesn't exist, 0 otherwise
#
# Requires YunoHost version 3.5.0 or higher.
ynh_psql_user_exists() {
# Declare an array to define the options of this helper.
local legacy_args=u
declare -Ar args_array=([u]=user=)
local user
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=u
local -A args_array=([u]=user=)
local user
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
if ! sudo --login --user=postgres PGUSER="postgres" PGPASSWORD="$(cat $PSQL_ROOT_PWD_FILE)" psql -tAc "SELECT rolname FROM pg_roles WHERE rolname='$user';" | grep --quiet "$user" ; then
return 1
else
return 0
fi
if ! sudo --login --user=postgres PGUSER="postgres" PGPASSWORD="$(cat $PSQL_ROOT_PWD_FILE)" psql -tAc "SELECT rolname FROM pg_roles WHERE rolname='$user';" | grep --quiet "$user"
then
return 1
else
return 0
fi
}
# Check if a psql database exists
#
# usage: ynh_psql_database_exists --database=database
# | arg: -d, --database - the database for which to check existence
# | arg: -d, --database= - the database for which to check existence
# | exit: Return 1 if the database doesn't exist, 0 otherwise
#
# Requires YunoHost version 3.5.0 or higher.
ynh_psql_database_exists() {
# Declare an array to define the options of this helper.
local legacy_args=d
declare -Ar args_array=([d]=database=)
local database
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=d
local -A args_array=([d]=database=)
local database
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
if ! sudo --login --user=postgres PGUSER="postgres" PGPASSWORD="$(cat $PSQL_ROOT_PWD_FILE)" psql -tAc "SELECT datname FROM pg_database WHERE datname='$database';" | grep --quiet "$database"; then
return 1
else
return 0
fi
if ! sudo --login --user=postgres PGUSER="postgres" PGPASSWORD="$(cat $PSQL_ROOT_PWD_FILE)" psql -tAc "SELECT datname FROM pg_database WHERE datname='$database';" | grep --quiet "$database"
then
return 1
else
return 0
fi
}
# Drop a user
@ -195,85 +204,96 @@ ynh_psql_database_exists() {
#
# Requires YunoHost version 3.5.0 or higher.
ynh_psql_drop_user() {
ynh_psql_execute_as_root --sql="DROP USER ${1};"
ynh_psql_execute_as_root --sql="DROP USER ${1};"
}
# Create a database, an user and its password. Then store the password in the app's config
#
# usage: ynh_psql_setup_db --db_user=user --db_name=name [--db_pwd=pwd]
# | arg: -u, --db_user= - Owner of the database
# | arg: -n, --db_name= - Name of the database
# | arg: -p, --db_pwd= - Password of the database. If not given, a password will be generated
#
# After executing this helper, the password of the created database will be available in $db_pwd
# It will also be stored as "psqlpwd" into the app settings.
#
# usage: ynh_psql_setup_db --db_user=user --db_name=name [--db_pwd=pwd]
# | arg: -u, --db_user - Owner of the database
# | arg: -n, --db_name - Name of the database
# | arg: -p, --db_pwd - Password of the database. If not given, a password will be generated
# Requires YunoHost version 2.7.13 or higher.
ynh_psql_setup_db() {
# Declare an array to define the options of this helper.
local legacy_args=unp
declare -Ar args_array=([u]=db_user= [n]=db_name= [p]=db_pwd=)
local db_user
local db_name
db_pwd=""
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=unp
local -A args_array=([u]=db_user= [n]=db_name= [p]=db_pwd=)
local db_user
local db_name
db_pwd=""
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local new_db_pwd=$(ynh_string_random) # Generate a random password
# If $db_pwd is not given, use new_db_pwd instead for db_pwd
db_pwd="${db_pwd:-$new_db_pwd}"
local new_db_pwd=$(ynh_string_random) # Generate a random password
# If $db_pwd is not given, use new_db_pwd instead for db_pwd
db_pwd="${db_pwd:-$new_db_pwd}"
if ! ynh_psql_user_exists --user=$db_user; then
ynh_psql_create_user "$db_user" "$db_pwd"
fi
if ! ynh_psql_user_exists --user=$db_user; then
ynh_psql_create_user "$db_user" "$db_pwd"
fi
ynh_psql_create_db "$db_name" "$db_user" # Create the database
ynh_app_setting_set --app=$app --key=psqlpwd --value=$db_pwd # Store the password in the app's config
ynh_psql_create_db "$db_name" "$db_user" # Create the database
ynh_app_setting_set --app=$app --key=psqlpwd --value=$db_pwd # Store the password in the app's config
}
# Remove a database if it exists, and the associated user
#
# usage: ynh_psql_remove_db --db_user=user --db_name=name
# | arg: -u, --db_user - Owner of the database
# | arg: -n, --db_name - Name of the database
# | arg: -u, --db_user= - Owner of the database
# | arg: -n, --db_name= - Name of the database
#
# Requires YunoHost version 2.7.13 or higher.
ynh_psql_remove_db() {
# Declare an array to define the options of this helper.
local legacy_args=un
declare -Ar args_array=([u]=db_user= [n]=db_name=)
local db_user
local db_name
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=un
local -A args_array=([u]=db_user= [n]=db_name=)
local db_user
local db_name
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
if ynh_psql_database_exists --database=$db_name; then # Check if the database exists
ynh_psql_drop_db $db_name # Remove the database
else
ynh_print_warn --message="Database $db_name not found"
fi
if ynh_psql_database_exists --database=$db_name
then # Check if the database exists
ynh_psql_drop_db $db_name # Remove the database
else
ynh_print_warn --message="Database $db_name not found"
fi
# Remove psql user if it exists
if ynh_psql_user_exists --user=$db_user; then
ynh_psql_drop_user $db_user
else
ynh_print_warn --message="User $db_user not found"
fi
# Remove psql user if it exists
if ynh_psql_user_exists --user=$db_user
then
ynh_psql_drop_user $db_user
else
ynh_print_warn --message="User $db_user not found"
fi
}
# Create a master password and set up global settings
# Please always call this script in install and restore scripts
#
# usage: ynh_psql_test_if_first_run
#
# Requires YunoHost version 2.7.13 or higher.
ynh_psql_test_if_first_run() {
if [ -f "$PSQL_ROOT_PWD_FILE" ]; then
echo "PostgreSQL is already installed, no need to create master password"
if [ -f "$PSQL_ROOT_PWD_FILE" ]
then
ynh_print_info --message="PostgreSQL is already installed, no need to create master password"
return
fi
local psql_root_password="$(ynh_string_random)"
echo "$psql_root_password" >$PSQL_ROOT_PWD_FILE
if [ -e /etc/postgresql/9.4/ ]; then
if [ -e /etc/postgresql/9.4/ ]
then
local pg_hba=/etc/postgresql/9.4/main/pg_hba.conf
local logfile=/var/log/postgresql/postgresql-9.4-main.log
elif [ -e /etc/postgresql/9.6/ ]; then
elif [ -e /etc/postgresql/9.6/ ]
then
local pg_hba=/etc/postgresql/9.6/main/pg_hba.conf
local logfile=/var/log/postgresql/postgresql-9.6-main.log
else

View file

@ -3,14 +3,14 @@
# Get an application setting
#
# usage: ynh_app_setting_get --app=app --key=key
# | arg: -a, --app - the application id
# | arg: -k, --key - the setting to get
# | arg: -a, --app= - the application id
# | arg: -k, --key= - the setting to get
#
# Requires YunoHost version 2.2.4 or higher.
ynh_app_setting_get() {
# Declare an array to define the options of this helper.
local legacy_args=ak
declare -Ar args_array=( [a]=app= [k]=key= )
local -A args_array=( [a]=app= [k]=key= )
local app
local key
# Manage arguments with getopts
@ -22,15 +22,15 @@ ynh_app_setting_get() {
# Set an application setting
#
# usage: ynh_app_setting_set --app=app --key=key --value=value
# | arg: -a, --app - the application id
# | arg: -k, --key - the setting name to set
# | arg: -v, --value - the setting value to set
# | arg: -a, --app= - the application id
# | arg: -k, --key= - the setting name to set
# | arg: -v, --value= - the setting value to set
#
# Requires YunoHost version 2.2.4 or higher.
ynh_app_setting_set() {
# Declare an array to define the options of this helper.
local legacy_args=akv
declare -Ar args_array=( [a]=app= [k]=key= [v]=value= )
local -A args_array=( [a]=app= [k]=key= [v]=value= )
local app
local key
local value
@ -43,14 +43,14 @@ ynh_app_setting_set() {
# Delete an application setting
#
# usage: ynh_app_setting_delete --app=app --key=key
# | arg: -a, --app - the application id
# | arg: -k, --key - the setting to delete
# | arg: -a, --app= - the application id
# | arg: -k, --key= - the setting to delete
#
# Requires YunoHost version 2.2.4 or higher.
ynh_app_setting_delete() {
# Declare an array to define the options of this helper.
local legacy_args=ak
declare -Ar args_array=( [a]=app= [k]=key= )
local -A args_array=( [a]=app= [k]=key= )
local app
local key
# Manage arguments with getopts
@ -117,20 +117,20 @@ EOF
# example: ynh_webpath_available --domain=some.domain.tld --path_url=/coffee
#
# usage: ynh_webpath_available --domain=domain --path_url=path
# | arg: -d, --domain - the domain/host of the url
# | arg: -p, --path_url - the web path to check the availability of
# | arg: -d, --domain= - the domain/host of the url
# | arg: -p, --path_url= - the web path to check the availability of
#
# Requires YunoHost version 2.6.4 or higher.
ynh_webpath_available () {
# Declare an array to define the options of this helper.
local legacy_args=dp
declare -Ar args_array=( [d]=domain= [p]=path_url= )
local domain
local path_url
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=dp
local -A args_array=( [d]=domain= [p]=path_url= )
local domain
local path_url
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
yunohost domain url-available $domain $path_url
yunohost domain url-available $domain $path_url
}
# Register/book a web path for an app
@ -138,22 +138,22 @@ ynh_webpath_available () {
# example: ynh_webpath_register --app=wordpress --domain=some.domain.tld --path_url=/coffee
#
# usage: ynh_webpath_register --app=app --domain=domain --path_url=path
# | arg: -a, --app - the app for which the domain should be registered
# | arg: -d, --domain - the domain/host of the web path
# | arg: -p, --path_url - the web path to be registered
# | arg: -a, --app= - the app for which the domain should be registered
# | arg: -d, --domain= - the domain/host of the web path
# | arg: -p, --path_url= - the web path to be registered
#
# Requires YunoHost version 2.6.4 or higher.
ynh_webpath_register () {
# Declare an array to define the options of this helper.
local legacy_args=adp
declare -Ar args_array=( [a]=app= [d]=domain= [p]=path_url= )
local app
local domain
local path_url
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=adp
local -A args_array=( [a]=app= [d]=domain= [p]=path_url= )
local app
local domain
local path_url
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
yunohost app register-url $app $domain $path_url
yunohost app register-url $app $domain $path_url
}
# Create a new permission for the app
@ -164,13 +164,14 @@ ynh_webpath_register () {
# [--allowed group1 [ group2 ]] [--label "label"] [--show_tile true|false]
# [--protected true|false]
# | arg: permission - the name for the permission (by default a permission named "main" already exist)
# | arg: url - (optional) URL for which access will be allowed/forbidden
# | arg: additional_urls - (optional) List of additional URL for which access will be allowed/forbidden
# | arg: auth_header - (optional) Define for the URL of this permission, if SSOwat pass the authentication header to the application. Default is true
# | arg: allowed - (optional) A list of group/user to allow for the permission
# | arg: label - (optional) Define a name for the permission. This label will be shown on the SSO and in the admin. Default is "APP_LABEL (permission name)".
# | arg: show_tile - (optional) Define if a tile will be shown in the SSO
# | arg: protected - (optional) Define if this permission is protected. If it is protected the administrator
# | arg: url - (optional) URL for which access will be allowed/forbidden
# | arg: additional_urls - (optional) List of additional URL for which access will be allowed/forbidden
# | arg: auth_header - (optional) Define for the URL of this permission, if SSOwat pass the authentication header to the application. Default is true
# | arg: allowed - (optional) A list of group/user to allow for the permission
# | arg: label - (optional) Define a name for the permission. This label will be shown on the SSO and in the admin.
# | Default is "APP_LABEL (permission name)".
# | arg: show_tile - (optional) Define if a tile will be shown in the SSO
# | arg: protected - (optional) Define if this permission is protected. If it is protected the administrator
# | won't be able to add or remove the visitors group of this permission.
# | By default it's 'true' (for the permission different than 'main').
#
@ -189,7 +190,7 @@ ynh_webpath_register () {
ynh_permission_create() {
# Declare an array to define the options of this helper.
local legacy_args=puAhaltP
declare -Ar args_array=( [p]=permission= [u]=url= [A]=additional_urls= [h]=auth_header= [a]=allowed= [l]=label= [t]=show_tile= [P]=protected= )
declare -A args_array=( [p]=permission= [u]=url= [A]=additional_urls= [h]=auth_header= [a]=allowed= [l]=label= [t]=show_tile= [P]=protected= )
local permission
local url
local additional_urls
@ -199,24 +200,30 @@ ynh_permission_create() {
local show_tile
local protected
ynh_handle_getopts_args "$@"
url=${url:-}
allowed=${allowed:-}
if [[ -n ${url:-} ]]; then
if [[ -n $url ]]
then
url=",url='$url'"
fi
if [[ -n ${additional_urls:-} ]]; then
if [[ -n $additional_urls ]]
then
additional_urls=",additional_urls=['${additional_urls//';'/"','"}']"
fi
if [[ -n ${auth_header:-} ]]; then
if [ $auth_header == "true" ]; then
if [[ -n $auth_header ]]
then
if [ $auth_header == "true" ]
then
auth_header=",auth_header=True"
else
auth_header=",auth_header=False"
fi
fi
if [[ -n ${allowed:-} ]]; then
if [[ -n $allowed ]]; then
allowed=",allowed=['${allowed//';'/"','"}']"
fi
@ -242,21 +249,21 @@ ynh_permission_create() {
fi
fi
yunohost tools shell -c "from yunohost.permission import permission_create; permission_create('$app.$permission' ${url:-} ${additional_urls:-} ${auth_header:-} ${allowed:-} ${label:-} ${show_tile:-} ${protected:-} , sync_perm=False)"
yunohost tools shell -c "from yunohost.permission import permission_create; permission_create('$app.$permission' $url $additional_urls $auth_header $allowed $label $show_tile $protected , sync_perm=False)"
}
# Remove a permission for the app (note that when the app is removed all permission is automatically removed)
#
# example: ynh_permission_delete --permission editors
# example: ynh_permission_delete --permission=editors
#
# usage: ynh_permission_delete --permission "permission"
# | arg: permission - the name for the permission (by default a permission named "main" is removed automatically when the app is removed)
# usage: ynh_permission_delete --permission="permission"
# | arg: -p, --permission= - the name for the permission (by default a permission named "main" is removed automatically when the app is removed)
#
# Requires YunoHost version 3.7.0 or higher.
ynh_permission_delete() {
# Declare an array to define the options of this helper.
local legacy_args=p
declare -Ar args_array=( [p]=permission= )
# Declare an array to define the options of this helper.
local legacy_args=p
local -A args_array=( [p]=permission= )
local permission
ynh_handle_getopts_args "$@"
@ -266,35 +273,37 @@ ynh_permission_delete() {
# Check if a permission exists
#
# usage: ynh_permission_exists --permission=permission
# | arg: -p, --permission - the permission to check
# | arg: -p, --permission= - the permission to check
# | exit: Return 1 if the permission doesn't exist, 0 otherwise
#
# Requires YunoHost version 3.7.0 or higher.
ynh_permission_exists() {
# Declare an array to define the options of this helper.
local legacy_args=p
declare -Ar args_array=( [p]=permission= )
# Declare an array to define the options of this helper.
local legacy_args=p
local -A args_array=( [p]=permission= )
local permission
ynh_handle_getopts_args "$@"
yunohost user permission list -s | grep -w -q "$app.$permission"
yunohost user permission list --short | grep --word-regexp --quiet "$app.$permission"
}
# Redefine the url associated to a permission
#
# usage: ynh_permission_url --permission "permission" [--url "url"] [--add_url "new-url" [ "other-new-url" ]] [--remove_url "old-url" [ "other-old-url"]]
# [--auth_header true|false][--clear_urls]
# | arg: permission - the name for the permission (by default a permission named "main" is removed automatically when the app is removed)
# | arg: url - (optional) URL for which access will be allowed/forbidden. Note that if you want to remove url you can pass an empty sting as arguments ("").
# | arg: add_url - (optional) List of additional url to add for which access will be allowed/forbidden.
# | arg: remove_url - (optional) List of additional url to remove for which access will be allowed/forbidden
# | arg: auth_header - (optional) Define for the URL of this permission, if SSOwat pass the authentication header to the application
# | arg: clear_urls - (optional) Clean all urls (url and additional_urls)
# | arg: permission - the name for the permission (by default a permission named "main" is removed automatically when the app is removed)
# | arg: url - (optional) URL for which access will be allowed/forbidden.
# | Note that if you want to remove url you can pass an empty sting as arguments ("").
# | arg: add_url - (optional) List of additional url to add for which access will be allowed/forbidden.
# | arg: remove_url - (optional) List of additional url to remove for which access will be allowed/forbidden
# | arg: auth_header - (optional) Define for the URL of this permission, if SSOwat pass the authentication header to the application
# | arg: clear_urls - (optional) Clean all urls (url and additional_urls)
#
# Requires YunoHost version 3.7.0 or higher.
ynh_permission_url() {
# Declare an array to define the options of this helper.
local legacy_args=puarhc
declare -Ar args_array=([p]=permission= [u]=url= [a]=add_url= [r]=remove_url= [h]=auth_header= [c]=clear_urls)
declare -A args_array=([p]=permission= [u]=url= [a]=add_url= [r]=remove_url= [h]=auth_header= [c]=clear_urls)
local permission
local url
local add_url
@ -302,20 +311,23 @@ ynh_permission_url() {
local auth_header
local clear_urls
ynh_handle_getopts_args "$@"
url=${url:-}
if [[ -n ${url:-} ]]; then
if [[ -n $url ]]
then
url=",url='$url'"
fi
if [[ -n ${add_url:-} ]]; then
if [[ -n $add_url ]]
then
add_url=",add_url=['${add_url//';'/"','"}']"
fi
if [[ -n ${remove_url:-} ]]; then
if [[ -n $remove_url ]]; then
remove_url=",remove_url=['${remove_url//';'/"','"}']"
fi
if [[ -n ${auth_header:-} ]]; then
if [[ -n $auth_header ]]; then
if [ $auth_header == "true" ]; then
auth_header=",auth_header=True"
else
@ -323,11 +335,12 @@ ynh_permission_url() {
fi
fi
if [[ -n ${clear_urls:-} ]] && [ $clear_urls -eq 1 ]; then
if [[ -n $clear_urls ]] && [ $clear_urls -eq 1 ]
then
clear_urls=",clear_urls=True"
fi
yunohost tools shell -c "from yunohost.permission import permission_url; permission_url('$app.$permission' ${url:-} ${add_url:-} ${remove_url:-} ${auth_header:-} ${clear_urls:-} )"
yunohost tools shell -c "from yunohost.permission import permission_url; permission_url('$app.$permission' $url $add_url $remove_url $auth_header $clear_urls )"
}
@ -335,20 +348,19 @@ ynh_permission_url() {
#
# usage: ynh_permission_update --permission "permission" [--add "group" ["group" ...]] [--remove "group" ["group" ...]]
# [--label "label"] [--show_tile true|false] [--protected true|false]
# | arg: permission - the name for the permission (by default a permission named "main" already exist)
# | arg: add - the list of group or users to enable add to the permission
# | arg: remove - the list of group or users to remove from the permission
# | arg: label - (optional) Define a name for the permission. This label will be shown on the SSO and in the admin.
# | arg: show_tile - (optional) Define if a tile will be shown in the SSO
# | arg: protected - (optional) Define if this permission is protected. If it is protected the administrator
# | won't be able to add or remove the visitors group of this permission.
# | arg: permission - the name for the permission (by default a permission named "main" already exist)
# | arg: add - the list of group or users to enable add to the permission
# | arg: remove - the list of group or users to remove from the permission
# | arg: label - (optional) Define a name for the permission. This label will be shown on the SSO and in the admin.
# | arg: show_tile - (optional) Define if a tile will be shown in the SSO
# | arg: protected - (optional) Define if this permission is protected. If it is protected the administrator
# | won't be able to add or remove the visitors group of this permission.
#
# example: ynh_permission_update --permission admin --add samdoe --remove all_users
# Requires YunoHost version 3.7.0 or higher.
ynh_permission_update() {
# Declare an array to define the options of this helper.
local legacy_args=parlsp
declare -Ar args_array=( [p]=permission= [a]=add= [r]=remove= [l]=label= [t]=show_tile= [P]=protected= )
declare -A args_array=( [p]=permission= [a]=add= [r]=remove= [l]=label= [t]=show_tile= [P]=protected= )
local permission
local add
local remove
@ -356,19 +368,24 @@ ynh_permission_update() {
local show_tile
local protected
ynh_handle_getopts_args "$@"
add=${add:-}
remove=${remove:-}
if [[ -n ${add:-} ]]; then
if [[ -n $add ]]
then
add=",add=['${add//';'/"','"}']"
fi
if [[ -n ${remove:-} ]]; then
if [[ -n $remove ]]
then
remove=",remove=['${remove//';'/"','"}']"
fi
if [[ -n ${label:-} ]]; then
if [[ -n $label ]]
then
label=",label='$label'"
fi
if [[ -n ${show_tile:-} ]]; then
if [[ -n $show_tile ]]; then
if [ $show_tile == "true" ]; then
show_tile=",show_tile=True"
else
@ -376,7 +393,7 @@ ynh_permission_update() {
fi
fi
if [[ -n ${protected:-} ]]; then
if [[ -n $protected ]]; then
if [ $protected == "true" ]; then
protected=",protected=True"
else
@ -384,22 +401,23 @@ ynh_permission_update() {
fi
fi
yunohost tools shell -c "from yunohost.permission import user_permission_update; user_permission_update('$app.$permission' ${add:-} ${remove:-} ${label:-} ${show_tile:-} ${protected:-} , force=True, sync_perm=False)"
yunohost tools shell -c "from yunohost.permission import user_permission_update; user_permission_update('$app.$permission' $add $remove $label $show_tile $protected , force=True, sync_perm=False)"
}
# Check if a permission exists
#
# usage: ynh_permission_has_user --permission=permission --user=user
# | arg: -p, --permission - the permission to check
# | arg: -u, --user - the user seek in the permission
# Check if a permission has an user
#
# example: ynh_permission_has_user --permission=main --user=visitors
#
# usage: ynh_permission_has_user --permission=permission --user=user
# | arg: -p, --permission= - the permission to check
# | arg: -u, --user= - the user seek in the permission
# | exit: Return 1 if the permission doesn't have that user or doesn't exist, 0 otherwise
#
# Requires YunoHost version 3.7.1 or higher.
ynh_permission_has_user() {
local legacy_args=pu
# Declare an array to define the options of this helper.
declare -Ar args_array=( [p]=permission= [u]=user= )
local -A args_array=( [p]=permission= [u]=user= )
local permission
local user
# Manage arguments with getopts
@ -410,5 +428,5 @@ ynh_permission_has_user() {
return 1
fi
yunohost user permission info "$app.$permission" | grep -w -q "$user"
yunohost user permission info "$app.$permission" | grep --word-regexp --quiet "$user"
}

View file

@ -5,29 +5,30 @@
# example: pwd=$(ynh_string_random --length=8)
#
# usage: ynh_string_random [--length=string_length]
# | arg: -l, --length - the string length to generate (default: 24)
# | arg: -l, --length= - the string length to generate (default: 24)
# | ret: the generated string
#
# Requires YunoHost version 2.2.4 or higher.
ynh_string_random() {
# Declare an array to define the options of this helper.
local legacy_args=l
declare -Ar args_array=( [l]=length= )
local -A args_array=( [l]=length= )
local length
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
length=${length:-24}
dd if=/dev/urandom bs=1 count=1000 2> /dev/null \
| tr -c -d 'A-Za-z0-9' \
| sed -n 's/\(.\{'"$length"'\}\).*/\1/p'
| tr --complement --delete 'A-Za-z0-9' \
| sed --quiet 's/\(.\{'"$length"'\}\).*/\1/p'
}
# Substitute/replace a string (or expression) by another in a file
#
# usage: ynh_replace_string --match_string=match_string --replace_string=replace_string --target_file=target_file
# | arg: -m, --match_string - String to be searched and replaced in the file
# | arg: -r, --replace_string - String that will replace matches
# | arg: -f, --target_file - File in which the string will be replaced.
# | arg: -m, --match_string= - String to be searched and replaced in the file
# | arg: -r, --replace_string= - String that will replace matches
# | arg: -f, --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
@ -35,53 +36,53 @@ ynh_string_random() {
#
# Requires YunoHost version 2.6.4 or higher.
ynh_replace_string () {
# Declare an array to define the options of this helper.
local legacy_args=mrf
declare -Ar args_array=( [m]=match_string= [r]=replace_string= [f]=target_file= )
local match_string
local replace_string
local target_file
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=mrf
local -A args_array=( [m]=match_string= [r]=replace_string= [f]=target_file= )
local match_string
local replace_string
local target_file
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local delimit=@
# Escape the delimiter if it's in the string.
match_string=${match_string//${delimit}/"\\${delimit}"}
replace_string=${replace_string//${delimit}/"\\${delimit}"}
local delimit=@
# Escape the delimiter if it's in the string.
match_string=${match_string//${delimit}/"\\${delimit}"}
replace_string=${replace_string//${delimit}/"\\${delimit}"}
sed --in-place "s${delimit}${match_string}${delimit}${replace_string}${delimit}g" "$target_file"
sed --in-place "s${delimit}${match_string}${delimit}${replace_string}${delimit}g" "$target_file"
}
# Substitute/replace a special string by another in a file
#
# usage: ynh_replace_special_string --match_string=match_string --replace_string=replace_string --target_file=target_file
# | arg: -m, --match_string - String to be searched and replaced in the file
# | arg: -r, --replace_string - String that will replace matches
# | arg: -t, --target_file - File in which the string will be replaced.
# | arg: -m, --match_string= - String to be searched and replaced in the file
# | arg: -r, --replace_string= - String that will replace matches
# | arg: -t, --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.
#
# Requires YunoHost version 2.7.7 or higher.
ynh_replace_special_string () {
# Declare an array to define the options of this helper.
local legacy_args=mrf
declare -Ar args_array=( [m]=match_string= [r]=replace_string= [f]=target_file= )
local match_string
local replace_string
local target_file
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=mrf
local -A args_array=( [m]=match_string= [r]=replace_string= [f]=target_file= )
local match_string
local replace_string
local target_file
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# 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//&/"\&"}
ynh_replace_string --match_string="$match_string" --replace_string="$replace_string" --target_file="$target_file"
ynh_replace_string --match_string="$match_string" --replace_string="$replace_string" --target_file="$target_file"
}
# Sanitize a string intended to be the name of a database
@ -90,24 +91,26 @@ ynh_replace_special_string () {
# example: dbname=$(ynh_sanitize_dbid $app)
#
# usage: ynh_sanitize_dbid --db_name=name
# | arg: -n, --db_name - name to correct/sanitize
# | arg: -n, --db_name= - name to correct/sanitize
# | ret: the corrected name
#
# Requires YunoHost version 2.2.4 or higher.
ynh_sanitize_dbid () {
# Declare an array to define the options of this helper.
local legacy_args=n
declare -Ar args_array=( [n]=db_name= )
local db_name
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=n
local -A args_array=( [n]=db_name= )
local db_name
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# We should avoid having - and . in the name of databases. They are replaced by _
echo ${db_name//[-.]/_}
# We should avoid having - and . in the name of databases. They are replaced by _
echo ${db_name//[-.]/_}
}
# Normalize the url path syntax
#
# [internal]
#
# Handle the slash at the beginning of path and its absence at ending
# Return a normalized url path
#
@ -119,23 +122,23 @@ ynh_sanitize_dbid () {
# ynh_normalize_url_path / # -> /
#
# usage: ynh_normalize_url_path --path_url=path_to_normalize
# | arg: -p, --path_url - URL path to normalize before using it
# | arg: -p, --path_url= - URL path to normalize before using it
#
# Requires YunoHost version 2.6.4 or higher.
ynh_normalize_url_path () {
# Declare an array to define the options of this helper.
local legacy_args=p
declare -Ar args_array=( [p]=path_url= )
local path_url
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=p
local -A args_array=( [p]=path_url= )
local path_url
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
test -n "$path_url" || ynh_die --message="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
fi
if [ "${path_url:${#path_url}-1}" == "/" ] && [ ${#path_url} -gt 1 ]; then # If the last character is a / and that not the only character.
path_url="${path_url:0:${#path_url}-1}" # Delete the last character
fi
echo $path_url
test -n "$path_url" || ynh_die --message="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
fi
if [ "${path_url:${#path_url}-1}" == "/" ] && [ ${#path_url} -gt 1 ]; then # If the last character is a / and that not the only character.
path_url="${path_url:0:${#path_url}-1}" # Delete the last character
fi
echo $path_url
}

View file

@ -3,8 +3,8 @@
# Create a dedicated systemd config
#
# usage: ynh_add_systemd_config [--service=service] [--template=template]
# | arg: -s, --service - Service name (optionnal, $app by default)
# | arg: -t, --template - Name of template file (optionnal, this is 'systemd' by default, meaning ./conf/systemd.service will be used as template)
# | arg: -s, --service= - Service name (optionnal, $app by default)
# | arg: -t, --template= - Name of template file (optionnal, this is 'systemd' by default, meaning ./conf/systemd.service will be used as template)
#
# This will use the template ../conf/<templatename>.service
# to generate a systemd config, by replacing the following keywords
@ -14,103 +14,106 @@
# __APP__ by $app
# __FINALPATH__ by $final_path
#
# Requires YunoHost version 2.7.2 or higher.
# Requires YunoHost version 2.7.11 or higher.
ynh_add_systemd_config () {
# Declare an array to define the options of this helper.
local legacy_args=st
declare -Ar args_array=( [s]=service= [t]=template= )
local service
local template
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local service="${service:-$app}"
local template="${template:-systemd.service}"
# Declare an array to define the options of this helper.
local legacy_args=st
local -A args_array=( [s]=service= [t]=template= )
local service
local template
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local service="${service:-$app}"
local template="${template:-systemd.service}"
finalsystemdconf="/etc/systemd/system/$service.service"
ynh_backup_if_checksum_is_different --file="$finalsystemdconf"
cp ../conf/$template "$finalsystemdconf"
finalsystemdconf="/etc/systemd/system/$service.service"
ynh_backup_if_checksum_is_different --file="$finalsystemdconf"
cp ../conf/$template "$finalsystemdconf"
# To avoid a break by set -u, use a void substitution ${var:-}. If the variable is not set, it's simply set with an empty variable.
# Substitute in a nginx config file only if the variable is not empty
if test -n "${final_path:-}"; then
ynh_replace_string --match_string="__FINALPATH__" --replace_string="$final_path" --target_file="$finalsystemdconf"
fi
if test -n "${app:-}"; then
ynh_replace_string --match_string="__APP__" --replace_string="$app" --target_file="$finalsystemdconf"
fi
ynh_store_file_checksum --file="$finalsystemdconf"
# To avoid a break by set -u, use a void substitution ${var:-}. If the variable is not set, it's simply set with an empty variable.
# Substitute in a nginx config file only if the variable is not empty
if [ -n "${final_path:-}" ]; then
ynh_replace_string --match_string="__FINALPATH__" --replace_string="$final_path" --target_file="$finalsystemdconf"
fi
if [ -n "${app:-}" ]; then
ynh_replace_string --match_string="__APP__" --replace_string="$app" --target_file="$finalsystemdconf"
fi
ynh_store_file_checksum --file="$finalsystemdconf"
chown root: "$finalsystemdconf"
systemctl enable $service
systemctl daemon-reload
chown root: "$finalsystemdconf"
systemctl enable $service
systemctl daemon-reload
}
# Remove the dedicated systemd config
#
# usage: ynh_remove_systemd_config [--service=service]
# | arg: -s, --service - Service name (optionnal, $app by default)
# | arg: -s, --service= - Service name (optionnal, $app by default)
#
# Requires YunoHost version 2.7.2 or higher.
ynh_remove_systemd_config () {
# Declare an array to define the options of this helper.
local legacy_args=s
declare -Ar args_array=( [s]=service= )
local service
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local service="${service:-$app}"
# Declare an array to define the options of this helper.
local legacy_args=s
local -A args_array=( [s]=service= )
local service
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local service="${service:-$app}"
local finalsystemdconf="/etc/systemd/system/$service.service"
if [ -e "$finalsystemdconf" ]; then
ynh_systemd_action --service_name=$service --action=stop
systemctl disable $service
ynh_secure_remove --file="$finalsystemdconf"
systemctl daemon-reload
fi
local finalsystemdconf="/etc/systemd/system/$service.service"
if [ -e "$finalsystemdconf" ]
then
ynh_systemd_action --service_name=$service --action=stop
systemctl disable $service
ynh_secure_remove --file="$finalsystemdconf"
systemctl daemon-reload
fi
}
# Start (or other actions) a service, print a log in case of failure and optionnaly wait until the service is completely started
#
# usage: ynh_systemd_action [-n service_name] [-a action] [ [-l "line to match"] [-p log_path] [-t timeout] [-e length] ]
# usage: ynh_systemd_action [--service_name=service_name] [--action=action] [ [--line_match="line to match"] [--log_path=log_path] [--timeout=300] [--length=20] ]
# | arg: -n, --service_name= - Name of the service to start. Default : $app
# | arg: -a, --action= - Action to perform with systemctl. Default: start
# | arg: -l, --line_match= - Line to match - The line to find in the log to attest the service have finished to boot. If not defined it don't wait until the service is completely started. WARNING: When using --line_match, you should always add `ynh_clean_check_starting` into your `ynh_clean_setup` at the beginning of the script. Otherwise, tail will not stop in case of failure of the script. The script will then hang forever.
# | arg: -p, --log_path= - Log file - Path to the log file. Default : /var/log/$app/$app.log
# | arg: -t, --timeout= - Timeout - The maximum time to wait before ending the watching. Default : 300 seconds.
# | arg: -e, --length= - Length of the error log : Default : 20
#
# Requires YunoHost version 3.5.0 or higher.
ynh_systemd_action() {
# Declare an array to define the options of this helper.
local legacy_args=nalpte
declare -Ar args_array=( [n]=service_name= [a]=action= [l]=line_match= [p]=log_path= [t]=timeout= [e]=length= )
local -A args_array=( [n]=service_name= [a]=action= [l]=line_match= [p]=log_path= [t]=timeout= [e]=length= )
local service_name
local action
local line_match
local length
local log_path
local timeout
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local service_name="${service_name:-$app}"
local action=${action:-start}
local log_path="${log_path:-/var/log/$service_name/$service_name.log}"
local length=${length:-20}
local timeout=${timeout:-300}
service_name="${service_name:-$app}"
action=${action:-start}
line_match=${line_match:-}
length=${length:-20}
log_path="${log_path:-/var/log/$service_name/$service_name.log}"
timeout=${timeout:-300}
# Start to read the log
if [[ -n "${line_match:-}" ]]
if [[ -n "$line_match" ]]
then
local templog="$(mktemp)"
# Following the starting of the app in its log
if [ "$log_path" == "systemd" ] ; then
if [ "$log_path" == "systemd" ]
then
# Read the systemd journal
journalctl --unit=$service_name --follow --since=-0 --quiet > "$templog" &
# Get the PID of the journalctl command
local pid_tail=$!
else
# Read the specified log file
tail -F -n0 "$log_path" > "$templog" 2>&1 &
tail --follow=name --retry --lines=0 "$log_path" > "$templog" 2>&1 &
# Get the PID of the tail command
local pid_tail=$!
fi
@ -121,10 +124,20 @@ ynh_systemd_action() {
action="reload-or-restart"
fi
systemctl $action $service_name \
|| ( journalctl --no-pager --lines=$length -u $service_name >&2 \
; test -e "$log_path" && echo "--" >&2 && tail --lines=$length "$log_path" >&2 \
; false )
# If the service fails to perform the action
if ! systemctl $action $service_name
then
# Show syslog for this service
ynh_exec_err journalctl --no-pager --lines=$length --unit=$service_name
# If a log is specified for this service, show also the content of this log
if [ -e "$log_path" ]
then
ynh_print_err --message="--"
ynh_exec_err tail --lines=$length "$log_path"
fi
# Fail the app script, since the service failed.
ynh_die
fi
# Start the timeout and try to find line_match
if [[ -n "${line_match:-}" ]]
@ -133,7 +146,7 @@ ynh_systemd_action() {
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_match" "$templog"
if grep --extended-regexp --quiet "$line_match" "$templog"
then
ynh_print_info --message="The service $service_name has correctly executed the action ${action}."
break
@ -153,8 +166,12 @@ ynh_systemd_action() {
then
ynh_print_warn --message="The service $service_name didn't fully executed the action ${action} before the timeout."
ynh_print_warn --message="Please find here an extract of the end of the log of the service $service_name:"
journalctl --no-pager --lines=$length -u $service_name >&2
test -e "$log_path" && echo "--" >&2 && tail --lines=$length "$log_path" >&2
ynh_exec_warn journalctl --no-pager --lines=$length --unit=$service_name
if [ -e "$log_path" ]
then
ynh_print_warn --message="\-\-\-"
ynh_exec_warn tail --lines=$length "$log_path"
fi
fi
ynh_clean_check_starting
fi
@ -164,16 +181,17 @@ ynh_systemd_action() {
# (usually used in ynh_clean_setup scripts)
#
# usage: ynh_clean_check_starting
#
# Requires YunoHost version 3.5.0 or higher.
ynh_clean_check_starting () {
if [ -n "$pid_tail" ]
then
# Stop the execution of tail.
kill -s 15 $pid_tail 2>&1
kill -SIGTERM $pid_tail 2>&1
fi
if [ -n "$templog" ]
then
ynh_secure_remove "$templog" 2>&1
ynh_secure_remove "$templog" 2>&1
fi
}

View file

@ -5,18 +5,19 @@
# example: ynh_user_exists 'toto' || exit 1
#
# usage: ynh_user_exists --username=username
# | arg: -u, --username - the username to check
# | arg: -u, --username= - the username to check
# | exit: Return 1 if the user doesn't exist, 0 otherwise
#
# Requires YunoHost version 2.2.4 or higher.
ynh_user_exists() {
# Declare an array to define the options of this helper.
local legacy_args=u
declare -Ar args_array=( [u]=username= )
local -A args_array=( [u]=username= )
local username
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
yunohost user list --output-as json | grep -q "\"username\": \"${username}\""
yunohost user list --output-as json | grep --quiet "\"username\": \"${username}\""
}
# Retrieve a YunoHost user information
@ -24,15 +25,15 @@ ynh_user_exists() {
# example: mail=$(ynh_user_get_info 'toto' 'mail')
#
# usage: ynh_user_get_info --username=username --key=key
# | arg: -u, --username - the username to retrieve info from
# | arg: -k, --key - the key to retrieve
# | arg: -u, --username= - the username to retrieve info from
# | arg: -k, --key= - the key to retrieve
# | ret: string - the key's value
#
# Requires YunoHost version 2.2.4 or higher.
ynh_user_get_info() {
# Declare an array to define the options of this helper.
local legacy_args=uk
declare -Ar args_array=( [u]=username= [k]=key= )
local -A args_array=( [u]=username= [k]=key= )
local username
local key
# Manage arguments with getopts
@ -51,19 +52,20 @@ ynh_user_get_info() {
# Requires YunoHost version 2.4.0 or higher.
ynh_user_list() {
yunohost user list --output-as plain --quiet \
| awk '/^##username$/{getline; print}'
| awk '/^##username$/{getline; print}'
}
# Check if a user exists on the system
#
# usage: ynh_system_user_exists --username=username
# | arg: -u, --username - the username to check
# | arg: -u, --username= - the username to check
# | exit: Return 1 if the user doesn't exist, 0 otherwise
#
# Requires YunoHost version 2.2.4 or higher.
ynh_system_user_exists() {
# Declare an array to define the options of this helper.
local legacy_args=u
declare -Ar args_array=( [u]=username= )
local -A args_array=( [u]=username= )
local username
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
@ -74,11 +76,14 @@ ynh_system_user_exists() {
# Check if a group exists on the system
#
# usage: ynh_system_group_exists --group=group
# | arg: -g, --group - the group to check
# | arg: -g, --group= - the group to check
# | exit: Return 1 if the group doesn't exist, 0 otherwise
#
# Requires YunoHost version 3.5.0.2 or higher.
ynh_system_group_exists() {
# Declare an array to define the options of this helper.
local legacy_args=g
declare -Ar args_array=( [g]=group= )
local -A args_array=( [g]=group= )
local group
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
@ -95,49 +100,51 @@ ynh_system_group_exists() {
# ynh_system_user_create --username=discourse --home_dir=/var/www/discourse --use_shell
#
# usage: ynh_system_user_create --username=user_name [--home_dir=home_dir] [--use_shell]
# | arg: -u, --username - Name of the system user that will be create
# | arg: -h, --home_dir - Path of the home dir for the user. Usually the final path of the app. If this argument is omitted, the user will be created without home
# | arg: -s, --use_shell - Create a user using the default login shell if present. If this argument is omitted, the user will be created with /usr/sbin/nologin shell
# | arg: -u, --username= - Name of the system user that will be create
# | arg: -h, --home_dir= - Path of the home dir for the user. Usually the final path of the app. If this argument is omitted, the user will be created without home
# | arg: -s, --use_shell - Create a user using the default login shell if present. If this argument is omitted, the user will be created with /usr/sbin/nologin shell
#
# Requires YunoHost version 2.6.4 or higher.
ynh_system_user_create () {
# Declare an array to define the options of this helper.
local legacy_args=uhs
declare -Ar args_array=( [u]=username= [h]=home_dir= [s]=use_shell )
local username
local home_dir
local use_shell
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
use_shell="${use_shell:-0}"
home_dir="${home_dir:-}"
# Declare an array to define the options of this helper.
local legacy_args=uhs
local -A args_array=( [u]=username= [h]=home_dir= [s]=use_shell )
local username
local home_dir
local use_shell
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
use_shell="${use_shell:-0}"
home_dir="${home_dir:-}"
if ! ynh_system_user_exists "$username" # Check if the user exists on the system
then # If the user doesn't exist
if [ -n "$home_dir" ]; then # If a home dir is mentioned
local user_home_dir="-d $home_dir"
else
local user_home_dir="--no-create-home"
fi
if [ $use_shell -eq 1 ]; then # If we want a shell for the user
local shell="" # Use default shell
else
local shell="--shell /usr/sbin/nologin"
fi
useradd $user_home_dir --system --user-group $username $shell || ynh_die "Unable to create $username system account"
fi
if ! ynh_system_user_exists "$username" # Check if the user exists on the system
then # If the user doesn't exist
if [ -n "$home_dir" ]
then # If a home dir is mentioned
local user_home_dir="--home-dir $home_dir"
else
local user_home_dir="--no-create-home"
fi
if [ $use_shell -eq 1 ]
then # If we want a shell for the user
local shell="" # Use default shell
else
local shell="--shell /usr/sbin/nologin"
fi
useradd $user_home_dir --system --user-group $username $shell || ynh_die --message="Unable to create $username system account"
fi
}
# Delete a system user
#
# usage: ynh_system_user_delete --username=user_name
# | arg: -u, --username - Name of the system user that will be create
# | arg: -u, --username= - Name of the system user that will be create
#
# Requires YunoHost version 2.6.4 or higher.
ynh_system_user_delete () {
# Declare an array to define the options of this helper.
local legacy_args=u
declare -Ar args_array=( [u]=username= )
local -A args_array=( [u]=username= )
local username
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
@ -145,14 +152,14 @@ ynh_system_user_delete () {
# Check if the user exists on the system
if ynh_system_user_exists "$username"
then
deluser $username
else
ynh_print_warn --message="The user $username was not found"
deluser $username
else
ynh_print_warn --message="The user $username was not found"
fi
# Check if the group exists on the system
if ynh_system_group_exists "$username"
then
delgroup $username
delgroup $username
fi
}

View file

@ -16,23 +16,26 @@
#
# It prints a warning to inform that the script was failed, and execute the ynh_clean_setup function if used in the app script
#
# Requires YunoHost version 2.6.4 or higher.
ynh_exit_properly () {
local exit_code=$?
if [ "$exit_code" -eq 0 ]; then
exit 0 # Exit without error if the script ended correctly
fi
local exit_code=$?
if [ "$exit_code" -eq 0 ]; then
exit 0 # Exit without error if the script ended correctly
fi
trap '' EXIT # Ignore new exit signals
set +eu # Do not exit anymore if a command fail or if a variable is empty
trap '' EXIT # Ignore new exit signals
# Do not exit anymore if a command fail or if a variable is empty
set +o errexit # set +e
set +o nounset # set +u
# Small tempo to avoid the next message being mixed up with other DEBUG messages
sleep 0.5
# Small tempo to avoid the next message being mixed up with other DEBUG messages
sleep 0.5
if type -t ynh_clean_setup > /dev/null; then # Check if the function exist in the app script.
ynh_clean_setup # Call the function to do specific cleaning for the app.
fi
if type -t ynh_clean_setup > /dev/null; then # Check if the function exist in the app script.
ynh_clean_setup # Call the function to do specific cleaning for the app.
fi
ynh_die # Exit with error status
ynh_die # Exit with error status
}
# Exits if an error occurs during the execution of the script.
@ -46,12 +49,17 @@ ynh_exit_properly () {
#
# Requires YunoHost version 2.6.4 or higher.
ynh_abort_if_errors () {
set -eu # Exit if a command fail, and if a variable is used unset.
trap ynh_exit_properly EXIT # Capturing exit signals on shell script
set -o errexit # set -e; Exit if a command fail
set -o nounset # set -u; And if a variable is used unset
trap ynh_exit_properly EXIT # Capturing exit signals on shell script
}
# Download, check integrity, uncompress and patch the source from app.src
#
# usage: ynh_setup_source --dest_dir=dest_dir [--source_id=source_id]
# | arg: -d, --dest_dir= - Directory where to setup sources
# | arg: -s, --source_id= - Name of the app, if the package contains more than one app
#
# The file conf/app.src need to contains:
#
# SOURCE_URL=Address to download the app archive
@ -90,16 +98,11 @@ ynh_abort_if_errors () {
# Finally, patches named sources/patches/${src_id}-*.patch and extra files in
# sources/extra_files/$src_id will be applied to dest_dir
#
#
# usage: ynh_setup_source --dest_dir=dest_dir [--source_id=source_id]
# | arg: -d, --dest_dir - Directory where to setup sources
# | arg: -s, --source_id - Name of the app, if the package contains more than one app
#
# Requires YunoHost version 2.6.4 or higher.
ynh_setup_source () {
# Declare an array to define the options of this helper.
local legacy_args=ds
declare -Ar args_array=( [d]=dest_dir= [s]=source_id= )
local -A args_array=( [d]=dest_dir= [s]=source_id= )
local dest_dir
local source_id
# Manage arguments with getopts
@ -115,13 +118,13 @@ ynh_setup_source () {
# Load value from configuration file (see above for a small doc about this file
# format)
local src_url=$(grep 'SOURCE_URL=' "$src_file_path" | cut -d= -f2-)
local src_sum=$(grep 'SOURCE_SUM=' "$src_file_path" | cut -d= -f2-)
local src_sumprg=$(grep 'SOURCE_SUM_PRG=' "$src_file_path" | cut -d= -f2-)
local src_format=$(grep 'SOURCE_FORMAT=' "$src_file_path" | cut -d= -f2-)
local src_extract=$(grep 'SOURCE_EXTRACT=' "$src_file_path" | cut -d= -f2-)
local src_in_subdir=$(grep 'SOURCE_IN_SUBDIR=' "$src_file_path" | cut -d= -f2-)
local src_filename=$(grep 'SOURCE_FILENAME=' "$src_file_path" | cut -d= -f2-)
local src_url=$(grep 'SOURCE_URL=' "$src_file_path" | cut --delimiter='=' --fields=2-)
local src_sum=$(grep 'SOURCE_SUM=' "$src_file_path" | cut --delimiter='=' --fields=2-)
local src_sumprg=$(grep 'SOURCE_SUM_PRG=' "$src_file_path" | cut --delimiter='=' --fields=2-)
local src_format=$(grep 'SOURCE_FORMAT=' "$src_file_path" | cut --delimiter='=' --fields=2-)
local src_extract=$(grep 'SOURCE_EXTRACT=' "$src_file_path" | cut --delimiter='=' --fields=2-)
local src_in_subdir=$(grep 'SOURCE_IN_SUBDIR=' "$src_file_path" | cut --delimiter='=' --fields=2-)
local src_filename=$(grep 'SOURCE_FILENAME=' "$src_file_path" | cut --delimiter='=' --fields=2-)
# Default value
src_sumprg=${src_sumprg:-sha256sum}
@ -129,7 +132,7 @@ ynh_setup_source () {
src_format=${src_format:-tar.gz}
src_format=$(echo "$src_format" | tr '[:upper:]' '[:lower:]')
src_extract=${src_extract:-true}
if [ "$src_filename" = "" ] ; then
if [ "$src_filename" = "" ]; then
src_filename="${source_id}.${src_format}"
fi
local local_src="/opt/yunohost-apps-src/${YNH_APP_ID}/${src_filename}"
@ -138,15 +141,15 @@ ynh_setup_source () {
then # Use the local source file if it is present
cp $local_src $src_filename
else # If not, download the source
local out=`wget -nv -O $src_filename $src_url 2>&1` || ynh_print_err --message="$out"
local out=`wget --no-verbose --output-document=$src_filename $src_url 2>&1` || ynh_print_err --message="$out"
fi
# Check the control sum
echo "${src_sum} ${src_filename}" | ${src_sumprg} -c --status \
echo "${src_sum} ${src_filename}" | ${src_sumprg} --check --status \
|| ynh_die --message="Corrupt source"
# Extract source into the app dir
mkdir -p "$dest_dir"
mkdir --parents "$dest_dir"
if ! "$src_extract"
then
@ -155,10 +158,11 @@ ynh_setup_source () {
then
# Zip format
# Using of a temp directory, because unzip doesn't manage --strip-components
if $src_in_subdir ; then
local tmp_dir=$(mktemp -d)
if $src_in_subdir
then
local tmp_dir=$(mktemp --directory)
unzip -quo $src_filename -d "$tmp_dir"
cp -a $tmp_dir/*/. "$dest_dir"
cp --archive $tmp_dir/*/. "$dest_dir"
ynh_secure_remove --file="$tmp_dir"
else
unzip -quo $src_filename -d "$dest_dir"
@ -167,40 +171,39 @@ ynh_setup_source () {
local strip=""
if [ "$src_in_subdir" != "false" ]
then
if [ "$src_in_subdir" == "true" ]; then
if [ "$src_in_subdir" == "true" ]
then
local sub_dirs=1
else
local sub_dirs="$src_in_subdir"
fi
strip="--strip-components $sub_dirs"
fi
if [[ "$src_format" =~ ^tar.gz|tar.bz2|tar.xz$ ]] ; then
tar -xf $src_filename -C "$dest_dir" $strip
if [[ "$src_format" =~ ^tar.gz|tar.bz2|tar.xz$ ]]
then
tar --extract --file=$src_filename --directory="$dest_dir" $strip
else
ynh_die --message="Archive format unrecognized."
fi
fi
# Apply patches
if (( $(find $YNH_CWD/../sources/patches/ -type f -name "${source_id}-*.patch" 2> /dev/null | wc -l) > "0" )); then
local old_dir=$(pwd)
(cd "$dest_dir" \
&& for p in $YNH_CWD/../sources/patches/${source_id}-*.patch; do \
patch -p1 < $p; done) \
|| ynh_die --message="Unable to apply patches"
cd $old_dir
if (( $(find $YNH_CWD/../sources/patches/ -type f -name "${source_id}-*.patch" 2> /dev/null | wc --lines) > "0" ))
then
(cd "$dest_dir"
for p in $YNH_CWD/../sources/patches/${source_id}-*.patch
do
patch --strip=1 < $p
done) || ynh_die --message="Unable to apply patches"
fi
# Add supplementary files
if test -e "$YNH_CWD/../sources/extra_files/${source_id}"; then
cp -a $YNH_CWD/../sources/extra_files/$source_id/. "$dest_dir"
cp --archive $YNH_CWD/../sources/extra_files/$source_id/. "$dest_dir"
fi
}
# Curl abstraction to help with POST requests to local pages (such as installation forms)
# For multiple calls, cookies are persisted between each call for the same app
#
# $domain and $path_url should be defined externally (and correspond to the domain.tld and the /path (of the app?))
#
# example: ynh_local_curl "/install.php?installButton" "foo=$var1" "bar=$var2"
#
@ -210,6 +213,10 @@ ynh_setup_source () {
# | arg: key2=value2 - (Optionnal) Another POST key and corresponding value
# | arg: ... - (Optionnal) More POST keys and values
#
# For multiple calls, cookies are persisted between each call for the same app
#
# $domain and $path_url should be defined externally (and correspond to the domain.tld and the /path (of the app?))
#
# Requires YunoHost version 2.6.4 or higher.
ynh_local_curl () {
# Define url of page to curl
@ -244,11 +251,13 @@ ynh_local_curl () {
chmod 700 $cookiefile
# Curl the URL
curl --silent --show-error -kL -H "Host: $domain" --resolve $domain:443:127.0.0.1 $POST_data "$full_page_url" --cookie-jar $cookiefile --cookie $cookiefile
curl --silent --show-error --insecure --location --header "Host: $domain" --resolve $domain:443:127.0.0.1 $POST_data "$full_page_url" --cookie-jar $cookiefile --cookie $cookiefile
}
# Render templates with Jinja2
#
# [internal]
#
# Attention : Variables should be exported before calling this helper to be
# accessible inside templates.
#
@ -256,13 +265,13 @@ ynh_local_curl () {
# | arg: some_template - Template file to be rendered
# | arg: output_path - The path where the output will be redirected to
ynh_render_template() {
local template_path=$1
local output_path=$2
mkdir -p "$(dirname $output_path)"
# Taken from https://stackoverflow.com/a/35009576
python2.7 -c 'import os, sys, jinja2; sys.stdout.write(
local template_path=$1
local output_path=$2
mkdir -p "$(dirname $output_path)"
# Taken from https://stackoverflow.com/a/35009576
python2.7 -c 'import os, sys, jinja2; sys.stdout.write(
jinja2.Template(sys.stdin.read()
).render(os.environ));' < $template_path > $output_path
).render(os.environ));' < $template_path > $output_path
}
# Fetch the Debian release codename
@ -272,7 +281,7 @@ ynh_render_template() {
#
# Requires YunoHost version 2.7.12 or higher.
ynh_get_debian_release () {
echo $(lsb_release --codename --short)
echo $(lsb_release --codename --short)
}
# Create a directory under /tmp
@ -287,7 +296,7 @@ ynh_mkdir_tmp() {
ynh_print_warn --message="The helper ynh_mkdir_tmp is deprecated."
ynh_print_warn --message="You should use 'mktemp -d' instead and manage permissions \
properly with chmod/chown."
local TMP_DIR=$(mktemp -d)
local TMP_DIR=$(mktemp --directory)
# Give rights to other users could be a security risk.
# But for retrocompatibility we need it. (This helpers is deprecated)
@ -298,13 +307,13 @@ properly with chmod/chown."
# Remove a file or a directory securely
#
# usage: ynh_secure_remove --file=path_to_remove
# | arg: -f, --file - File or directory to remove
# | arg: -f, --file= - File or directory to remove
#
# Requires YunoHost version 2.6.4 or higher.
ynh_secure_remove () {
# Declare an array to define the options of this helper.
local legacy_args=f
declare -Ar args_array=( [f]=file= )
local -A args_array=( [f]=file= )
local file
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
@ -321,7 +330,7 @@ ynh_secure_remove () {
if [[ -z "$file" ]]
then
ynh_print_warn --message="ynh_secure_remove called with empty argument, ignoring."
else if [[ "$forbidden_path" =~ "$file" \
elif [[ "$forbidden_path" =~ "$file" \
# Match all paths or subpaths in $forbidden_path
|| "$file" =~ ^/[[:alnum:]]+$ \
# Match all first level paths from / (Like /var, /root, etc...)
@ -329,16 +338,18 @@ ynh_secure_remove () {
# Match if the path finishes by /. Because it seems there is an empty variable
then
ynh_print_warn --message="Not deleting '$file' because it is not an acceptable path to delete."
else if [ -e "$file" ]
elif [ -e "$file" ]
then
rm -R "$file"
rm --recursive "$file"
else
ynh_print_info --message="'$file' wasn't deleted because it doesn't exist."
fi fi fi
fi
}
# Extract a key from a plain command output
#
# [internal]
#
# example: yunohost user info tata --output-as plain | ynh_get_plain_key mail
#
# usage: ynh_get_plain_key key [subkey [subsubkey ...]]
@ -352,12 +363,16 @@ ynh_get_plain_key() {
# an info to be redacted by the core
local key_=$1
shift
while read line; do
if [[ "$founded" == "1" ]] ; then
while read line
do
if [[ "$founded" == "1" ]]
then
[[ "$line" =~ ^${prefix}[^#] ]] && return
echo $line
elif [[ "$line" =~ ^${prefix}${key_}$ ]]; then
if [[ -n "${1:-}" ]]; then
elif [[ "$line" =~ ^${prefix}${key_}$ ]]
then
if [[ -n "${1:-}" ]]
then
prefix+="#"
key_=$1
shift
@ -370,72 +385,75 @@ ynh_get_plain_key() {
# Read the value of a key in a ynh manifest file
#
# usage: ynh_read_manifest manifest key
# | arg: -m, --manifest= - Path of the manifest to read
# | arg: -k, --key= - Name of the key to find
# usage: ynh_read_manifest --manifest="manifest.json" --key="key"
# | arg: -m, --manifest= - Path of the manifest to read
# | arg: -k, --key= - Name of the key to find
# | ret: the value associate to that key
#
# Requires YunoHost version 3.5.0 or higher.
ynh_read_manifest () {
# Declare an array to define the options of this helper.
local legacy_args=mk
declare -Ar args_array=( [m]=manifest= [k]=manifest_key= )
local manifest
local manifest_key
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=mk
local -A args_array=( [m]=manifest= [k]=manifest_key= )
local manifest
local manifest_key
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
if [ ! -e "$manifest" ]; then
# If the manifest isn't found, try the common place for backup and restore script.
manifest="../settings/manifest.json"
fi
if [ ! -e "$manifest" ]; then
# If the manifest isn't found, try the common place for backup and restore script.
manifest="../settings/manifest.json"
fi
jq ".$manifest_key" "$manifest" --raw-output
jq ".$manifest_key" "$manifest" --raw-output
}
# Read the upstream version from the manifest
#
# usage: ynh_app_upstream_version [--manifest="manifest.json"]
# | arg: -m, --manifest= - Path of the manifest to read
# | ret: the version number of the upstream app
#
# The version number in the manifest is defined by <upstreamversion>~ynh<packageversion>
# 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 [-m manifest]
# | arg: -m, --manifest= - Path of the manifest to read
#
# Requires YunoHost version 3.5.0 or higher.
ynh_app_upstream_version () {
# Declare an array to define the options of this helper.
local legacy_args=m
declare -Ar args_array=( [m]=manifest= )
local -A args_array=( [m]=manifest= )
local manifest
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
manifest="${manifest:-../manifest.json}"
version_key=$(ynh_read_manifest --manifest="$manifest" --manifest_key="version")
echo "${version_key/~ynh*/}"
}
# Read package version from the manifest
#
# usage: ynh_app_package_version [--manifest="manifest.json"]
# | arg: -m, --manifest= - Path of the manifest to read
# | ret: the version number of the package
#
# The version number in the manifest is defined by <upstreamversion>~ynh<packageversion>
# For example : 4.3-2~ynh3
# This include the number after ~ynh
# In the last example it return 3
#
# usage: ynh_app_package_version [-m manifest]
# | arg: -m, --manifest= - Path of the manifest to read
#
# Requires YunoHost version 3.5.0 or higher.
ynh_app_package_version () {
# Declare an array to define the options of this helper.
local legacy_args=m
declare -Ar args_array=( [m]=manifest= )
local -A args_array=( [m]=manifest= )
local manifest
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
manifest="${manifest:-../manifest.json}"
version_key=$(ynh_read_manifest --manifest="$manifest" --manifest_key="version")
echo "${version_key/*~ynh/}"
}
@ -458,32 +476,34 @@ ynh_app_package_version () {
#
# Requires YunoHost version 3.5.0 or higher.
ynh_check_app_version_changed () {
local force_upgrade=${YNH_FORCE_UPGRADE:-0}
local package_check=${PACKAGE_CHECK_EXEC:-0}
local force_upgrade=${YNH_FORCE_UPGRADE:-0}
local package_check=${PACKAGE_CHECK_EXEC:-0}
# By default, upstream app version has changed
local return_value="UPGRADE_APP"
# By default, upstream app version has changed
local return_value="UPGRADE_APP"
local current_version=$(ynh_read_manifest --manifest="/etc/yunohost/apps/$YNH_APP_INSTANCE_NAME/manifest.json" --manifest_key="version" || echo 1.0)
local current_upstream_version="$(ynh_app_upstream_version --manifest="/etc/yunohost/apps/$YNH_APP_INSTANCE_NAME/manifest.json")"
local update_version=$(ynh_read_manifest --manifest="../manifest.json" --manifest_key="version" || echo 1.0)
local update_upstream_version="$(ynh_app_upstream_version)"
local current_version=$(ynh_read_manifest --manifest="/etc/yunohost/apps/$YNH_APP_INSTANCE_NAME/manifest.json" --manifest_key="version" || echo 1.0)
local current_upstream_version="$(ynh_app_upstream_version --manifest="/etc/yunohost/apps/$YNH_APP_INSTANCE_NAME/manifest.json")"
local update_version=$(ynh_read_manifest --manifest="../manifest.json" --manifest_key="version" || echo 1.0)
local update_upstream_version="$(ynh_app_upstream_version)"
if [ "$current_version" == "$update_version" ] ; then
# Complete versions are the same
if [ "$force_upgrade" != "0" ]
then
ynh_print_info --message="Upgrade forced by YNH_FORCE_UPGRADE."
unset YNH_FORCE_UPGRADE
elif [ "$package_check" != "0" ]
then
ynh_print_info --message="Upgrade forced for package check."
else
ynh_die "Up-to-date, nothing to do" 0
fi
elif [ "$current_upstream_version" == "$update_upstream_version" ] ; then
# Upstream versions are the same, only YunoHost package versions differ
return_value="UPGRADE_PACKAGE"
fi
echo $return_value
if [ "$current_version" == "$update_version" ]
then
# Complete versions are the same
if [ "$force_upgrade" != "0" ]
then
ynh_print_info --message="Upgrade forced by YNH_FORCE_UPGRADE."
unset YNH_FORCE_UPGRADE
elif [ "$package_check" != "0" ]
then
ynh_print_info --message="Upgrade forced for package check."
else
ynh_die "Up-to-date, nothing to do" 0
fi
elif [ "$current_upstream_version" == "$update_upstream_version" ]
then
# Upstream versions are the same, only YunoHost package versions differ
return_value="UPGRADE_PACKAGE"
fi
echo $return_value
}

View file

@ -43,16 +43,16 @@ do_post_regen() {
# retrieve variables
main_domain=$(cat /etc/yunohost/current_host)
domain_list=$(yunohost domain list --output-as plain --quiet)
domain_list=$(yunohost domain list --exclude-subdomains --output-as plain --quiet)
# create metronome directories for domains
for domain in $domain_list; do
mkdir -p "/var/lib/metronome/${domain//./%2e}/pep"
# http_upload directory must be writable by metronome and readable by nginx
mkdir -p "/var/xmpp-upload/${domain}/upload"
chmod g+s "/var/xmpp-upload/${domain}/upload"
chown -R metronome:www-data "/var/xmpp-upload/${domain}"
done
# http_upload directory must be writable by metronome and readable by nginx
mkdir -p "/var/xmpp-upload/${main_domain}/upload"
chmod g+s "/var/xmpp-upload/${main_domain}/upload"
chown -R metronome:www-data "/var/xmpp-upload/${main_domain}"
# fix some permissions
chown -R metronome: /var/lib/metronome/

View file

@ -27,7 +27,8 @@ do_init_regen() {
ynh_render_template "yunohost_admin.conf" "${nginx_conf_dir}/yunohost_admin.conf"
# Restart nginx if conf looks good, otherwise display error and exit unhappy
nginx -t 2>/dev/null && service nginx restart || (nginx -t && exit 1)
nginx -t 2>/dev/null || { nginx -t; exit 1; }
systemctl restart nginx || { journalctl --no-pager --lines=10 -u nginx >&2; exit 1; }
exit 0
}
@ -125,9 +126,9 @@ do_post_regen() {
fi
done
# Reload nginx configuration
pgrep nginx && service nginx reload
# Reload nginx if conf looks good, otherwise display error and exit unhappy
nginx -t 2>/dev/null || { nginx -t; exit 1; }
pgrep nginx && systemctl reload nginx || { journalctl --no-pager --lines=10 -u nginx >&2; exit 1; }
}
FORCE=${2:-0}

View file

@ -2,9 +2,9 @@
import os
from moulinette.utils.process import check_output
from moulinette.utils.filesystem import read_file
from yunohost.utils.network import dig
from yunohost.diagnosis import Diagnoser
from yunohost.domain import domain_list, _build_dns_conf, _get_maindomain
@ -100,20 +100,14 @@ class DNSRecordsDiagnoser(Diagnoser):
yield output
def get_current_record(self, domain, name, type_):
if name == "@":
command = "dig +short @%s %s %s" % (self.resolver, type_, domain)
else:
command = "dig +short @%s %s %s.%s" % (self.resolver, type_, name, domain)
# FIXME : gotta handle case where this command fails ...
# e.g. no internet connectivity (dependency mechanism to good result from 'ip' diagosis ?)
# or the resolver is unavailable for some reason
output = check_output(command).strip().split("\n")
if len(output) == 0 or not output[0]:
query = "%s.%s" % (name, domain) if name != "@" else domain
success, answers = dig(query, type_, resolvers="force_external")
if success != "ok":
return None
elif len(output) == 1:
return output[0]
else:
return output
return answers[0] if len(answers) == 1 else answers
def current_record_match_expected(self, r):
if r["value"] is not None and r["current"] is None:

View file

@ -13,6 +13,7 @@ from moulinette.utils.filesystem import read_yaml
from yunohost.diagnosis import Diagnoser
from yunohost.domain import _get_maindomain, domain_list
from yunohost.settings import settings_get
from yunohost.utils.network import dig
DEFAULT_DNS_BLACKLIST = "/usr/share/yunohost/other/dnsbl_list.yml"
@ -155,26 +156,25 @@ class MailDiagnoser(Diagnoser):
if not blacklist[item_type]:
continue
# Determine if we are listed on this RBL
try:
subdomain = item
if item_type != "domain":
rev = dns.reversename.from_address(item)
subdomain = str(rev.split(3)[0])
query = subdomain + '.' + blacklist['dns_server']
# TODO add timeout lifetime
dns.resolver.query(query, "A")
except (dns.resolver.NXDOMAIN, dns.resolver.NoNameservers, dns.resolver.NoAnswer,
dns.exception.Timeout):
# Build the query for DNSBL
subdomain = item
if item_type != "domain":
rev = dns.reversename.from_address(item)
subdomain = str(rev.split(3)[0])
query = subdomain + '.' + blacklist['dns_server']
# Do the DNS Query
status, _ = dig(query, 'A')
if status != 'ok':
continue
# Try to get the reason
details = []
try:
reason = str(dns.resolver.query(query, "TXT")[0])
status, answers = dig(query, 'TXT')
reason = "-"
if status == 'ok':
reason = ', '.join(answers)
details.append("diagnosis_mail_blacklist_reason")
except Exception:
reason = "-"
details.append("diagnosis_mail_blacklist_website")

View file

@ -1,4 +1,5 @@
VirtualHost "{{ domain }}"
enable = true
ssl = {
key = "/etc/yunohost/certs/{{ domain }}/key.pem";
certificate = "/etc/yunohost/certs/{{ domain }}/crt.pem";
@ -13,3 +14,58 @@ VirtualHost "{{ domain }}"
namefield = "cn",
},
}
-- Discovery items
disco_items = {
{ "muc.{{ domain }}" },
{ "pubsub.{{ domain }}" },
{ "jabber.{{ domain }}" },
{ "vjud.{{ domain }}" },
{ "xmpp-upload.{{ domain }}" },
};
-- contact_info = {
-- abuse = { "mailto:abuse@{{ domain }}", "xmpp:admin@{{ domain }}" };
-- admin = { "mailto:root@{{ domain }}", "xmpp:admin@{{ domain }}" };
-- };
------ Components ------
-- You can specify components to add hosts that provide special services,
-- like multi-user conferences, and transports.
---Set up a MUC (multi-user chat) room server
Component "muc.{{ domain }}" "muc"
name = "{{ domain }} Chatrooms"
modules_enabled = {
"muc_limits";
"muc_log";
"muc_log_mam";
"muc_log_http";
"muc_vcard";
}
muc_event_rate = 0.5
muc_burst_factor = 10
---Set up a PubSub server
Component "pubsub.{{ domain }}" "pubsub"
name = "{{ domain }} Publish/Subscribe"
unrestricted_node_creation = true -- Anyone can create a PubSub node (from any server)
---Set up a HTTP Upload service
Component "xmpp-upload.{{ domain }}" "http_upload"
name = "{{ domain }} Sharing Service"
http_file_path = "/var/xmpp-upload/{{ domain }}/upload"
http_external_url = "https://xmpp-upload.{{ domain }}:443"
http_file_base_path = "/upload"
http_file_size_limit = 6*1024*1024
http_file_quota = 60*1024*1024
http_upload_file_size_limit = 100 * 1024 * 1024 -- bytes
http_upload_quota = 10 * 1024 * 1024 * 1024 -- bytes
---Set up a VJUD service
Component "vjud.{{ domain }}" "vjud"
vjud_disco_name = "{{ domain }} User Directory"

View file

@ -81,14 +81,6 @@ http_interfaces = { "127.0.0.1", "::1" }
-- Enable IPv6
use_ipv6 = true
-- Discovery items
disco_items = {
{ "muc.{{ main_domain }}" },
{ "pubsub.{{ main_domain }}" },
{ "xmpp-upload.{{ main_domain }}" },
{ "vjud.{{ main_domain }}" }
};
-- BOSH configuration (mod_bosh)
consider_bosh_secure = true
cross_domain_bosh = true
@ -119,45 +111,6 @@ log = {
Component "localhost" "http"
modules_enabled = { "bosh" }
---Set up a MUC (multi-user chat) room server
Component "muc.{{ main_domain }}" "muc"
name = "{{ main_domain }} Chatrooms"
modules_enabled = {
"muc_limits";
"muc_log";
"muc_log_mam";
"muc_log_http";
"muc_vcard";
}
muc_event_rate = 0.5
muc_burst_factor = 10
---Set up a PubSub server
Component "pubsub.{{ main_domain }}" "pubsub"
name = "{{ main_domain }} Publish/Subscribe"
unrestricted_node_creation = true -- Anyone can create a PubSub node (from any server)
---Set up a HTTP Upload service
Component "xmpp-upload.{{ main_domain }}" "http_upload"
name = "{{ main_domain }} Sharing Service"
http_file_path = "/var/xmpp-upload/{{ main_domain }}/upload"
http_external_url = "https://xmpp-upload.{{ main_domain }}:443"
http_file_base_path = "/upload"
http_file_size_limit = 6*1024*1024
http_file_quota = 60*1024*1024
http_upload_file_size_limit = 100 * 1024 * 1024 -- bytes
http_upload_quota = 10 * 1024 * 1024 * 1024 -- bytes
---Set up a VJUD service
Component "vjud.{{ main_domain }}" "vjud"
ud_disco_name = "{{ main_domain }} User Directory"
----------- Virtual hosts -----------
-- You need to add a VirtualHost entry for each domain you wish Metronome to serve.
-- Settings under each VirtualHost entry apply *only* to that host.

View file

@ -33,14 +33,20 @@ smtpd_tls_cert_file = /etc/yunohost/certs/{{ main_domain }}/crt.pem
smtpd_tls_key_file = /etc/yunohost/certs/{{ main_domain }}/key.pem
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtpd_tls_mandatory_ciphers = medium
# smtpd_tls_mandatory_ciphers = medium # (c.f. below)
# curl https://ssl-config.mozilla.org/ffdhe2048.txt > /path/to/dhparam.pem
# not actually 1024 bits, this applies to all DHE >= 1024 bits
# smtpd_tls_dh1024_param_file = /path/to/dhparam.pem
tls_medium_cipherlist = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
# This custom medium cipherlist recommendation only works if we have a DH ... which we don't, c.f. https://github.com/YunoHost/issues/issues/93
# On the other hand, the postfix doc strongly discourage tweaking this list ... So whatever, let's keep the mandatory_ciphers to high like we did before applying the Mozilla recommendation ...
#tls_medium_cipherlist = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
tls_preempt_cipherlist = no
# Custom Yunohost stuff ... because we can't use the recommendation about medium cipher list ...
smtpd_tls_mandatory_ciphers=high
smtpd_tls_eecdh_grade = ultra
###############################################################################
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtpd_tls_loglevel=1

11
debian/changelog vendored
View file

@ -74,6 +74,17 @@ yunohost (3.8.0) testing; urgency=low
-- Kay0u <pierre@kayou.io> Thu, 09 Apr 2020 19:59:18 +0000
yunohost (3.7.1.2) stable; urgency=low
- [fix] Be more robust against some situation where some archives are corrupted
- [fix] Make nginx regen-conf more robust against broken config or service failing to start, show info to help debugging
- [fix] Force-flush the regen-conf for nginx domain conf when adding/removing a domain...
- [fix] app_map : Make sure to return / and not empty string for stuff on domain root
- [fix] Improve ynh_systemd_action to wait for fail2ban to reload
- [fix] Improper use of logger.exception in app.py leading to infamous weird "KeyError: label"
-- Alexandre Aubin <alex.aubin@mailoo.org> Mon, 27 Apr 2020 23:50:00 +0000
yunohost (3.7.1.1) stable; urgency=low
- [fix] lxc uid number is limited to 65536 by default (0c9a4509)

View file

@ -77,6 +77,8 @@
"backup_archive_name_exists": "A backup archive with this name already exists.",
"backup_archive_name_unknown": "Unknown local backup archive named '{name:s}'",
"backup_archive_open_failed": "Could not open the backup archive",
"backup_archive_cant_retrieve_info_json": "Could not load infos for archive '{archive}' ... The info.json cannot be retrieved (or is not a valid json).",
"backup_archive_corrupted": "It looks like the backup archive '{archive}' is corrupted : {error}",
"backup_archive_system_part_not_available": "System part '{part:s}' unavailable in this backup",
"backup_archive_writing_error": "Could not add the files '{source:s}' (named in the archive '{dest:s}') to be backed up into the compressed archive '{archive:s}'",
"backup_ask_for_copying_if_needed": "Do you want to perform the backup using {size:s} MB temporarily? (This way is used since some files could not be prepared using a more efficient method.)",
@ -94,7 +96,6 @@
"backup_delete_error": "Could not delete '{path:s}'",
"backup_deleted": "Backup deleted",
"backup_hook_unknown": "The backup hook '{hook:s}' is unknown",
"backup_invalid_archive": "This is not a backup archive",
"backup_method_borg_finished": "Backup into Borg finished",
"backup_method_copy_finished": "Backup copy finalized",
"backup_method_custom_finished": "Custom backup method '{method:s}' finished",
@ -113,7 +114,7 @@
"backup_unable_to_organize_files": "Could not use the quick method to organize files in the archive",
"backup_with_no_backup_script_for_app": "The app '{app:s}' has no backup script. Ignoring.",
"backup_with_no_restore_script_for_app": "The '{app:s}' has no restoration script, you will not be able to automatically restore the backup of this app.",
"certmanager_acme_not_configured_for_domain": "Certificate for the domain '{domain:s}' does not appear to be correctly installed. Please run 'cert-install' for this domain first.",
"certmanager_acme_not_configured_for_domain": "The ACME challenge cannot be ran for {domain} right now because its nginx conf lacks the corresponding code snippet... Please make sure that your nginx configuration is up to date using `yunohost tools regen-conf nginx --dry-run --with-diff`.",
"certmanager_attempt_to_renew_nonLE_cert": "The certificate for the domain '{domain:s}' is not issued by Let's Encrypt. Cannot renew it automatically!",
"certmanager_attempt_to_renew_valid_cert": "The certificate for the domain '{domain:s}' is not about to expire! (You may use --force if you know what you're doing)",
"certmanager_attempt_to_replace_valid_cert": "You are attempting to overwrite a good and valid certificate for domain {domain:s}! (Use --force to bypass)",

View file

@ -110,12 +110,34 @@ def app_catalog(full=False, with_categories=False):
return {"apps": catalog["apps"], "categories": catalog["categories"]}
def app_list(full=False):
# Old legacy function...
def app_fetchlist():
logger.warning("'yunohost app fetchlist' is deprecated. Please use 'yunohost tools update --apps' instead")
from yunohost.tools import tools_update
tools_update(apps=True)
def app_list(full=False, installed=False, filter=None):
"""
List installed apps
"""
# Old legacy argument ... app_list was a combination of app_list and
# app_catalog before 3.8 ...
if installed:
logger.warning("Argument --installed ain't needed anymore when using 'yunohost app list'. It directly returns the list of installed apps..")
# Filter is a deprecated option...
if filter:
logger.warning("Using -f $appname in 'yunohost app list' is deprecated. Just use 'yunohost app list | grep -q 'id: $appname' to check a specific app is installed")
out = []
for app_id in sorted(_installed_apps()):
if filter and not app_id.startswith(filter):
continue
try:
app_info_dict = app_info(app_id, full=full)
except Exception as e:
@ -225,6 +247,7 @@ def app_map(app=None, raw=False, user=None, permission=None):
continue
this_app_perms = {p: i for p, i in permissions.items() if p.startswith(app_id + ".") and (i["url"] or i['additional_urls'] != [None])}
for perm_name, perm_info in this_app_perms.items():
# If we're building the map for a specific user, check the user
# actually is allowed for this specific perm
@ -478,7 +501,7 @@ def app_upgrade(app=[], url=None, file=None):
upgrade_failed = True if upgrade_retcode != 0 else False
if upgrade_failed:
error = m18n.n('app_upgrade_script_failed')
logger.exception(m18n.n("app_upgrade_failed", app=app_instance_name, error=error))
logger.error(m18n.n("app_upgrade_failed", app=app_instance_name, error=error))
failure_message_with_debug_instructions = operation_logger.error(error)
if msettings.get('interface') != 'api':
dump_app_log_extract_for_debugging(operation_logger)
@ -486,13 +509,13 @@ def app_upgrade(app=[], url=None, file=None):
except (KeyboardInterrupt, EOFError):
upgrade_retcode = -1
error = m18n.n('operation_interrupted')
logger.exception(m18n.n("app_upgrade_failed", app=app_instance_name, error=error))
logger.error(m18n.n("app_upgrade_failed", app=app_instance_name, error=error))
failure_message_with_debug_instructions = operation_logger.error(error)
# Something wrong happened in Yunohost's code (most probably hook_exec)
except Exception:
import traceback
error = m18n.n('unexpected_error', error=u"\n" + traceback.format_exc())
logger.exception(m18n.n("app_install_failed", app=app_instance_name, error=error))
logger.error(m18n.n("app_install_failed", app=app_instance_name, error=error))
failure_message_with_debug_instructions = operation_logger.error(error)
finally:
# Whatever happened (install success or failure) we check if it broke the system
@ -502,7 +525,7 @@ def app_upgrade(app=[], url=None, file=None):
_assert_system_is_sane_for_app(manifest, "post")
except Exception as e:
broke_the_system = True
logger.exception(m18n.n("app_upgrade_failed", app=app_instance_name, error=str(e)))
logger.error(m18n.n("app_upgrade_failed", app=app_instance_name, error=str(e)))
failure_message_with_debug_instructions = operation_logger.error(str(e))
# If upgrade failed or broke the system,
@ -735,20 +758,20 @@ def app_install(operation_logger, app, label=None, args=None, no_remove_on_failu
install_failed = True if install_retcode != 0 else False
if install_failed:
error = m18n.n('app_install_script_failed')
logger.exception(m18n.n("app_install_failed", app=app_id, error=error))
logger.error(m18n.n("app_install_failed", app=app_id, error=error))
failure_message_with_debug_instructions = operation_logger.error(error)
if msettings.get('interface') != 'api':
dump_app_log_extract_for_debugging(operation_logger)
# Script got manually interrupted ... N.B. : KeyboardInterrupt does not inherit from Exception
except (KeyboardInterrupt, EOFError):
error = m18n.n('operation_interrupted')
logger.exception(m18n.n("app_install_failed", app=app_id, error=error))
logger.error(m18n.n("app_install_failed", app=app_id, error=error))
failure_message_with_debug_instructions = operation_logger.error(error)
# Something wrong happened in Yunohost's code (most probably hook_exec)
except Exception as e:
import traceback
error = m18n.n('unexpected_error', error=u"\n" + traceback.format_exc())
logger.exception(m18n.n("app_install_failed", app=app_id, error=error))
logger.error(m18n.n("app_install_failed", app=app_id, error=error))
failure_message_with_debug_instructions = operation_logger.error(error)
finally:
# Whatever happened (install success or failure) we check if it broke the system
@ -758,7 +781,7 @@ def app_install(operation_logger, app, label=None, args=None, no_remove_on_failu
_assert_system_is_sane_for_app(manifest, "post")
except Exception as e:
broke_the_system = True
logger.exception(m18n.n("app_install_failed", app=app_id, error=str(e)))
logger.error(m18n.n("app_install_failed", app=app_id, error=str(e)))
failure_message_with_debug_instructions = operation_logger.error(str(e))
# If the install failed or broke the system, we remove it
@ -795,7 +818,7 @@ def app_install(operation_logger, app, label=None, args=None, no_remove_on_failu
except (KeyboardInterrupt, EOFError, Exception):
remove_retcode = -1
import traceback
logger.exception(m18n.n('unexpected_error', error=u"\n" + traceback.format_exc()))
logger.error(m18n.n('unexpected_error', error=u"\n" + traceback.format_exc()))
# Remove all permission in LDAP
for permission_name in user_permission_list()["permissions"].keys():
@ -967,7 +990,7 @@ def app_remove(operation_logger, app):
except (KeyboardInterrupt, EOFError, Exception):
ret = -1
import traceback
logger.exception(m18n.n('unexpected_error', error=u"\n" + traceback.format_exc()))
logger.error(m18n.n('unexpected_error', error=u"\n" + traceback.format_exc()))
if ret == 0:
logger.success(m18n.n('app_removed', app=app))
@ -1073,11 +1096,12 @@ def app_makedefault(operation_logger, app, domain=None):
elif domain not in domain_list()['domains']:
raise YunohostError('domain_named_unknown', domain=domain)
operation_logger.start()
if '/' in app_map(raw=True)[domain]:
raise YunohostError('app_make_default_location_already_used', app=app, domain=app_domain,
other_app=app_map(raw=True)[domain]["/"]["id"])
operation_logger.start()
# TODO / FIXME : current trick is to add this to conf.json.persisten
# This is really not robust and should be improved
# e.g. have a flag in /etc/yunohost/apps/$app/ to say that this is the
@ -1247,6 +1271,8 @@ def app_ssowatconf():
perm_domain, perm_path = perm_url.split("/", 1)
perm_path = "/" + perm_path.rstrip("/")
perm_path = perm_path if perm_path.strip() != "" else "/"
return perm_domain + perm_path
# Skipped
@ -1826,7 +1852,7 @@ def _get_app_settings(app_id):
if app_id == settings['id']:
return settings
except (IOError, TypeError, KeyError):
logger.exception(m18n.n('app_not_correctly_installed',
logger.error(m18n.n('app_not_correctly_installed',
app=app_id))
return {}

View file

@ -35,9 +35,9 @@ import tempfile
from datetime import datetime
from glob import glob
from collections import OrderedDict
from functools import reduce
from moulinette import msignals, m18n, msettings
from yunohost.utils.error import YunohostError
from moulinette.utils import filesystem
from moulinette.utils.log import getActionLogger
from moulinette.utils.filesystem import read_file, mkdir, write_to_yaml, read_yaml
@ -51,7 +51,8 @@ from yunohost.hook import (
from yunohost.tools import tools_postinstall
from yunohost.regenconf import regen_conf
from yunohost.log import OperationLogger
from functools import reduce
from yunohost.utils.error import YunohostError
from yunohost.utils.packages import ynh_packages_version
BACKUP_PATH = '/home/yunohost.backup'
ARCHIVES_PATH = '%s/archives' % BACKUP_PATH
@ -282,7 +283,8 @@ class BackupManager():
'size': self.size,
'size_details': self.size_details,
'apps': self.apps_return,
'system': self.system_return
'system': self.system_return,
'from_yunohost_version': ynh_packages_version()["yunohost"]["version"]
}
@property
@ -870,7 +872,7 @@ class RestoreManager():
Read the info file from inside an archive
Exceptions:
backup_invalid_archive -- Raised if we can't read the info
backup_archive_cant_retrieve_info_json -- Raised if we can't read the info
"""
# Retrieve backup info
info_file = os.path.join(self.work_dir, "info.json")
@ -883,7 +885,7 @@ class RestoreManager():
self.info["system"] = self.info["hooks"]
except IOError:
logger.debug("unable to load '%s'", info_file, exc_info=1)
raise YunohostError('backup_invalid_archive')
raise YunohostError('backup_archive_cant_retrieve_info_json', archive=self.archive_path)
else:
logger.debug("restoring from backup '%s' created on %s", self.name,
datetime.utcfromtimestamp(self.info['created_at']))
@ -891,10 +893,6 @@ class RestoreManager():
def _postinstall_if_needed(self):
"""
Post install yunohost if needed
Exceptions:
backup_invalid_archive -- Raised if the current_host isn't in the
archive
"""
# Check if YunoHost is installed
if not os.path.isfile('/etc/yunohost/installed'):
@ -906,7 +904,7 @@ class RestoreManager():
logger.debug("unable to retrieve current_host from the backup",
exc_info=1)
# FIXME include the current_host by default ?
raise YunohostError('backup_invalid_archive')
raise YunohostError("The main domain name cannot be retrieved from inside the archive, and is needed to perform the postinstall", raw_msg=True)
logger.debug("executing the post-install...")
tools_postinstall(domain, 'Yunohost', True)
@ -1922,6 +1920,8 @@ class TarBackupMethod(BackupMethod):
Exceptions:
backup_archive_open_failed -- Raised if the archive can't be open
backup_archive_corrupted -- Raised if the archive appears corrupted
backup_archive_cant_retrieve_info_json -- If the info.json file can't be retrieved
"""
super(TarBackupMethod, self).mount(restore_manager)
@ -1933,6 +1933,11 @@ class TarBackupMethod(BackupMethod):
self._archive_file, exc_info=1)
raise YunohostError('backup_archive_open_failed')
try:
files_in_archive = tar.getnames()
except IOError as e:
raise YunohostError("backup_archive_corrupted", archive=self._archive_file, error=str(e))
# FIXME : Is this really useful to close the archive just to
# reopen it right after this with the same options ...?
tar.close()
@ -1941,21 +1946,21 @@ class TarBackupMethod(BackupMethod):
logger.debug(m18n.n("restore_extracting"))
tar = tarfile.open(self._archive_file, "r:gz")
if "info.json" in tar.getnames():
if "info.json" in files_in_archive:
leading_dot = ""
tar.extract('info.json', path=self.work_dir)
elif "./info.json" in tar.getnames():
elif "./info.json" in files_in_archive:
leading_dot = "./"
tar.extract('./info.json', path=self.work_dir)
else:
logger.debug("unable to retrieve 'info.json' inside the archive",
exc_info=1)
tar.close()
raise YunohostError('backup_invalid_archive')
raise YunohostError('backup_archive_cant_retrieve_info_json', archive=self._archive_file)
if "backup.csv" in tar.getnames():
if "backup.csv" in files_in_archive:
tar.extract('backup.csv', path=self.work_dir)
elif "./backup.csv" in tar.getnames():
elif "./backup.csv" in files_in_archive:
tar.extract('./backup.csv', path=self.work_dir)
else:
# Old backup archive have no backup.csv file
@ -2297,7 +2302,7 @@ def backup_list(with_info=False, human_readable=False):
try:
d[a] = backup_info(a, human_readable=human_readable)
except YunohostError as e:
logger.warning('%s: %s' % (a, e.strerror))
logger.warning(str(e))
result = d
@ -2334,17 +2339,23 @@ def backup_info(name, with_details=False, human_readable=False):
if not os.path.exists(info_file):
tar = tarfile.open(archive_file, "r:gz")
info_dir = info_file + '.d'
try:
if "info.json" in tar.getnames():
files_in_archive = tar.getnames()
except IOError as e:
raise YunohostError("backup_archive_corrupted", archive=archive_file, error=str(e))
try:
if "info.json" in files_in_archive:
tar.extract('info.json', path=info_dir)
elif "./info.json" in tar.getnames():
elif "./info.json" in files_in_archive:
tar.extract('./info.json', path=info_dir)
else:
raise KeyError
except KeyError:
logger.debug("unable to retrieve '%s' inside the archive",
info_file, exc_info=1)
raise YunohostError('backup_invalid_archive')
raise YunohostError('backup_archive_cant_retrieve_info_json', archive=archive_file)
else:
shutil.move(os.path.join(info_dir, 'info.json'), info_file)
finally:
@ -2357,7 +2368,7 @@ def backup_info(name, with_details=False, human_readable=False):
info = json.load(f)
except:
logger.debug("unable to load '%s'", info_file, exc_info=1)
raise YunohostError('backup_invalid_archive')
raise YunohostError('backup_archive_cant_retrieve_info_json', archive=archive_file)
# Retrieve backup size
size = info.get('size', 0)

View file

@ -34,15 +34,14 @@ import glob
from datetime import datetime
from yunohost.vendor.acme_tiny.acme_tiny import get_crt as sign_certificate
from yunohost.utils.error import YunohostError
from moulinette import m18n
from moulinette.utils.log import getActionLogger
from moulinette.utils.filesystem import read_file
from yunohost.vendor.acme_tiny.acme_tiny import get_crt as sign_certificate
from yunohost.utils.error import YunohostError
from yunohost.utils.network import get_public_ip
from moulinette import m18n
from yunohost.app import app_ssowatconf
from yunohost.service import _run_service_command
from yunohost.regenconf import regen_conf
from yunohost.log import OperationLogger
@ -468,14 +467,15 @@ Subject: %s
def _check_acme_challenge_configuration(domain):
# Check nginx conf file exists
nginx_conf_folder = "/etc/nginx/conf.d/%s.d" % domain
nginx_conf_file = "%s/000-acmechallenge.conf" % nginx_conf_folder
if not os.path.exists(nginx_conf_file):
return False
else:
domain_conf = "/etc/nginx/conf.d/%s.conf" % domain
if "include /etc/nginx/conf.d/acme-challenge.conf.inc" in read_file(domain_conf):
return True
else:
# This is for legacy setups which haven't updated their domain conf to
# the new conf that include the acme snippet...
legacy_acme_conf = "/etc/nginx/conf.d/%s.d/000-acmechallenge.conf" % domain
return os.path.exists(legacy_acme_conf)
def _fetch_and_enable_new_certificate(domain, staging=False, no_checks=False):
@ -592,10 +592,10 @@ def _prepare_certificate_signing_request(domain, key_file, output_folder):
# Set the domain
csr.get_subject().CN = domain
from yunohost.domain import _get_maindomain
if domain == _get_maindomain():
# Include xmpp-upload subdomain in subject alternate names
subdomain="xmpp-upload." + domain
from yunohost.domain import domain_list
# For "parent" domains, include xmpp-upload subdomain in subject alternate names
if domain in domain_list(exclude_subdomains=True)["domains"]:
subdomain = "xmpp-upload." + domain
try:
_dns_ip_match_public_ip(get_public_ip(), subdomain)
csr.add_extensions([crypto.X509Extension("subjectAltName", False, "DNS:" + subdomain)])

View file

@ -25,15 +25,14 @@
"""
import os
import re
import yaml
from moulinette import m18n, msettings
from moulinette.core import MoulinetteError
from yunohost.utils.error import YunohostError
from moulinette.utils.log import getActionLogger
from yunohost.app import app_ssowatconf
from yunohost.regenconf import regen_conf
from yunohost.app import app_ssowatconf, _installed_apps, _get_app_settings
from yunohost.regenconf import regen_conf, _force_clear_hashes, _process_regen_conf
from yunohost.utils.network import get_public_ip
from yunohost.log import is_unit_operation
from yunohost.hook import hook_callback
@ -41,24 +40,26 @@ from yunohost.hook import hook_callback
logger = getActionLogger('yunohost.domain')
def domain_list():
def domain_list(exclude_subdomains=False):
"""
List domains
Keyword argument:
filter -- LDAP filter used to search
offset -- Starting number for domain fetching
limit -- Maximum number of domain fetched
exclude_subdomains -- Filter out domains that are subdomains of other declared domains
"""
from yunohost.utils.ldap import _get_ldap_interface
ldap = _get_ldap_interface()
result = ldap.search('ou=domains,dc=yunohost,dc=org', 'virtualdomain=*', ['virtualdomain'])
result = [entry['virtualdomain'][0] for entry in ldap.search('ou=domains,dc=yunohost,dc=org', 'virtualdomain=*', ['virtualdomain'])]
result_list = []
for domain in result:
result_list.append(domain['virtualdomain'][0])
if exclude_subdomains:
parent_domain = domain.split(".", 1)[1]
if parent_domain in result:
continue
result_list.append(domain)
return {'domains': result_list}
@ -122,6 +123,17 @@ def domain_add(operation_logger, domain, dyndns=False):
# Don't regen these conf if we're still in postinstall
if os.path.exists('/etc/yunohost/installed'):
# Sometime we have weird issues with the regenconf where some files
# appears as manually modified even though they weren't touched ...
# There are a few ideas why this happens (like backup/restore nginx
# conf ... which we shouldnt do ...). This in turns creates funky
# situation where the regenconf may refuse to re-create the conf
# (when re-creating a domain..)
# So here we force-clear the has out of the regenconf if it exists.
# This is a pretty ad hoc solution and only applied to nginx
# because it's one of the major service, but in the long term we
# should identify the root of this bug...
_force_clear_hashes(["/etc/nginx/conf.d/%s.conf" % domain])
regen_conf(names=['nginx', 'metronome', 'dnsmasq', 'postfix', 'rspamd'])
app_ssowatconf()
@ -167,15 +179,9 @@ def domain_remove(operation_logger, domain, force=False):
raise YunohostError('domain_cannot_remove_main_add_new_one', domain=domain)
# Check if apps are installed on the domain
for app in os.listdir('/etc/yunohost/apps/'):
with open('/etc/yunohost/apps/' + app + '/settings.yml') as f:
try:
app_domain = yaml.load(f)['domain']
except:
continue
else:
if app_domain == domain:
raise YunohostError('domain_uninstall_app_first')
app_settings = [_get_app_settings(app) for app in _installed_apps()]
if any(s["domain"] == domain for s in app_settings):
raise YunohostError('domain_uninstall_app_first')
operation_logger.start()
ldap = _get_ldap_interface()
@ -186,6 +192,25 @@ def domain_remove(operation_logger, domain, force=False):
os.system('rm -rf /etc/yunohost/certs/%s' % domain)
# Sometime we have weird issues with the regenconf where some files
# appears as manually modified even though they weren't touched ...
# There are a few ideas why this happens (like backup/restore nginx
# conf ... which we shouldnt do ...). This in turns creates funky
# situation where the regenconf may refuse to re-create the conf
# (when re-creating a domain..)
#
# So here we force-clear the has out of the regenconf if it exists.
# This is a pretty ad hoc solution and only applied to nginx
# because it's one of the major service, but in the long term we
# should identify the root of this bug...
_force_clear_hashes(["/etc/nginx/conf.d/%s.conf" % domain])
# And in addition we even force-delete the file Otherwise, if the file was
# manually modified, it may not get removed by the regenconf which leads to
# catastrophic consequences of nginx breaking because it can't load the
# cert file which disappeared etc..
if os.path.exists("/etc/nginx/conf.d/%s.conf" % domain):
_process_regen_conf("/etc/nginx/conf.d/%s.conf" % domain, new_conf=None, save=True)
regen_conf(names=['nginx', 'metronome', 'dnsmasq', 'postfix'])
app_ssowatconf()

View file

@ -473,6 +473,18 @@ def _update_conf_hashes(category, hashes):
_save_regenconf_infos(categories)
def _force_clear_hashes(paths):
categories = _get_regenconf_infos()
for path in paths:
for category in categories.keys():
if path in categories[category]['conffiles']:
logger.debug("force-clearing old conf hash for %s in category %s" % (path, category))
del categories[category]['conffiles'][path]
_save_regenconf_infos(categories)
def _process_regen_conf(system_conf, new_conf=None, save=True):
"""Regenerate a given system configuration file

View file

@ -9,7 +9,7 @@ from conftest import message, raiseYunohostError
from moulinette import m18n
from moulinette.utils.filesystem import mkdir
from yunohost.app import app_install, app_remove, app_ssowatconf, _is_installed, app_upgrade
from yunohost.app import app_install, app_remove, app_ssowatconf, _is_installed, app_upgrade, app_map
from yunohost.domain import _get_maindomain, domain_add, domain_remove, domain_list
from yunohost.utils.error import YunohostError
from yunohost.tests.test_permission import check_LDAP_db_integrity, check_permission_for_apps
@ -142,6 +142,12 @@ def test_legacy_app_install_main_domain():
install_legacy_app(main_domain, "/legacy")
app_map_ = app_map(raw=True)
assert main_domain in app_map_
assert '/legacy' in app_map_[main_domain]
assert 'id' in app_map_[main_domain]['/legacy']
assert app_map_[main_domain]['/legacy']['id'] == 'legacy_app'
assert app_is_installed(main_domain, "legacy_app")
assert app_is_exposed_on_http(main_domain, "/legacy", "This is a dummy app")
@ -166,6 +172,12 @@ def test_legacy_app_install_secondary_domain_on_root(secondary_domain):
install_legacy_app(secondary_domain, "/")
app_map_ = app_map(raw=True)
assert secondary_domain in app_map_
assert '/' in app_map_[secondary_domain]
assert 'id' in app_map_[secondary_domain]['/']
assert app_map_[secondary_domain]['/']['id'] == 'legacy_app'
assert app_is_installed(secondary_domain, "legacy_app")
assert app_is_exposed_on_http(secondary_domain, "/", "This is a dummy app")

View file

@ -586,9 +586,22 @@ def test_restore_archive_with_no_json(mocker):
assert "badbackup" in backup_list()["archives"]
with raiseYunohostError(mocker, 'backup_invalid_archive'):
with raiseYunohostError(mocker, 'backup_archive_cant_retrieve_info_json'):
backup_restore(name="badbackup", force=True)
@pytest.mark.with_wordpress_archive_from_2p4
def test_restore_archive_with_bad_archive(mocker):
# Break the archive
os.system("head -n 1000 /home/yunohost.backup/archives/backup_wordpress_from_2p4.tar.gz > /home/yunohost.backup/archives/backup_wordpress_from_2p4.tar.gz")
assert "backup_wordpress_from_2p4" in backup_list()["archives"]
with raiseYunohostError(mocker, 'backup_archive_open_failed'):
backup_restore(name="backup_wordpress_from_2p4", force=True)
clean_tmp_backup_directory()
def test_backup_binds_are_readonly(mocker, monkeypatch):

View file

@ -0,0 +1,80 @@
import glob
import os
import pytest
import shutil
import requests
from conftest import message, raiseYunohostError
from moulinette import m18n
from moulinette.utils.filesystem import mkdir
from yunohost.domain import _get_maindomain, domain_add, domain_remove, domain_list
from yunohost.utils.error import YunohostError
from yunohost.regenconf import manually_modified_files, _get_conf_hashes, _force_clear_hashes
TEST_DOMAIN = "secondarydomain.test"
TEST_DOMAIN_NGINX_CONFIG = "/etc/nginx/conf.d/secondarydomain.test.conf"
def setup_function(function):
_force_clear_hashes([TEST_DOMAIN_NGINX_CONFIG])
clean()
def teardown_function(function):
clean()
_force_clear_hashes([TEST_DOMAIN_NGINX_CONFIG])
def clean():
assert os.system("pgrep slapd >/dev/null") == 0
assert os.system("pgrep nginx >/dev/null") == 0
if TEST_DOMAIN in domain_list()["domains"]:
domain_remove(TEST_DOMAIN)
assert not os.path.exists(TEST_DOMAIN_NGINX_CONFIG)
os.system("rm -f %s" % TEST_DOMAIN_NGINX_CONFIG)
assert os.system("nginx -t 2>/dev/null") == 0
assert not os.path.exists(TEST_DOMAIN_NGINX_CONFIG)
assert TEST_DOMAIN_NGINX_CONFIG not in _get_conf_hashes("nginx")
assert TEST_DOMAIN_NGINX_CONFIG not in manually_modified_files()
def test_add_domain():
domain_add(TEST_DOMAIN)
assert TEST_DOMAIN in domain_list()["domains"]
assert os.path.exists(TEST_DOMAIN_NGINX_CONFIG)
assert TEST_DOMAIN_NGINX_CONFIG in _get_conf_hashes("nginx")
assert TEST_DOMAIN_NGINX_CONFIG not in manually_modified_files()
def test_add_and_edit_domain_conf():
domain_add(TEST_DOMAIN)
assert os.path.exists(TEST_DOMAIN_NGINX_CONFIG)
assert TEST_DOMAIN_NGINX_CONFIG in _get_conf_hashes("nginx")
assert TEST_DOMAIN_NGINX_CONFIG not in manually_modified_files()
os.system("echo ' ' >> %s" % TEST_DOMAIN_NGINX_CONFIG)
assert TEST_DOMAIN_NGINX_CONFIG in manually_modified_files()
def test_add_domain_conf_already_exists():
os.system("echo ' ' >> %s" % TEST_DOMAIN_NGINX_CONFIG)
domain_add(TEST_DOMAIN)
assert os.path.exists(TEST_DOMAIN_NGINX_CONFIG)
assert TEST_DOMAIN_NGINX_CONFIG in _get_conf_hashes("nginx")
assert TEST_DOMAIN_NGINX_CONFIG not in manually_modified_files()

View file

@ -21,9 +21,11 @@
import os
import re
import logging
import dns.resolver
from moulinette.utils.network import download_text
from moulinette.utils.process import check_output
from moulinette.utils.filesystem import read_file
logger = logging.getLogger('yunohost.utils.network')
@ -84,6 +86,52 @@ def get_gateway():
return addr.popitem()[1] if len(addr) == 1 else None
# Lazy dev caching to avoid re-reading the file multiple time when calling
# dig() often during same yunohost operation
external_resolvers_ = []
def external_resolvers():
global external_resolvers_
if not external_resolvers_:
resolv_dnsmasq_conf = read_file("/etc/resolv.dnsmasq.conf").split("\n")
external_resolvers_ = [r.split(" ")[1] for r in resolv_dnsmasq_conf if r.startswith("nameserver")]
return external_resolvers_
def dig(qname, rdtype="A", timeout=5, resolvers="local", edns_size=1500, full_answers=False):
"""
Do a quick DNS request and avoid the "search" trap inside /etc/resolv.conf
"""
if resolvers == "local":
resolvers = ["127.0.0.1"]
elif resolvers == "force_external":
resolvers = external_resolvers()
else:
assert isinstance(resolvers, list)
resolver = dns.resolver.Resolver(configure=False)
resolver.use_edns(0, 0, edns_size)
resolver.nameservers = resolvers
resolver.timeout = timeout
try:
answers = resolver.query(qname, rdtype)
except (dns.resolver.NXDOMAIN,
dns.resolver.NoNameservers,
dns.resolver.NoAnswer,
dns.exception.Timeout) as e:
return ("nok", (e.__class__.__name__, e))
if not full_answers:
answers = [answer.to_text() for answer in answers]
return ("ok", answers)
def _extract_inet(string, skip_netmask=False, skip_loopback=True):
"""
Extract IP addresses (v4 and/or v6) from a string limited to one