You may want to inform yourself about human rights in China.

On Sugar, a Sweeter Salt: Annexes

date: 2022-03-20
update: 2022-06-01

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.


Traditional Japanese confectionary food collon, or Wagashi 和菓子

Traditional Japanese confectionary food collon, or Wagashi 和菓子 by Lzen9216 through wikimedia.orgCC-BY-SA-4.0

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
}

In the series:


Comments

By email, at mathieu.bivert chez:

email