The complete code is available on github; the OpenBSD setup scripts, hooks, templates & all are available in a distinct repository. We include below a few excerpts to give an idea on how some features actually are implemented.
Automatic commands
The following can be used in a main pre-hook to create linear combinaison of existing commands; see also on github
#!/bin/sh
set -e
# .auto scripts management, as linear combinations of other
# scripts.
# Create a single automatic script/hook
#
# Input:
# /dev/stdin : files to include in the script/hook, one fn per line
# $1 : directory where to create script/hook
# $2 : script|hook's basename
# Output:
mkauto1() {
cat <<'EOF' > $1/$2
#!/bin/sh
set -e
if echo "$DEBUG" | grep -q x; then set -x; fi
EOF
while read x; do
if [ -f "$1/$x" ]; then echo $x '$@' >> $1/$2; fi
done
}
# Create automatic script and related hooks.
#
# Input:
# $1 : .auto file
# $2 : bin/ directory where to create auto script/hooks
# Output:
# Automatic script and related hooks created in $2
mkauto() {
n=`basename $1 .auto`
sed 's/^/hook-pre-/' $1 | mkauto1 $2 hook-pre-$n
cat $1 | mkauto1 $2 $n
sed 's/^/hook-post-/' $1 | mkauto1 $2 hook-post-$n
chmod +x $2/hook-pre-$n $2/$n $2/hook-post-$n
}
# Create all automatic scripts if any.
#
# Input:
# $1 : server raw directory
# $2 : server ready directory
# Output:
# Automatic scripts/hooks created in $2/bin
mkautos() {
for x in $1/*.auto; do
# No match
if [ ! -f "$x" ]; then break; fi
mkauto $x $2/bin
done
}
# $1 is (unused) server alias
mkautos $2 $3
Code/data sharing
The following can be used in a main pre-hook to share files
between two raw/
directories addressing different machines
with similar setup; see also on github:
#!/bin/sh
set -e
# NOTE: imported bin/ files will override those already existing in
# the $raw/ directory.
# We'll be using set(1) shortly.
raw=$2
ready=$3
# No imports file => no-op
if [ ! -e $raw/imports ]; then exit 0; fi
# Skip comments, empty lines
grep -vE '^[ \t]*#|^[ \t]*$' $raw/imports | while read x; do
# Split fields
set -- $x
# Ensure destination's dirname exists
if echo "$2" | grep -q '/$'; then
mkdir -p $ready/$2
else
mkdir -p `dirname $ready/$2`
fi
# Actually import
eval "cp -p $1 $ready/$2"
done
Configuration, templating
Excerpts from sugar.lib:
...
# Load configuration files
#
# Input:
# $1 : directory containing the config.* and config files,
# typically a ready/ directory for hooks, thus after
# sugar.imports has pushed here some configs, or $SUGARD
# on remote locations, which is the default value.
# Output:
loadconfs() {
if [ -z "$1" ]; then set -- "$SUGARD"; fi
for x in $1/config.*; do
# globbing failure, mostly
if [ -r "$x" ]; then . $x; fi
done
if [ -r "$1/config" ]; then . "$1/config"; fi
}
# Process a template configuration file
# from the configuration variables defined
# in the config files.
#
# NOTE: %%VAR%% is substitued with $VAR's value,
# where $VAR is taken from the environment. config*
# files are loaded in the environment.
#
# NOTE: perhaps we should fork to avoid polluting the
# environment?
#
# Input:
# $1 : directory containing the config.* and config files,
# typically a ready/ directory, after sugar.imports has
# stored there imported configuration files.
# $2 : configuration file to process
# Output:
# $2 templatized with the value from $2/config*, on stdout
samurai() {
set -a; loadconfs $1; set +a
dbg=cat
if echo "$DEBUG" | grep -q 'd'; then
dbg="tee /dev/stderr"
logerr Processing $2...
fi
# Print stuff until we find a %%; look for a second %%;
# replace %%stuff%% by $stuff from ENVIRON. Loop.
awk '/%%/ { for (s = $0;;) {
# Look for opening %%
n = index(s, "%%")
if (n == 0) {
printf("%s\n", s);
break;
}
printf("%s", substr(s, 1, n-1))
# Skip %%
n += 2
s = substr(s, n)
# Look for second %%
n = index(s, "%%")
if (n == 0) {
printf("Failure: missing closing %% at %s\n", $0)
exit 1
}
printf("%s", ENVIRON[substr(s, 1, n-1)])
# Skip %%
n += 2
s = substr(s, n)
} next; } { print; } ' $2 | $dbg
}
Comments
By email, at mathieu.bivert chez: