Add jinja processing to alt command
With the new functionality, when the 'alt' command is called (or automatically triggered), any file with a name ending in '##yadm_tmpl' is treated as a jinja template. The template is processed by envtpl and the result is written to a file without the '##yadm_tmpl' name. The variables passed into the template processing are YADM_CLASS YADM_OS YADM_HOSTNAME YADM_USER These variables are set according to the normal rules for CLASS, OS, HOSTNAME, and USER during the alt processing.
This commit is contained in:
parent
5678e383d8
commit
a479b70d8a
4 changed files with 233 additions and 16 deletions
151
test/113_accept_jinja_alt.bats
Normal file
151
test/113_accept_jinja_alt.bats
Normal file
|
@ -0,0 +1,151 @@
|
|||
load common
|
||||
load_fixtures
|
||||
status=;output=; #; populated by bats run()
|
||||
|
||||
IN_REPO=(alt* "dir one")
|
||||
export TEST_TREE_WITH_ALT=1
|
||||
|
||||
|
||||
setup() {
|
||||
destroy_tmp
|
||||
build_repo "${IN_REPO[@]}"
|
||||
}
|
||||
|
||||
|
||||
function test_alt() {
|
||||
local alt_type="$1"
|
||||
local test_overwrite="$2"
|
||||
local auto_alt="$3"
|
||||
|
||||
#; detemine test parameters
|
||||
case $alt_type in
|
||||
base)
|
||||
real_name="alt-jinja"
|
||||
file_content_match="-${T_SYS}-${T_HOST}-${T_USER}"
|
||||
;;
|
||||
override_all)
|
||||
real_name="alt-jinja"
|
||||
file_content_match="custom_class-custom_system-custom_host-custom_user"
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ "$test_overwrite" = "true" ] ; then
|
||||
#; create incorrect links (to overwrite)
|
||||
echo "BAD_CONTENT" "$T_DIR_WORK/$real_name"
|
||||
else
|
||||
#; verify real file doesn't already exist
|
||||
if [ -e "$T_DIR_WORK/$real_name" ] ; then
|
||||
echo "ERROR: real file already exists before running yadm"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
#; configure yadm.auto_alt=false
|
||||
if [ "$auto_alt" = "false" ]; then
|
||||
git config --file="$T_YADM_CONFIG" yadm.auto-alt false
|
||||
fi
|
||||
|
||||
#; run yadm (alt or status)
|
||||
if [ -z "$auto_alt" ]; then
|
||||
run "${T_YADM_Y[@]}" alt
|
||||
#; validate status and output
|
||||
if [ "$status" != 0 ] || [[ ! "$output" =~ Creating.+$real_name ]]; then
|
||||
echo "OUTPUT:$output"
|
||||
echo "ERROR: Could not confirm status and output of alt command"
|
||||
return 1;
|
||||
fi
|
||||
else
|
||||
#; running any passed through Git command should trigger auto-alt
|
||||
run "${T_YADM_Y[@]}" status
|
||||
if [ -n "$auto_alt" ] && [[ "$output" =~ Creating.+$real_name ]]; then
|
||||
echo "ERROR: Reporting of jinja processing should not happen"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
#; validate link content
|
||||
if [[ "$alt_type" =~ none ]] || [ "$auto_alt" = "false" ]; then
|
||||
#; no real file should be present
|
||||
if [ -L "$T_DIR_WORK/$real_name" ] ; then
|
||||
echo "ERROR: Real file should not exist"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
#; correct real file should be present
|
||||
local file_content
|
||||
file_content=$(cat "$T_DIR_WORK/$real_name")
|
||||
if [ "$file_content" != "$file_content_match" ]; then
|
||||
echo "file_content: ${file_content}"
|
||||
echo "expected_content: ${file_content_match}"
|
||||
echo "ERROR: Link content is not correct"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
@test "Command 'alt' (select jinja)" {
|
||||
echo "
|
||||
When the command 'alt' is provided
|
||||
and file matches ##yadm_tmpl
|
||||
Report jinja template processing
|
||||
Verify that the correct content is written
|
||||
Exit with 0
|
||||
"
|
||||
|
||||
test_alt 'base' 'false' ''
|
||||
}
|
||||
|
||||
@test "Command 'auto-alt' (enabled)" {
|
||||
echo "
|
||||
When a command possibly changes the repo
|
||||
and auto-alt is configured true
|
||||
and file matches ##yadm_tmpl
|
||||
automatically process alternates
|
||||
report no linking (not loud)
|
||||
Verify that the correct content is written
|
||||
"
|
||||
|
||||
test_alt 'base' 'false' 'true'
|
||||
}
|
||||
|
||||
@test "Command 'auto-alt' (disabled)" {
|
||||
echo "
|
||||
When a command possibly changes the repo
|
||||
and auto-alt is configured false
|
||||
and file matches ##yadm_tmpl
|
||||
Report no jinja template processing
|
||||
Verify no content
|
||||
"
|
||||
|
||||
test_alt 'base' 'false' 'false'
|
||||
}
|
||||
|
||||
@test "Command 'alt' (overwrite existing content)" {
|
||||
echo "
|
||||
When the command 'alt' is provided
|
||||
and file matches ##yadm_tmpl
|
||||
and the real file exists, and is wrong
|
||||
Report jinja template processing
|
||||
Verify that the correct content is written
|
||||
Exit with 0
|
||||
"
|
||||
|
||||
test_alt 'base' 'true' ''
|
||||
}
|
||||
|
||||
@test "Command 'alt' (overwritten settings)" {
|
||||
echo "
|
||||
When the command 'alt' is provided
|
||||
and file matches ##yadm_tmpl
|
||||
after setting local.*
|
||||
Report jinja template processing
|
||||
Verify that the correct content is written
|
||||
Exit with 0
|
||||
"
|
||||
|
||||
GIT_DIR="$T_DIR_REPO" git config local.os custom_system
|
||||
GIT_DIR="$T_DIR_REPO" git config local.user custom_user
|
||||
GIT_DIR="$T_DIR_REPO" git config local.host custom_host
|
||||
GIT_DIR="$T_DIR_REPO" git config local.class custom_class
|
||||
test_alt 'override_all' 'false' ''
|
||||
}
|
|
@ -202,8 +202,10 @@ function create_worktree() {
|
|||
make_parents "$DIR_WORKTREE/$f"
|
||||
echo "$f" > "$DIR_WORKTREE/$f"
|
||||
done
|
||||
echo "{{ YADM_CLASS }}-{{ YADM_OS }}-{{ YADM_HOSTNAME }}-{{ YADM_USER }}" > "$DIR_WORKTREE/alt-jinja##yadm_tmpl"
|
||||
fi
|
||||
|
||||
|
||||
if [ ! -z "$TEST_TREE_WITH_WILD" ] ; then
|
||||
#; wildcard test data - yes this is a big mess :(
|
||||
#; none
|
||||
|
|
56
yadm
56
yadm
|
@ -114,30 +114,32 @@ function alt() {
|
|||
|
||||
require_repo
|
||||
|
||||
match_class="$(config local.class)"
|
||||
if [ -z "$match_class" ] ; then
|
||||
local_class="$(config local.class)"
|
||||
if [ -z "$local_class" ] ; then
|
||||
match_class="%"
|
||||
else
|
||||
match_class="$local_class"
|
||||
fi
|
||||
match_class="(%|$match_class)"
|
||||
|
||||
match_system="$(config local.os)"
|
||||
if [ -z "$match_system" ] ; then
|
||||
match_system=$(uname -s)
|
||||
local_system="$(config local.os)"
|
||||
if [ -z "$local_system" ] ; then
|
||||
local_system=$(uname -s)
|
||||
fi
|
||||
match_system="(%|$match_system)"
|
||||
match_system="(%|$local_system)"
|
||||
|
||||
match_host="$(config local.host)"
|
||||
if [ -z "$match_host" ] ; then
|
||||
match_host=$(hostname)
|
||||
match_host=${match_host%%.*} #; trim any domain from hostname
|
||||
local_host="$(config local.host)"
|
||||
if [ -z "$local_host" ] ; then
|
||||
local_host=$(hostname)
|
||||
local_host=${local_host%%.*} #; trim any domain from hostname
|
||||
fi
|
||||
match_host="(%|$match_host)"
|
||||
match_host="(%|$local_host)"
|
||||
|
||||
match_user="$(config local.user)"
|
||||
if [ -z "$match_user" ] ; then
|
||||
match_user=$(id -u -n)
|
||||
local_user="$(config local.user)"
|
||||
if [ -z "$local_user" ] ; then
|
||||
local_user=$(id -u -n)
|
||||
fi
|
||||
match_user="(%|$match_user)"
|
||||
match_user="(%|$local_user)"
|
||||
|
||||
#; regex for matching "<file>##CLASS.SYSTEM.HOSTNAME.USER"
|
||||
match1="^(.+)##(()|$match_system|$match_system\.$match_host|$match_system\.$match_host\.$match_user)$"
|
||||
|
@ -193,6 +195,30 @@ function alt() {
|
|||
done
|
||||
done
|
||||
|
||||
#; loop over all "tracked" files
|
||||
#; for every file which is a *##yadm_tmpl create a real file
|
||||
local IFS=$'\n'
|
||||
local match="^(.+)##yadm_tmpl"
|
||||
local envtpl_bin=$(which envtpl)
|
||||
for tracked_file in $("$GIT_PROGRAM" ls-files | sort) $(cat "$YADM_ENCRYPT" 2>/dev/null); do
|
||||
tracked_file="$YADM_WORK/$tracked_file"
|
||||
if [ -e "$tracked_file" ] ; then
|
||||
if [[ $tracked_file =~ $match ]] ; then
|
||||
if [[ -z "$envtpl_bin" ]]; then
|
||||
debug "'envtpl' (pip install envtpl) not available, not creating $real_file from template $tracked_file"
|
||||
[ -n "$loud" ] && echo "'envtpl' (pip install envtpl) not available, not creating $real_file from template $tracked_file"
|
||||
else
|
||||
real_file="${BASH_REMATCH[1]}"
|
||||
debug "Creating $real_file from template $tracked_file"
|
||||
[ -n "$loud" ] && echo "Creating $real_file from template $tracked_file"
|
||||
YADM_CLASS="$local_class" YADM_OS="$local_system" \
|
||||
YADM_HOSTNAME="$local_host" YADM_USER="$local_user" \
|
||||
$envtpl_bin < $tracked_file > $real_file
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
}
|
||||
|
||||
function bootstrap() {
|
||||
|
|
40
yadm.1
40
yadm.1
|
@ -89,7 +89,8 @@ Instead use the
|
|||
command (see below).
|
||||
.TP
|
||||
.B alt
|
||||
Create symbolic links for any managed files matching the naming rules describe in the ALTERNATES section.
|
||||
Create symbolic links and process jinja templates for any managed files matching the naming rules describe
|
||||
in the ALTERNATES section.
|
||||
It is usually unnecessary to run this command, as
|
||||
.B yadm
|
||||
automatically processes alternates by default.
|
||||
|
@ -473,6 +474,43 @@ using the configuration options
|
|||
and
|
||||
.BR local.user .
|
||||
|
||||
If
|
||||
.BR envtpl
|
||||
(
|
||||
.BR pip\ install\ envtpl
|
||||
) is available, you can also create
|
||||
.B jinja
|
||||
templates (http://jinja.pocoo.org/) which will transformed into real files.
|
||||
.B yadm
|
||||
will treat files ending in
|
||||
|
||||
##yadm_tmpl
|
||||
|
||||
as jinja templates. During processing, the following variables are
|
||||
set according to the above rules:
|
||||
|
||||
YADM_CLASS
|
||||
YADM_OS
|
||||
YADM_HOSTNAME
|
||||
YADM_USER
|
||||
|
||||
E.g. a file 'whatever##yadm_tmpl' with the following content
|
||||
|
||||
{% if YADM_USER == 'harvey' -%}
|
||||
config={{YADM_CLASS}}-{{ YADM_OS }}
|
||||
{% else -%}
|
||||
config=dev-whatever
|
||||
{% endif -%}
|
||||
|
||||
would output a file with the follwing content, if the username would be 'harvey'
|
||||
|
||||
config=work-Linux
|
||||
|
||||
and the following otherwise:
|
||||
|
||||
config=dev-whatever
|
||||
|
||||
|
||||
.SH ENCRYPTION
|
||||
It can be useful to manage confidential files, like SSH or GPG keys, across
|
||||
multiple systems. However, doing so would put plain text data into a Git
|
||||
|
|
Loading…
Reference in a new issue