Add support for ESH

This commit is contained in:
Jonathan Daigle 2020-05-19 22:27:14 -04:00 committed by Jonathan Daigle
parent 550a6b4340
commit f348e154c7
No known key found for this signature in database
GPG Key ID: 90C82C275D872859
9 changed files with 175 additions and 5 deletions

View File

@ -27,3 +27,4 @@ Patrick Hof
Russ Allbery
Satoshi Ohki
Sheng Yang
Jonathan Daigle

View File

@ -36,6 +36,9 @@ RUN pip3 install \
yamllint==1.17.0 \
;
RUN curl https://raw.githubusercontent.com/jirutka/esh/v0.3.0/esh > /usr/local/bin/esh; \
chmod +x /usr/local/bin/esh
# Create a flag to identify when running inside the yadm testbed
RUN touch /.yadmtestbed

View File

@ -90,7 +90,7 @@ $(PYTESTS):
test:
@if [ -f /.yadmtestbed ]; then \
cd /yadm && \
py.test -v $(testargs); \
py.test -vv $(testargs); \
else \
if command -v "docker-compose" &> /dev/null; then \
docker-compose run --rm testbed make test testargs="$(testargs)"; \

View File

@ -4,4 +4,4 @@ services:
testbed:
volumes:
- .:/yadm:ro
image: yadm/testbed:2020-01-20
build: .

View File

@ -126,7 +126,7 @@ def test_alt_conditions(
@pytest.mark.usefixtures('ds1_copy')
@pytest.mark.parametrize(
'kind', ['default', '', None, 'envtpl', 'j2cli', 'j2'])
'kind', ['default', '', None, 'envtpl', 'j2cli', 'j2', 'esh'])
@pytest.mark.parametrize('label', ['t', 'template', 'yadm', ])
def test_alt_templates(
runner, paths, kind, label):

View File

@ -0,0 +1,114 @@
"""Unit tests: template_esh"""
LOCAL_CLASS = "esh_Test+@-!^Class"
LOCAL_SYSTEM = "esh_Test+@-!^System"
LOCAL_HOST = "esh_Test+@-!^Host"
LOCAL_USER = "esh_Test+@-!^User"
LOCAL_DISTRO = "esh_Test+@-!^Distro"
TEMPLATE = f'''
start of template
esh class = ><%=$YADM_CLASS%><
esh os = ><%=$YADM_OS%><
esh host = ><%=$YADM_HOSTNAME%><
esh user = ><%=$YADM_USER%><
esh distro = ><%=$YADM_DISTRO%><
<% if [ "$YADM_CLASS" = "wrongclass1" ]; then -%>
wrong class 1
<% fi -%>
<% if [ "$YADM_CLASS" = "{LOCAL_CLASS}" ]; then -%>
Included section for class = <%=$YADM_CLASS%> (<%=$YADM_CLASS%> repeated)
<% fi -%>
<% if [ "$YADM_CLASS" = "wrongclass2" ]; then -%>
wrong class 2
<% fi -%>
<% if [ "$YADM_OS" = "wrongos1" ]; then -%>
wrong os 1
<% fi -%>
<% if [ "$YADM_OS" = "{LOCAL_SYSTEM}" ]; then -%>
Included section for os = <%=$YADM_OS%> (<%=$YADM_OS%> repeated)
<% fi -%>
<% if [ "$YADM_OS" = "wrongos2" ]; then -%>
wrong os 2
<% fi -%>
<% if [ "$YADM_HOSTNAME" = "wronghost1" ]; then -%>
wrong host 1
<% fi -%>
<% if [ "$YADM_HOSTNAME" = "{LOCAL_HOST}" ]; then -%>
Included section for host = <%=$YADM_HOSTNAME%> (<%=$YADM_HOSTNAME%> again)
<% fi -%>
<% if [ "$YADM_HOSTNAME" = "wronghost2" ]; then -%>
wrong host 2
<% fi -%>
<% if [ "$YADM_USER" = "wronguser1" ]; then -%>
wrong user 1
<% fi -%>
<% if [ "$YADM_USER" = "{LOCAL_USER}" ]; then -%>
Included section for user = <%=$YADM_USER%> (<%=$YADM_USER%> repeated)
<% fi -%>
<% if [ "$YADM_USER" = "wronguser2" ]; then -%>
wrong user 2
<% fi -%>
<% if [ "$YADM_DISTRO" = "wrongdistro1" ]; then -%>
wrong distro 1
<% fi -%>
<% if [ "$YADM_DISTRO" = "{LOCAL_DISTRO}" ]; then -%>
Included section for distro = <%=$YADM_DISTRO%> (<%=$YADM_DISTRO%> again)
<% fi -%>
<% if [ "$YADM_DISTRO" = "wrongdistro2" ]; then -%>
wrong distro 2
<% fi -%>
end of template
'''
EXPECTED = f'''
start of template
esh class = >{LOCAL_CLASS}<
esh os = >{LOCAL_SYSTEM}<
esh host = >{LOCAL_HOST}<
esh user = >{LOCAL_USER}<
esh distro = >{LOCAL_DISTRO}<
Included section for class = {LOCAL_CLASS} ({LOCAL_CLASS} repeated)
Included section for os = {LOCAL_SYSTEM} ({LOCAL_SYSTEM} repeated)
Included section for host = {LOCAL_HOST} ({LOCAL_HOST} again)
Included section for user = {LOCAL_USER} ({LOCAL_USER} repeated)
Included section for distro = {LOCAL_DISTRO} ({LOCAL_DISTRO} again)
end of template
'''
def test_template_esh(runner, yadm, tmpdir):
"""Test processing by esh"""
input_file = tmpdir.join('input')
input_file.write(TEMPLATE, ensure=True)
output_file = tmpdir.join('output')
script = f"""
YADM_TEST=1 source {yadm}
local_class="{LOCAL_CLASS}"
local_system="{LOCAL_SYSTEM}"
local_host="{LOCAL_HOST}"
local_user="{LOCAL_USER}"
local_distro="{LOCAL_DISTRO}"
template_esh "{input_file}" "{output_file}"
"""
run = runner(command=['bash'], inp=script)
assert run.success
assert run.err == ''
assert output_file.read().strip() == str(EXPECTED).strip()
def test_source(runner, yadm, tmpdir):
"""Test YADM_SOURCE"""
input_file = tmpdir.join('input')
input_file.write('<%= $YADM_SOURCE %>', ensure=True)
output_file = tmpdir.join('output')
script = f"""
YADM_TEST=1 source {yadm}
template_esh "{input_file}" "{output_file}"
"""
run = runner(command=['bash'], inp=script)
assert run.success
assert run.err == ''
assert output_file.read().strip() == str(input_file)

23
yadm
View File

@ -45,6 +45,7 @@ GIT_CRYPT_PROGRAM="git-crypt"
TRANSCRYPT_PROGRAM="transcrypt"
J2CLI_PROGRAM="j2"
ENVTPL_PROGRAM="envtpl"
ESH_PROGRAM="esh"
LSB_RELEASE_PROGRAM="lsb_release"
OS_RELEASE="/etc/os-release"
@ -299,6 +300,8 @@ function choose_template_cmd() {
if [ "$kind" = "default" ] || [ "$kind" = "" ] && awk_available; then
echo "template_default"
elif [ "$kind" = "esh" ] && esh_available; then
echo "template_esh"
elif [ "$kind" = "j2cli" ] || [ "$kind" = "j2" ] && j2cli_available; then
echo "template_j2cli"
elif [ "$kind" = "envtpl" ] || [ "$kind" = "j2" ] && envtpl_available; then
@ -407,6 +410,22 @@ function template_envtpl() {
[ -f "$temp_file" ] && mv -f "$temp_file" "$output"
}
function template_esh() {
input="$1"
output="$2"
temp_file="${output}.$$.$RANDOM"
"$ESH_PROGRAM" -o "$temp_file" "$input" \
YADM_CLASS="$local_class" \
YADM_OS="$local_system" \
YADM_HOSTNAME="$local_host" \
YADM_USER="$local_user" \
YADM_DISTRO="$local_distro" \
YADM_SOURCE="$input"
[ -f "$temp_file" ] && mv -f "$temp_file" "$output"
}
# ****** yadm Commands ******
function alt() {
@ -1936,6 +1955,10 @@ function envtpl_available() {
command -v "$ENVTPL_PROGRAM" &> /dev/null && return
return 1
}
function esh_available() {
command -v "$ESH_PROGRAM" &> /dev/null && return
return 1
}
function readlink_available() {
command -v "readlink" &> /dev/null && return
return 1

15
yadm.1
View File

@ -637,6 +637,9 @@ upon
which is available on most *nix systems. To use this processor,
specify the value of "default" or just leave the value off (e.g. "##template").
.TP
.B esh
To use the esh template processor, specify the value of "esh"
.TP
.B j2cli
To use the j2cli Jinja template processor, specify the value of "j2" or
"j2cli".
@ -654,7 +657,7 @@ to create or overwrite files.
During processing, the following variables are available in the template:
Default Jinja Description
Default Jinja & Esh Description
------------- ------------- --------------------------
yadm.class YADM_CLASS Locally defined yadm class
yadm.distro YADM_DISTRO lsb_release -si
@ -702,6 +705,16 @@ would look like:
config=dev-whatever
{% endif -%}
And an equivalent esh named
.I whatever##template.esh
would look like:
<% if [ "$YADM_USER" = "harvey" ]; then -%>
config=<%= $YADM_CLASS %>-<%= $YADM_OS %>
<% else -%>
config=dev-whatever
<% fi -%>
.SH ENCRYPTION
It can be useful to manage confidential files, like SSH or GPG keys, across

18
yadm.md
View File

@ -495,6 +495,15 @@
most *nix systems. To use this processor, specify the value of
"default" or just leave the value off (e.g. "##template").
esh
ESH is a super light template processor written in POSIX
compliant shell. With no other dependencies than awk. It should
therefore run on any system. It can be "installed" by simply
downloading the file. Also one of the great features of esh is
that you can execute shell commands from inside templates. This
can be verry usefull to use your own configuration variables
from inside templates, like this `<% yadm config my-config %>`
j2cli To use the j2cli Jinja template processor, specify the value of
"j2" or "j2cli".
@ -511,7 +520,7 @@
During processing, the following variables are available in the tem-
plate:
Default Jinja Description
Default Jinja & Esh Description
------------- ------------- --------------------------
yadm.class YADM_CLASS Locally defined yadm class
yadm.distro YADM_DISTRO lsb_release -si
@ -554,6 +563,13 @@
config=dev-whatever
{% endif -%}
And an equivalent esh namedwhatever##template.esh would look like:
<% if [ "$YADM_USER" = "harvey" ]; then -%>
config=<%= $YADM_CLASS %>-<%= $YADM_OS %>
<% else -%>
config=dev-whatever
<% fi -%>
## ENCRYPTION
It can be useful to manage confidential files, like SSH or GPG keys,