Move the default guest package list into a repo manifest and record a hash beside built rootfs images so run/make-rootfs can warn when the docker-ready image is stale. Switch the Firecracker launch path to a single sparse root overlay per VM instead of separate /home and /var disks, so many VMs can share the same base image while still installing packages under /var and working from /root. Keep older images bootable by masking stale home.mount and var.mount units at boot, and scrub those obsolete fstab entries when customize.sh rebuilds an image. Verified with bash -n on the updated scripts; no live VM boot was run in this environment.
115 lines
2.9 KiB
Bash
115 lines
2.9 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
BANGER_PACKAGES_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
BANGER_APT_PACKAGES_FILE="${BANGER_APT_PACKAGES_FILE:-$BANGER_PACKAGES_DIR/packages.apt}"
|
|
|
|
banger_packages_file() {
|
|
printf '%s' "$BANGER_APT_PACKAGES_FILE"
|
|
}
|
|
|
|
banger_packages_normalized_lines() {
|
|
local packages_file="${1:-$BANGER_APT_PACKAGES_FILE}"
|
|
|
|
[[ -f "$packages_file" ]] || return 1
|
|
awk '
|
|
{
|
|
sub(/\r$/, "")
|
|
sub(/[[:space:]]*#.*$/, "")
|
|
gsub(/^[[:space:]]+|[[:space:]]+$/, "")
|
|
if ($0 != "") print
|
|
}
|
|
' "$packages_file"
|
|
}
|
|
|
|
banger_packages_read_array() {
|
|
local -n out="$1"
|
|
local packages_file="${2:-$BANGER_APT_PACKAGES_FILE}"
|
|
|
|
mapfile -t out < <(banger_packages_normalized_lines "$packages_file")
|
|
(( ${#out[@]} > 0 ))
|
|
}
|
|
|
|
banger_packages_hash_stream() {
|
|
command -v sha256sum >/dev/null 2>&1 || return 1
|
|
sha256sum | awk '{print $1}'
|
|
}
|
|
|
|
banger_packages_manifest_hash() {
|
|
local packages_file="${1:-$BANGER_APT_PACKAGES_FILE}"
|
|
|
|
[[ -f "$packages_file" ]] || return 1
|
|
banger_packages_normalized_lines "$packages_file" | banger_packages_hash_stream
|
|
}
|
|
|
|
banger_rootfs_manifest_metadata_path() {
|
|
local rootfs_path="$1"
|
|
printf '%s.packages.sha256' "$rootfs_path"
|
|
}
|
|
|
|
banger_rootfs_manifest_recorded_hash() {
|
|
local rootfs_path="$1"
|
|
local metadata_file recorded_hash
|
|
|
|
metadata_file="$(banger_rootfs_manifest_metadata_path "$rootfs_path")"
|
|
[[ -f "$metadata_file" ]] || return 1
|
|
|
|
recorded_hash="$(head -n 1 "$metadata_file" | tr -d '[:space:]')"
|
|
[[ -n "$recorded_hash" ]] || return 1
|
|
printf '%s' "$recorded_hash"
|
|
}
|
|
|
|
banger_write_rootfs_manifest_metadata() {
|
|
local rootfs_path="$1"
|
|
local manifest_hash="$2"
|
|
local metadata_file
|
|
|
|
metadata_file="$(banger_rootfs_manifest_metadata_path "$rootfs_path")"
|
|
printf '%s\n' "$manifest_hash" > "$metadata_file"
|
|
}
|
|
|
|
banger_rootfs_manifest_status() {
|
|
local rootfs_path="$1"
|
|
local current_hash recorded_hash
|
|
|
|
if [[ ! -f "$rootfs_path" ]]; then
|
|
printf '%s' "missing-rootfs"
|
|
return 0
|
|
fi
|
|
|
|
if ! current_hash="$(banger_packages_manifest_hash)"; then
|
|
printf '%s' "unknown"
|
|
return 0
|
|
fi
|
|
|
|
if ! recorded_hash="$(banger_rootfs_manifest_recorded_hash "$rootfs_path")"; then
|
|
printf '%s' "missing-metadata"
|
|
return 0
|
|
fi
|
|
|
|
if [[ "$recorded_hash" == "$current_hash" ]]; then
|
|
printf '%s' "fresh"
|
|
else
|
|
printf '%s' "stale"
|
|
fi
|
|
}
|
|
|
|
banger_rootfs_manifest_warning() {
|
|
local rootfs_path="$1"
|
|
local status
|
|
|
|
status="$(banger_rootfs_manifest_status "$rootfs_path")"
|
|
case "$status" in
|
|
stale)
|
|
printf '%s was built with an older package manifest; rebuild it explicitly to pick up package changes' "$rootfs_path"
|
|
;;
|
|
missing-metadata)
|
|
printf '%s has no package manifest metadata; rebuild it explicitly to pick up package changes' "$rootfs_path"
|
|
;;
|
|
unknown)
|
|
printf 'unable to compare %s against %s; install sha256sum and verify the package manifest manually' "$rootfs_path" "$BANGER_APT_PACKAGES_FILE"
|
|
;;
|
|
*)
|
|
return 1
|
|
;;
|
|
esac
|
|
}
|