1
0
mirror of https://github.com/deadc0de6/dotdrop.git synced 2026-02-05 06:48:49 +00:00

adding dynamic/interpreted template variables

This commit is contained in:
deadc0de6
2018-11-15 23:25:42 +01:00
parent 3af31cc5f2
commit 4d0a1a798a
4 changed files with 180 additions and 23 deletions

View File

@@ -81,6 +81,10 @@ why [dotdrop](https://github.com/deadc0de6/dotdrop) rocks.
* [Config](#config)
* [Templating](#templating)
* [Available variables](#available-variables)
* [Dotdrop header](#dotdrop-header)
* [Example](#example)
* [User tricks](#user-tricks)
* [People using dotdrop](#people-using-dotdrop)
@@ -623,12 +627,18 @@ the following entries:
<trans-key>: <command-to-execute>
```
* **variables** entry (optional): a list of template variables (see [Available variables](#available-variables))
* **variables** entry (optional): a list of template variables (see [Variables](#variables))
```
<variable-name>: <variable-content>
```
* **dynvariables** entry (optional): a list of interpreted variables (see [Interpreted variables](#interpreted-variables))
```
<variable-name>: <shell-oneliner>>
```
## All dotfiles for a profile
To use all defined dotfiles for a profile, simply use
@@ -673,9 +683,10 @@ Here profile *host1* contains all the dotfiles defined for *host2* plus `f_xinit
## Ignore empty template
It is possible not to deploy template file if their rendered content
is empty. Simply set the global setting `ignoreempty` to true for this
behavior for all dotfiles or specifically to one or more dotfile entries.
It is possible to avoid having an empty rendered template being
deployed by setting the `ignoreempty` entry to *true*. This can be set
globally for all dotfiles or only for specific dotfiles.
For more see the [Config](#config).
# Templating
@@ -695,13 +706,18 @@ Note that dotdrop uses different delimiters than
## Available variables
Following template variables are available:
* `{{@@ profile @@}}` contains the profile provided to dotdrop.
* `{{@@ env['MY_VAR'] @@}}` contains environment variables (see [Environment variables](#environment-variables)).
* `{{@@ header() @@}}` insert dotdrop header (see [Dotdrop header](#dotdrop-header)).
* defined variables (see [Variables](#variables))
* interpreted variables (see [Interpreted variables](#interpreted-variables))
Addionally to the above, variables can be added in the config file under
the `variables` entry. The variables added there are directly reachable in
any templates.
## Variables
Variables can be added in the config file under the `variables` entry.
The variables added there are directly reachable in any templates.
For example in the config file:
```yaml
@@ -714,26 +730,24 @@ These can then be used in any template with
{{@@ var1 @@}}
```
## Dotdrop header
## Interpreted variables
Dotdrop is able to insert a header in the generated dotfiles. This allows
to remind anyone opening the file for editing that this file is managed by dotdrop.
It is also possible to have *dynamic* variables in the sense that their
content will be interpreted by the shell before being replaced in the templates.
Here's what it looks like:
```
This dotfile is managed using dotdrop
For example:
```yaml
dynvariables:
dvar1: head -1 /proc/meminfo
dvar2: "echo 'this is some test' | rev | tr ' ' ','"
dvar3: /tmp/my_shell_script.sh
```
The header can be automatically added using jinja2 directive:
These can be used as any variables in the templates
```
{{@@ header() @@}}
{{@@ dvar1 @@}}
```
Properly commenting the header in templates is the responsability of the user
as jinja2 has no way of knowing what is the proper char(s) used for comments.
Either prepend the directive with the commenting char(s) used in the dotfile (for example `# {{@@ header() @@}}`)
or provide it as an argument `{{@@ header('# ') @@}}`. The result is equivalent.
## Environment variables
It's possible to access environment variables inside the templates.
@@ -766,6 +780,26 @@ alias dotdrop='eval $(grep -v "^#" ~/dotfiles/.env) /usr/bin/dotdrop --cfg=~/dot
The above aliases load all the variables from `~/dotfiles/.env`
(while omitting lines starting with `#`) before calling dotdrop.
## Dotdrop header
Dotdrop is able to insert a header in the generated dotfiles. This allows
to remind anyone opening the file for editing that this file is managed by dotdrop.
Here's what it looks like:
```
This dotfile is managed using dotdrop
```
The header can be automatically added using jinja2 directive:
```
{{@@ header() @@}}
```
Properly commenting the header in templates is the responsability of the user
as jinja2 has no way of knowing what is the proper char(s) used for comments.
Either prepend the directive with the commenting char(s) used in the dotfile (for example `# {{@@ header() @@}}`)
or provide it as an argument `{{@@ header('# ') @@}}`. The result is equivalent.
## Debug template
To debug the result of a template, one can install the dotfiles to a temporary

View File

@@ -13,6 +13,7 @@ import shlex
from dotdrop.dotfile import Dotfile
from dotdrop.logger import Logger
from dotdrop.action import Action, Transform
from dotdrop.utils import *
TILD = '~'
@@ -44,6 +45,8 @@ class Cfg:
# template variables
key_variables = 'variables'
# shell variable
key_dynvariables = 'dynvariables'
# dotfiles keys
key_dotfiles = 'dotfiles'
@@ -521,9 +524,15 @@ class Cfg:
return self.lnk_settings.copy()
def get_variables(self):
variables = {}
if self.key_variables in self.content:
return self.content[self.key_variables]
return {}
variables.update(self.content[self.key_variables])
if self.key_dynvariables in self.content:
# interpret dynamic variables
dynvars = self.content[self.key_dynvariables]
for key, cmd in dynvars.items():
variables[key] = shell(cmd)
return variables
def dump(self):
"""return a dump of the config"""

View File

@@ -19,7 +19,7 @@ LOG = Logger()
def run(cmd, raw=True, debug=False, checkerr=False):
"""run a command in the shell (expects a list)"""
"""run a command (expects a list)"""
if debug:
LOG.dbg('exec: {}'.format(' '.join(cmd)))
p = subprocess.Popen(cmd, shell=False,
@@ -38,6 +38,11 @@ def run(cmd, raw=True, debug=False, checkerr=False):
return ret == 0, lines
def shell(cmd):
"""run a command in the shell (expects a string)"""
return subprocess.getoutput(cmd)
def diff(src, dst, raw=True, opts='', debug=False):
"""call unix diff to compare two files"""
cmd = 'diff -r {} \"{}\" \"{}\"'.format(opts, src, dst)

109
tests-ng/dynvariables.sh Executable file
View File

@@ -0,0 +1,109 @@
#!/usr/bin/env bash
# author: deadc0de6 (https://github.com/deadc0de6)
# Copyright (c) 2017, deadc0de6
#
# test dynamic variables from yaml file
# returns 1 in case of error
#
# exit on first error
set -e
# all this crap to get current path
rl="readlink -f"
if ! ${rl} "${0}" >/dev/null 2>&1; then
rl="realpath"
if ! hash ${rl}; then
echo "\"${rl}\" not found !" && exit 1
fi
fi
cur=$(dirname "$(${rl} "${0}")")
#hash dotdrop >/dev/null 2>&1
#[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1
#echo "called with ${1}"
# dotdrop path can be pass as argument
ddpath="${cur}/../"
[ "${1}" != "" ] && ddpath="${1}"
[ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1
export PYTHONPATH="${ddpath}:${PYTHONPATH}"
bin="python3 -m dotdrop.dotdrop"
echo "dotdrop path: ${ddpath}"
echo "pythonpath: ${PYTHONPATH}"
# get the helpers
source ${cur}/helpers
echo -e "\e[96m\e[1m==> RUNNING $(basename $BASH_SOURCE) <==\e[0m"
################################################################
# this is the test
################################################################
# the dotfile source
tmps=`mktemp -d`
mkdir -p ${tmps}/dotfiles
# the dotfile destination
tmpd=`mktemp -d`
#echo "dotfile destination: ${tmpd}"
# create a shell script
export TESTENV="this is my testenv"
scr=`mktemp`
chmod +x ${scr}
echo -e "#!/bin/bash\necho $TESTENV\n" >> ${scr}
# create the config file
cfg="${tmps}/config.yaml"
cat > ${cfg} << _EOF
config:
backup: true
create: true
dotpath: dotfiles
variables:
var1: "this is some test"
dynvariables:
dvar1: head -1 /proc/meminfo
dvar2: "echo 'this is some test' | rev | tr ' ' ','"
dvar3: ${scr}
dotfiles:
f_abc:
dst: ${tmpd}/abc
src: abc
profiles:
p1:
dotfiles:
- f_abc
_EOF
cat ${cfg}
# create the dotfile
echo "{{@@ var1 @@}}" > ${tmps}/dotfiles/abc
echo "{{@@ dvar1 @@}}" >> ${tmps}/dotfiles/abc
echo "{{@@ dvar2 @@}}" >> ${tmps}/dotfiles/abc
echo "{{@@ dvar3 @@}}" >> ${tmps}/dotfiles/abc
echo "test" >> ${tmps}/dotfiles/abc
# install
cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V
#cat ${tmpd}/abc
grep '^this is some test' ${tmpd}/abc >/dev/null
grep "^MemTotal" ${tmpd}/abc >/dev/null
grep '^tset,emos,si,siht' ${tmpd}/abc >/dev/null
grep "^${TESTENV}" ${tmpd}/abc > /dev/null
#cat ${tmpd}/abc
## CLEANING
rm -rf ${tmps} ${tmpd} ${scr}
echo "OK"
exit 0