coreos-home-server/host/base/service/coreos-home-server-update

95 lines
3.7 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# Hook for updating local configuration on each pull. This will automatically put files in their
# right places, but will not enable or start any services automatically; this is left to the user.
#
# Move this to '.git/hooks/post-merge' to have to run automatically after every 'git pull' operation.
# The script assumes write access to host directories, and a CoreOS host. Don't run on other systems!
set -euo pipefail
shopt -s globstar
# Global configuration variables.
TEMP_CONFIG_PATH="$(git -C "$(dirname "$0")" rev-parse --show-toplevel)"
HOST_CONFIG_PATH="/etc/coreos-home-server"
SYSTEMD_CONFIG_PATH="/etc/systemd/system"
# Synchronize CoreOS home-server configuration for specific path.
function sync-coreos-config() {
local hostdir="$1"
local dirname="$(basename "$hostdir")"
# Check if any remote configuration exists for the name given.
if ! compgen -G "$TEMP_CONFIG_PATH"/*/"$dirname" > /dev/null; then
printf "configuration not found, skipping.\n"
return
fi
# Collect remote configuration files across base directories.
for tmpdir in "$TEMP_CONFIG_PATH"/*/"$dirname"; do
# Update timestamp for temporary file to match last commit time, in order to ensure correct partial updates.
for f in "$tmpdir/"**; do
# Skip directories, as updating their commit times will have all files within be synchronized.
if test -d "$f"; then
continue
fi
touch -t "$(cd "$tmpdir" && git log -n 1 --pretty=format:%cd --date=format-local:%Y%m%d%H%M.%S --date-order -- "$f")" -- "$f"
done
# Link source files into temporary destination directory.
mkdir --parents "$TEMP_CONFIG_PATH/.tmp/$dirname"
cp --archive --force --target-directory "$TEMP_CONFIG_PATH/.tmp/$dirname" "$tmpdir"/.
done
# Remove files that only exist in local configuration.
for f in $(comm -23 <(cd "$hostdir"; find . | sort) <(cd "$TEMP_CONFIG_PATH/.tmp/$dirname"; find . | sort)); do
# Don't delete environment files, as these are required for active services.
if test "$(basename --suffix=.env "$f")" != "$(basename "$f")"; then
continue
fi
rm --verbose --recursive --force "$(realpath --quiet "$hostdir/$f")"
done
# Copy files from temporary directory to host configuration directory.
(cd "$TEMP_CONFIG_PATH/.tmp/$dirname" && cp --verbose --recursive --update --target-directory "$hostdir" -- *)
printf "done.\n"
}
# Synchronize systemd service files from CoreOS home-server configuration.
function sync-systemd-services() {
local buffer="" tmp
# Copy service files if newer than destination.
for src in "$HOST_CONFIG_PATH"/*/systemd/*; do
tmp="$(cp --verbose --recursive --update --target-directory "$SYSTEMD_CONFIG_PATH" "$src")"
if test -n "$tmp"; then buffer="${buffer}"$'\n'"${tmp}"; fi
done
printf "%s\ndone.\n" "$buffer"
if test -n "$buffer"; then return 0; else return 1; fi
}
# Entrypoint for script. Process all services present in host configuration against remote state.
function main() {
# Synchronize all existing CoreOS home-server configuration.
for hostdir in "$HOST_CONFIG_PATH"/*; do
if test ! -d "$hostdir"; then
continue
fi
printf "Synchronizing host configuration for '%s'... " "$hostdir"
sync-coreos-config "$hostdir"
done
# Synchronize systemd services from local CoreOS home-server configuration.
printf "Synchronizing systemd service files... "
if sync-systemd-services; then
printf "Reloading systemd daemon after service updates...\n"
systemctl daemon-reload
fi
}
main "$@"