From 12764652b0469ba4d839ec80c3481b11d3546842 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Sun, 26 May 2024 20:10:30 +0200 Subject: [PATCH 1/2] helpers: Add a --jinja option to ynh_add_config --- debian/control | 2 +- helpers/utils | 24 ++++++--- tests/test_helpers.d/ynhtest_templating.sh | 62 ++++++++++++++++++++++ tests/test_helpers.sh | 4 ++ 4 files changed, 83 insertions(+), 9 deletions(-) create mode 100644 tests/test_helpers.d/ynhtest_templating.sh diff --git a/debian/control b/debian/control index 2fa1a12206..8139375e75 100644 --- a/debian/control +++ b/debian/control @@ -27,7 +27,7 @@ Depends: ${python3:Depends}, ${misc:Depends} , rspamd, opendkim-tools, postsrsd, procmail, mailutils , redis-server , acl - , git, curl, wget, cron, unzip, jq, bc, at, procps + , git, curl, wget, cron, unzip, jq, bc, at, procps, j2cli , lsb-release, haveged, fake-hwclock, equivs, lsof, whois Recommends: yunohost-admin , ntp, inetutils-ping | iputils-ping diff --git a/helpers/utils b/helpers/utils index f182fee382..50a26c4358 100644 --- a/helpers/utils +++ b/helpers/utils @@ -489,13 +489,15 @@ ynh_local_curl() { # Requires YunoHost version 4.1.0 or higher. ynh_add_config() { # Declare an array to define the options of this helper. - local legacy_args=tdv - local -A args_array=([t]=template= [d]=destination=) + local legacy_args=tdj + local -A args_array=([t]=template= [d]=destination= [j]=jinja) local template local destination + local jinja # Manage arguments with getopts ynh_handle_getopts_args "$@" local template_path + jinja="${jinja:-0}" if [ -f "$YNH_APP_BASEDIR/conf/$template" ]; then template_path="$YNH_APP_BASEDIR/conf/$template" @@ -512,14 +514,20 @@ ynh_add_config() { # created a file beforehand to have control over it # (cp won't overwrite ownership / modes by default...) touch $destination - chown root:root $destination chmod 640 $destination - - cp -f "$template_path" "$destination" - _ynh_apply_default_permissions $destination - ynh_replace_vars --file="$destination" + if [[ "$jinja" == 1 ]] + then + # This is ran in a subshell such that the "export" does not "contaminate" the main process + ( + export $(compgen -v) + j2 "$template_path" -f env -o $destination + ) + else + cp -f "$template_path" "$destination" + ynh_replace_vars --file="$destination" + fi ynh_store_file_checksum --file="$destination" } @@ -1088,7 +1096,7 @@ _ynh_apply_default_permissions() { # Crons should be owned by root # Also we don't want systemd conf, nginx conf or others stuff to be owned by the app, # otherwise they could self-edit their own systemd conf and escalate privilege - if echo "$target" | grep -q '^/etc/cron\|/etc/php\|/etc/nginx/conf.d\|/etc/fail2ban\|/etc/systemd/system' + if grep -qE '^(/etc/cron|/etc/php|/etc/nginx/conf.d|/etc/fail2ban|/etc/systemd/system)' <<< "$target" then chmod 400 $target chown root:root $target diff --git a/tests/test_helpers.d/ynhtest_templating.sh b/tests/test_helpers.d/ynhtest_templating.sh new file mode 100644 index 0000000000..118e643ee7 --- /dev/null +++ b/tests/test_helpers.d/ynhtest_templating.sh @@ -0,0 +1,62 @@ +ynhtest_simple_template_app_config() { + + mkdir -p /etc/yunohost/apps/$app/ + echo "id: $app" > /etc/yunohost/apps/$app/settings.yml + + template="$(mktemp -d -p $VAR_WWW)/template.txt" + cat << EOF > $template +app=__APP__ +foo=__FOO__ +EOF + + foo="bar" + + ynh_add_config --template="$template" --destination="$VAR_WWW/config.txt" + + test "$(cat $VAR_WWW/config.txt)" == "$(echo -ne 'app=ynhtest\nfoo=bar')" + test "$(ls -l $VAR_WWW/config.txt | cut -d' ' -f1-4)" == "-rw-r----- 1 ynhtest ynhtest" +} + +ynhtest_simple_template_system_config() { + + mkdir -p /etc/yunohost/apps/$app/ + echo "id: $app" > /etc/yunohost/apps/$app/settings.yml + + rm -f /etc/cron.d/ynhtest_config + + template="$(mktemp -d -p $VAR_WWW)/template.txt" + cat << EOF > $template +app=__APP__ +foo=__FOO__ +EOF + + foo="bar" + + ynh_add_config --template="$template" --destination="/etc/cron.d/ynhtest_config" + + test "$(cat $VAR_WWW/config.txt)" == "$(echo -ne 'app=ynhtest\nfoo=bar')" + test "$(ls -l /etc/cron.d/ynhtest_config | cut -d' ' -f1-4)" == "-r-------- 1 root root" + + rm -f /etc/cron.d/ynhtest_config +} + +ynhtest_jinja_template_app_config() { + + mkdir -p /etc/yunohost/apps/$app/ + echo "id: $app" > /etc/yunohost/apps/$app/settings.yml + + template="$(mktemp -d -p $VAR_WWW)/template.txt" + cat << EOF > $template +app={{ app }} +{% if foo == "bar" %}foo=true{% endif %} +EOF + + foo="bar" + + ynh_add_config --template="$template" --destination="$VAR_WWW/config.txt" --jinja + + test "$(cat $VAR_WWW/config.txt)" == "$(echo -ne 'app=ynhtest\nfoo=true')" + test "$(ls -l $VAR_WWW/config.txt | cut -d' ' -f1-4)" == "-rw-r----- 1 ynhtest ynhtest" +} + + diff --git a/tests/test_helpers.sh b/tests/test_helpers.sh index 153ce1386d..a2ccb75c49 100644 --- a/tests/test_helpers.sh +++ b/tests/test_helpers.sh @@ -41,6 +41,10 @@ popd >/dev/null VAR_WWW=$(mktemp -d)/var/www mkdir -p $VAR_WWW + +# Needed to check the permission behavior in ynh_add_config x_x +getent passwd ynhtest &>/dev/null || useradd --system ynhtest + # ========================================================= for TEST_SUITE in $(ls test_helpers.d/*) From 4a9a3ba138373a474d30fcb7d60df39b25d2cbb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josu=C3=A9=20Tille?= Date: Tue, 28 May 2024 00:39:04 +0200 Subject: [PATCH 2/2] Update doc about helper ynh_add_config --- helpers/utils | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/helpers/utils b/helpers/utils index 50a26c4358..d8039b6598 100644 --- a/helpers/utils +++ b/helpers/utils @@ -451,12 +451,17 @@ ynh_local_curl() { # # usage: ynh_add_config --template="template" --destination="destination" # | arg: -t, --template= - Template config file to use -# | arg: -d, --destination= - Destination of the config file +# | arg: -d, --destination= - Destination of the config file +# | arg: -j, --jinja - Use jinja template instead of legacy __MY_VAR__ # # examples: # ynh_add_config --template=".env" --destination="$install_dir/.env" use the template file "../conf/.env" +# ynh_add_config --jinja --template="config.j2" --destination="$install_dir/config" use the template file "../conf/config.j2" # ynh_add_config --template="/etc/nginx/sites-available/default" --destination="etc/nginx/sites-available/mydomain.conf" # +## +## How it works in "legacy" mode +## # The template can be by default the name of a file in the conf directory # of a YunoHost Package, a relative path or an absolute path. # @@ -480,6 +485,37 @@ ynh_local_curl() { # __VAR_2__ by $var_2 # ``` # +## +## When --jinja is enabled +## +# For a full documentation of the template you can refer to: https://jinja.palletsprojects.com/en/3.1.x/templates/ +# In Yunohost context there are no really some specificity except that all variable passed are of type string. +# So here are some example of recommended usage: +# +# If you need a conditional block +# +# {% if should_my_block_be_shown == 'true' %} +# ... +# {% endif %} +# +# or +# +# {% if should_my_block_be_shown == '1' %} +# ... +# {% endif %} +# +# If you need to iterate with loop: +# +# {% for yolo in var_with_multiline_value.splitlines() %} +# ... +# {% endfor %} +# +# or +# +# {% for jail in my_var_with_coma.split(',') %} +# ... +# {% endfor %} +# # The helper will verify the checksum and backup the destination file # if it's different before applying the new template. #