#!/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 } # 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