yunohost/data/helpers.d/config

273 lines
10 KiB
Bash

#!/bin/bash
_ynh_app_config_get() {
# From settings
local lines
lines=`python3 << EOL
import toml
from collections import OrderedDict
with open("../config_panel.toml", "r") as f:
file_content = f.read()
loaded_toml = toml.loads(file_content, _dict=OrderedDict)
for panel_name, panel in loaded_toml.items():
if not isinstance(panel, dict): continue
for section_name, section in panel.items():
if not isinstance(section, dict): continue
for name, param in section.items():
if not isinstance(param, dict):
continue
print(';'.join([
name,
param.get('type', 'string'),
param.get('source', 'settings' if param.get('type', 'string') != 'file' else '')
]))
EOL
`
for line in $lines
do
IFS=';' read short_setting type source <<< "$line"
local getter="get__${short_setting}"
sources[${short_setting}]="$source"
types[${short_setting}]="$type"
file_hash[${short_setting}]=""
formats[${short_setting}]=""
# Get value from getter if exists
if type -t $getter 2>/dev/null | grep -q '^function$' 2>/dev/null; then
old[$short_setting]="$($getter)"
formats[${short_setting}]="yaml"
elif [[ "$source" == "" ]] ; then
old[$short_setting]="YNH_NULL"
# Get value from app settings or from another file
elif [[ "$type" == "file" ]] ; then
if [[ "$source" == "settings" ]] ; then
ynh_die "File '${short_setting}' can't be stored in settings"
fi
old[$short_setting]="$(ls $(echo $source | sed s@__FINALPATH__@$final_path@ | sed s/__APP__/$app/) 2> /dev/null || echo YNH_NULL)"
file_hash[$short_setting]="true"
# Get multiline text from settings or from a full file
elif [[ "$type" == "text" ]] ; then
if [[ "$source" == "settings" ]] ; then
old[$short_setting]="$(ynh_app_setting_get $app $short_setting)"
elif [[ "$source" == *":"* ]] ; then
ynh_die "For technical reasons, multiline text '${short_setting}' can't be stored automatically in a variable file, you have to create custom getter/setter"
else
old[$short_setting]="$(cat $(echo $source | sed s@__FINALPATH__@$final_path@ | sed s/__APP__/$app/) 2> /dev/null || echo YNH_NULL)"
fi
# Get value from a kind of key/value file
else
if [[ "$source" == "settings" ]] ; then
source=":/etc/yunohost/apps/$app/settings.yml"
fi
local source_key="$(echo "$source" | cut -d: -f1)"
source_key=${source_key:-$short_setting}
local source_file="$(echo "$source" | cut -d: -f2 | sed s@__FINALPATH__@$final_path@ | sed s/__APP__/$app/)"
old[$short_setting]="$(ynh_read_var_in_file --file="${source_file}" --key="${source_key}")"
fi
done
}
_ynh_app_config_apply() {
for short_setting in "${!old[@]}"
do
local setter="set__${short_setting}"
local source="${sources[$short_setting]}"
local type="${types[$short_setting]}"
if [ "${changed[$short_setting]}" == "true" ] ; then
# Apply setter if exists
if type -t $setter 2>/dev/null | grep -q '^function$' 2>/dev/null; then
$setter
elif [[ "$source" == "" ]] ; then
continue
# Save in a file
elif [[ "$type" == "file" ]] ; then
if [[ "$source" == "settings" ]] ; then
ynh_die "File '${short_setting}' can't be stored in settings"
fi
local source_file="$(echo "$source" | sed s@__FINALPATH__@$final_path@ | sed s/__APP__/$app/)"
if [[ "${!short_setting}" == "" ]] ; then
ynh_backup_if_checksum_is_different --file="$source_file"
rm -f "$source_file"
ynh_delete_file_checksum --file="$source_file" --update_only
ynh_print_info "File '$source_file' removed"
else
ynh_backup_if_checksum_is_different --file="$source_file"
cp "${!short_setting}" "$source_file"
ynh_store_file_checksum --file="$source_file" --update_only
ynh_print_info "File '$source_file' overwrited with ${!short_setting}"
fi
# Save value in app settings
elif [[ "$source" == "settings" ]] ; then
ynh_app_setting_set $app $short_setting "${!short_setting}"
ynh_print_info "Configuration key '$short_setting' edited in app settings"
# Save multiline text in a file
elif [[ "$type" == "text" ]] ; then
if [[ "$source" == *":"* ]] ; then
ynh_die "For technical reasons, multiline text '${short_setting}' can't be stored automatically in a variable file, you have to create custom getter/setter"
fi
local source_file="$(echo "$source" | sed s@__FINALPATH__@$final_path@ | sed s/__APP__/$app/)"
ynh_backup_if_checksum_is_different --file="$source_file"
echo "${!short_setting}" > "$source_file"
ynh_store_file_checksum --file="$source_file" --update_only
ynh_print_info "File '$source_file' overwrited with the content you provieded in '${short_setting}' question"
# Set value into a kind of key/value file
else
local source_key="$(echo "$source" | cut -d: -f1)"
source_key=${source_key:-$short_setting}
local source_file="$(echo "$source" | cut -d: -f2 | sed s@__FINALPATH__@$final_path@ | sed s/__APP__/$app/)"
ynh_backup_if_checksum_is_different --file="$source_file"
ynh_write_var_in_file --file="${source_file}" --key="${source_key}" --value="${!short_setting}"
ynh_store_file_checksum --file="$source_file" --update_only
# We stored the info in settings in order to be able to upgrade the app
ynh_app_setting_set $app $short_setting "${!short_setting}"
ynh_print_info "Configuration key '$source_key' edited into $source_file"
fi
fi
done
}
_ynh_app_config_show() {
for short_setting in "${!old[@]}"
do
if [[ "${old[$short_setting]}" != YNH_NULL ]] ; then
if [[ "${formats[$short_setting]}" == "yaml" ]] ; then
ynh_return "${short_setting}:"
ynh_return "$(echo "${old[$short_setting]}" | sed 's/^/ /g')"
else
ynh_return "${short_setting}: "'"'"$(echo "${old[$short_setting]}" | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\n\n/g')"'"'
fi
fi
done
}
_ynh_app_config_validate() {
# Change detection
ynh_script_progression --message="Checking what changed in the new configuration..." --weight=1
local is_error=true
#for changed_status in "${!changed[@]}"
for short_setting in "${!old[@]}"
do
changed[$short_setting]=false
if [ -z ${!short_setting+x} ]; then
# Assign the var with the old value in order to allows multiple
# args validation
declare "$short_setting"="${old[$short_setting]}"
continue
fi
if [ ! -z "${file_hash[${short_setting}]}" ] ; then
file_hash[old__$short_setting]=""
file_hash[new__$short_setting]=""
if [ -f "${old[$short_setting]}" ] ; then
file_hash[old__$short_setting]=$(sha256sum "${old[$short_setting]}" | cut -d' ' -f1)
if [ -z "${!short_setting}" ] ; then
changed[$short_setting]=true
is_error=false
fi
fi
if [ -f "${!short_setting}" ] ; then
file_hash[new__$short_setting]=$(sha256sum "${!short_setting}" | cut -d' ' -f1)
if [[ "${file_hash[old__$short_setting]}" != "${file_hash[new__$short_setting]}" ]]
then
changed[$short_setting]=true
is_error=false
fi
fi
else
if [[ "${!short_setting}" != "${old[$short_setting]}" ]]
then
changed[$short_setting]=true
is_error=false
fi
fi
done
if [[ "$is_error" == "true" ]]
then
ynh_print_info "Nothing has changed"
exit 0
fi
# Run validation if something is changed
ynh_script_progression --message="Validating the new configuration..." --weight=1
for short_setting in "${!old[@]}"
do
[[ "${changed[$short_setting]}" == "false" ]] && continue
local result=""
if type -t validate__$short_setting | grep -q '^function$' 2>/dev/null; then
result="$(validate__$short_setting)"
fi
if [ -n "$result" ]
then
local key="YNH_ERROR_${short_setting}"
ynh_return "$key: \"$result\""
is_error=true
fi
done
if [[ "$is_error" == "true" ]]
then
exit 0
fi
}
ynh_app_config_get() {
_ynh_app_config_get
}
ynh_app_config_show() {
_ynh_app_config_show
}
ynh_app_config_validate() {
_ynh_app_config_validate
}
ynh_app_config_apply() {
_ynh_app_config_apply
}
ynh_app_config_run() {
declare -Ag old=()
declare -Ag changed=()
declare -Ag file_hash=()
declare -Ag sources=()
declare -Ag types=()
declare -Ag formats=()
case $1 in
show)
ynh_app_config_get
ynh_app_config_show
;;
apply)
max_progression=4
ynh_script_progression --message="Reading config panel description and current configuration..."
ynh_app_config_get
ynh_app_config_validate
ynh_script_progression --message="Applying the new configuration..."
ynh_app_config_apply
ynh_script_progression --message="Configuration of $app completed" --last
;;
esac
}