Skip to content

Commit

Permalink
Merge pull request #64 from PowerDNS/templates-nested-if
Browse files Browse the repository at this point in the history
Templates: support nested @if statements
  • Loading branch information
wojas authored May 11, 2023
2 parents 61c60a6 + 215db57 commit 169502b
Show file tree
Hide file tree
Showing 9 changed files with 219 additions and 31 deletions.
12 changes: 8 additions & 4 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ name: 'Run tests'
on:
push:
pull_request:
schedule:
- cron: '0 7 * * *'
# Disabled, because Github appears to disable the whole workflow if you have a schedule
# and no updates for 60 days...
# schedule:
#- cron: '0 7 * * *'

jobs:
tests:
Expand All @@ -20,6 +22,8 @@ jobs:
with:
fetch-depth: 5
submodules: recursive
- run: ./test-templating.sh
working-directory: ./templating
- run: ./tests/test_versioning.sh
working-directory: .
- run: ./prepare.sh
Expand All @@ -34,6 +38,6 @@ jobs:
- run: ./builder/build.sh -c -B MYCOOLARG=iLikeTests centos-7
# - Third one is very fast due to the Docker layer cache
- run: ./builder/build.sh -c -B MYCOOLARG=iLikeTests centos-7
# Do a reproducible centos-8 build (does not work for centos-7)
- run: ../tests/test-centos-8-reproducible.sh
# Do a reproducible rocky-8 build (does not work for centos-7)
- run: ../tests/test-rocky-8-reproducible.sh

Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@

# This defines the distribution base layer
# Put only the bare minimum of common commands here, without dev tools
FROM centos:8 as dist-base
FROM rockylinux:8 as dist-base
ARG BUILDER_CACHE_BUSTER=
RUN yum install -y epel-release
#RUN dnf install -y epel-release
# Python 3.4+ is needed for the builder helpers
RUN yum install -y /usr/bin/python3
RUN yum install -y dnf-plugins-core
RUN yum config-manager --set-enabled powertools
RUN dnf install -y /usr/bin/python3
RUN dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
RUN dnf install -y dnf-plugins-core
RUN dnf config-manager --set-enabled powertools

# Do the actual rpm build
@INCLUDE Dockerfile.rpmbuild
Expand Down
56 changes: 39 additions & 17 deletions templating/templating.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ if [ "$1" = "" ]; then
echo '@EXEC uname -a'
echo '@EXEC [ "$foo" = "bar" ] && include bar.txt'
echo '@IF [ "$foo" = "bar" ]'
echo 'This line is only printed if $foo = "bar" (cannot be nested)'
echo 'This line is only printed if $foo = "bar"'
echo '@ENDIF'
echo 'Other lines are printed unchanged.'
echo
echo "Environment variables:"
echo " tmpl_debug: If set, markers are printed around included files"
echo " tmpl_comment: Characters to use to start the marker comments (default: #)"
echo " tmpl_prefix: Characters to start processing directives (default: @)"
echo " tmpl_prefix: Regexp to match processing directive prefixes (default: @)"
exit 1
fi

Expand All @@ -28,41 +28,63 @@ tmpl_prefix=${tmpl_prefix:-@}

include() {
[ "$tmpl_debug" != "" ] && echo "$tmpl_comment $1"
local skip
# Current level of @IF we are in
local iflevel=0
# Set to the @IF level that disabled the current block, if any
local ifdisablelevel=0
local line
local condition
( cat "$1" && echo ) | while IFS= read -r line; do
if [[ $line = ${tmpl_prefix}ENDIF* ]]; then
skip=

if [[ $line =~ ^${tmpl_prefix}\ *IF\ (.*) ]]; then
[ "$tmpl_debug" != "" ] && echo "$tmpl_comment $line"
iflevel=$((iflevel+1))
if ! [ $ifdisablelevel -gt 0 ]; then
# Only if not already in a disabled IF statement
condition="${BASH_REMATCH[1]}"
if ! eval "$condition" ; then
# Disabled at the current IF level
ifdisablelevel=$iflevel
fi
fi

elif [[ $line =~ ^${tmpl_prefix}\ *ENDIF ]]; then
[ "$tmpl_debug" != "" ] && echo "$tmpl_comment $line"
if [ $iflevel = 0 ] ; then
echo "ERROR: @ENDIF without matching @IF in file $1" > /dev/stderr
exit 30
fi
iflevel=$((iflevel-1))
if [ $ifdisablelevel -gt $iflevel ]; then
# We left the IF block level that was disabled
ifdisablelevel=0
fi

elif [ ! -z "$skip" ]; then
elif [ $ifdisablelevel -gt 0 ]; then
# nothing, in IF that evaluated to false
[ "$tmpl_debug" != "" ] && echo "$tmpl_comment $line"


elif [[ $line = ${tmpl_prefix}INCLUDE\ * ]]; then
include=${line#* }
elif [[ $line =~ ^${tmpl_prefix}\ *INCLUDE\ +([^ ]*) ]]; then
include="${BASH_REMATCH[1]}"
include $include

elif [[ $line = ${tmpl_prefix}EVAL\ * ]]; then
line=${line#* }
elif [[ $line =~ ^${tmpl_prefix}\ *EVAL\ (.*) ]]; then
line="${BASH_REMATCH[1]}"
eval echo "\"$line\""

elif [[ $line = ${tmpl_prefix}EXEC\ * ]]; then
line=${line#* }
elif [[ $line =~ ^${tmpl_prefix}\ *EXEC\ (.*) ]]; then
line="${BASH_REMATCH[1]}"
eval "$line"

elif [[ $line = ${tmpl_prefix}IF\ * ]]; then
condition=${line#* }
[ "$tmpl_debug" != "" ] && echo "$tmpl_comment $line"
eval "$condition" || skip=1

else
echo "$line"
fi

done
[ "$tmpl_debug" != "" ] && echo "$tmpl_comment /$1"
}

include "$1"

exit 0
14 changes: 14 additions & 0 deletions templating/test-templating.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/usr/bin/env bash

set -e

cd testdata

if ! diff -u test-expected.txt <(../templating.sh test-template.txt) ; then
echo
echo "FAILED"
exit 1
fi

echo "PASSED"

51 changes: 51 additions & 0 deletions templating/testdata/test-expected.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
Lines can start with @INCLUDE, @EVAL or @EXEC for special processing, they
have no effect when not at the start of a line.


Direct @INCLUDE:
[Include file 1 start]
value of FOO in include is also 123
[Include file 1 end]


The value of FOO is 123

Empty @EXEC:
@EXEC

Conditional include in @EXEC:
[Second include start]
Hello world!
[Second include end]


This line is only printed if $FOO = "123", which is the case.
Nested IF that is true.
In between IFs.
Last line of first IF.

Triple nested IF that is true.
Also true.
Second level.
First level.


true1
true1

true1
true2
true2
true1

# Test @IF with extra indenting after the @

true1
true2
true2
Other directives also get indenting
true1


Other lines are printed unchanged.

3 changes: 3 additions & 0 deletions templating/testdata/test-template-include1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[Include file 1 start]
@EVAL value of FOO in include is also $FOO
[Include file 1 end]
3 changes: 3 additions & 0 deletions templating/testdata/test-template-include2.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[Second include start]
@EXEC echo "Hello world!"
[Second include end]
90 changes: 90 additions & 0 deletions templating/testdata/test-template.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
Lines can start with @INCLUDE, @EVAL or @EXEC for special processing, they
have no effect when not at the start of a line.

@EXEC FOO=123

Direct @INCLUDE:
@INCLUDE test-template-include1.txt

@EVAL The value of FOO is $FOO

Empty @EXEC:
@EXEC

Conditional include in @EXEC:
@EXEC [ "$FOO" = "123" ] && include test-template-include2.txt

@IF [ "$FOO" = "123" ]
This line is only printed if $FOO = "123", which is the case.
@IF true
Nested IF that is true.
@ENDIF
In between IFs.
@IF [ "$FOO" = "wrong" ]
THIS WILL NEVER BE PRINTED.
@ENDIF
Last line of first IF.
@ENDIF

@IF true
@IF true
@IF true
Triple nested IF that is true.
@ENDIF
@IF true
Also true.
@ENDIF
Second level.
@ENDIF
First level.
@ENDIF

@IF false
@IF true
@IF true
Triple nested IF that is FALSE.
@ENDIF
@ENDIF
@ENDIF

@IF true
true1
@IF false
false2
@IF true
Triple nested IF that is FALSE.
@ENDIF
false2 MUST NOT APPEAR, BUG!
@ENDIF
true1
@ENDIF

@IF true
true1
@IF true
true2
@IF false
Triple nested IF that is FALSE.
@ENDIF
true2
@ENDIF
true1
@ENDIF

# Test @IF with extra indenting after the @

@IF true
true1
@ IF true
true2
@ IF false
Triple nested IF that is FALSE.
@ ENDIF
true2
@ EXEC echo "Other directives also get indenting"
@ ENDIF
true1
@ENDIF


Other lines are printed unchanged.
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
#!/bin/sh
# Test if centos-8 RPM builds are reproducible
# Test if rocky-8 RPM builds are reproducible
# Must be run from demo dir

set -ex

# First build
./builder/build.sh -B MYCOOLARG=iLikeTests centos-8
./builder/build.sh -B MYCOOLARG=iLikeTests rocky-8

# Record hashes
sha256sum \
builder/tmp/latest/centos-8/dist/noarch/*.rpm \
builder/tmp/latest/rocky-8/dist/noarch/*.rpm \
builder/tmp/latest/sdist/*.tar.gz \
> /tmp/sha256sum.txt

# Second build after cleaning and adding a file to invalidate the build context
rm -rf ./builder/tmp/latest/centos-8
rm -rf ./builder/tmp/latest/rocky-8
rm -rf ./builder/tmp/latest/sdist
./builder/build.sh -B MYCOOLARG=iLikeTests -b build-again centos-8
./builder/build.sh -B MYCOOLARG=iLikeTests -b build-again rocky-8

# Check hashes, should be identical
sha256sum -c /tmp/sha256sum.txt
Expand Down

0 comments on commit 169502b

Please sign in to comment.