95 lines
3.6 KiB
Bash
Executable File
95 lines
3.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
# Copyright (C) 2026 Bryan Joshua Pedini
|
|
|
|
# tests/docker/snapshot.sh - record the host's Docker image set BEFORE tests run,
|
|
# so tests/docker/cleanup.sh can restore it afterwards.
|
|
#
|
|
# Writes, next to this script:
|
|
# images-before.tsv repo:tag<TAB>image-id (docker images --no-trunc, sorted)
|
|
# image-ids-before.txt every image id, incl. untagged (docker images -a -q --no-trunc, sort -u)
|
|
#
|
|
# An existing snapshot is NEVER overwritten without --force: running `make test`
|
|
# twice must not "launder" images pulled by the first run into the baseline.
|
|
# Without --force an existing snapshot is kept and the script exits 0, so
|
|
# `make docker-snapshot` / `make test` can call it every time.
|
|
#
|
|
# usage: snapshot.sh [--force]
|
|
set -euo pipefail
|
|
|
|
prog=${0##*/}
|
|
here=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
|
|
tags_file=$here/images-before.tsv
|
|
ids_file=$here/image-ids-before.txt
|
|
|
|
usage() {
|
|
cat <<USAGE
|
|
usage: $prog [--force]
|
|
|
|
Record the current Docker image set to
|
|
$tags_file
|
|
$ids_file
|
|
|
|
An existing snapshot is kept unless --force is given. Only use --force when
|
|
the images currently on the host are exactly the ones you want to keep: every
|
|
image present at snapshot time is treated as pre-existing by cleanup.sh.
|
|
USAGE
|
|
}
|
|
|
|
die() {
|
|
printf '%s: error: %s\n' "$prog" "$*" >&2
|
|
exit 1
|
|
}
|
|
|
|
force=0
|
|
for arg in "$@"; do
|
|
case $arg in
|
|
--force) force=1 ;;
|
|
-h | --help) usage; exit 0 ;;
|
|
*) printf '%s: unknown argument: %s\n' "$prog" "$arg" >&2; usage >&2; exit 1 ;;
|
|
esac
|
|
done
|
|
|
|
if [[ -e $tags_file && -e $ids_file ]]; then
|
|
if ((!force)); then
|
|
printf '%s: snapshot already exists (taken %s), NOT overwriting it.\n' \
|
|
"$prog" "$(date -r "$tags_file" '+%Y-%m-%d %H:%M:%S %Z')" >&2
|
|
printf '%s: to re-baseline on purpose: %s --force\n' "$prog" "$0" >&2
|
|
exit 0
|
|
fi
|
|
elif [[ -e $tags_file || -e $ids_file ]]; then
|
|
((force)) || die "incomplete snapshot (only one of ${tags_file##*/}, ${ids_file##*/} exists); inspect it, then re-run with --force"
|
|
fi
|
|
|
|
docker info >/dev/null 2>&1 || die "cannot talk to the Docker daemon (is it running, are you in the docker group?)"
|
|
|
|
tmp_tags=$(mktemp "$tags_file.XXXXXX.tmp")
|
|
tmp_ids=$(mktemp "$ids_file.XXXXXX.tmp")
|
|
trap 'rm -f -- "$tmp_tags" "$tmp_ids"' EXIT
|
|
|
|
# Exactly the commands of the original manual snapshot (plain `sort`, so the
|
|
# order follows the caller's locale, byte-identical to running them by hand).
|
|
# Consumers must not depend on the order: cleanup.sh reads both files into maps.
|
|
docker images --no-trunc --format '{{.Repository}}:{{.Tag}}\t{{.ID}}' | sort >"$tmp_tags"
|
|
docker images -a -q --no-trunc | sort -u >"$tmp_ids"
|
|
|
|
if [[ -e $tags_file && -e $ids_file ]]; then
|
|
# --force over an existing snapshot: show what the baseline gains, so an
|
|
# accidental re-baseline after a test run is at least visible.
|
|
gained_tags=$(LC_ALL=C comm -13 <(LC_ALL=C sort "$tags_file") <(LC_ALL=C sort "$tmp_tags"))
|
|
gained_ids=$(LC_ALL=C comm -13 <(LC_ALL=C sort -u "$ids_file") <(LC_ALL=C sort -u "$tmp_ids"))
|
|
if [[ -n $gained_tags || -n $gained_ids ]]; then
|
|
printf '%s: WARNING: the new baseline adopts images that were not in the old one:\n' "$prog" >&2
|
|
if [[ -n $gained_tags ]]; then mapfile -t lines <<<"$gained_tags"; printf ' tag %s\n' "${lines[@]}" >&2; fi
|
|
if [[ -n $gained_ids ]]; then mapfile -t lines <<<"$gained_ids"; printf ' id %s\n' "${lines[@]}" >&2; fi
|
|
fi
|
|
fi
|
|
|
|
chmod 0644 "$tmp_tags" "$tmp_ids"
|
|
mv -f -- "$tmp_tags" "$tags_file"
|
|
mv -f -- "$tmp_ids" "$ids_file"
|
|
trap - EXIT
|
|
|
|
printf '%s: snapshot written: %d tags -> %s, %d ids -> %s\n' "$prog" \
|
|
"$(wc -l <"$tags_file")" "${tags_file#"$PWD"/}" "$(wc -l <"$ids_file")" "${ids_file#"$PWD"/}"
|