| 1 |
|
| 2 |
|
| 3 |
|
| 4 |
|
| 5 |
|
| 6 |
|
| 7 |
|
| 8 |
|
| 9 |
|
| 10 |
|
| 11 |
|
| 12 |
|
| 13 |
|
| 14 |
|
| 15 |
|
| 16 |
|
| 17 |
|
| 18 |
|
| 19 |
|
| 20 |
|
| 21 |
|
| 22 |
|
| 23 |
set -euo pipefail |
| 24 |
|
| 25 |
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" |
| 26 |
IMAGE="localhost/alloy:local" |
| 27 |
BIB_IMAGE="quay.io/centos-bootc/bootc-image-builder:latest" |
| 28 |
DEF="$REPO_ROOT/build/alloy-0.0.yaml" |
| 29 |
OUTPUT="$REPO_ROOT/output" |
| 30 |
|
| 31 |
TYPE="iso" |
| 32 |
WRITE_DEV="" |
| 33 |
SKIP_BUILD=0 |
| 34 |
|
| 35 |
die() { printf 'error: %s\n' "$*" >&2; exit 1; } |
| 36 |
|
| 37 |
usage() { |
| 38 |
sed -n '2,20p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//' |
| 39 |
exit "${1:-0}" |
| 40 |
} |
| 41 |
|
| 42 |
while [ $# -gt 0 ]; do |
| 43 |
case "$1" in |
| 44 |
--type) TYPE="${2:?--type needs a value}"; shift 2 ;; |
| 45 |
--write) WRITE_DEV="${2:?--write needs a device path}"; shift 2 ;; |
| 46 |
--skip-build) SKIP_BUILD=1; shift ;; |
| 47 |
-h|--help) usage 0 ;; |
| 48 |
*) die "unknown argument: $1 (see --help)" ;; |
| 49 |
esac |
| 50 |
done |
| 51 |
|
| 52 |
command -v podman >/dev/null || die "podman not found" |
| 53 |
[ -f "$DEF" ] || die "missing distro def: $DEF" |
| 54 |
[ -f "$REPO_ROOT/Containerfile" ] || die "no Containerfile at $REPO_ROOT" |
| 55 |
|
| 56 |
|
| 57 |
if [ "$SKIP_BUILD" -eq 0 ]; then |
| 58 |
echo "==> Building $IMAGE (rootful)" |
| 59 |
sudo podman build -t "$IMAGE" "$REPO_ROOT" |
| 60 |
else |
| 61 |
echo "==> Skipping image build; reusing $IMAGE" |
| 62 |
sudo podman image exists "$IMAGE" || die "$IMAGE not in the root store; drop --skip-build" |
| 63 |
fi |
| 64 |
|
| 65 |
|
| 66 |
sudo podman image exists "$BIB_IMAGE" || { |
| 67 |
echo "==> Pulling $BIB_IMAGE" |
| 68 |
sudo podman pull "$BIB_IMAGE" |
| 69 |
} |
| 70 |
|
| 71 |
|
| 72 |
|
| 73 |
echo "==> Building --type $TYPE into $OUTPUT" |
| 74 |
mkdir -p "$OUTPUT" |
| 75 |
sudo rm -rf "${OUTPUT:?}/"* 2>/dev/null || true |
| 76 |
sudo podman run --rm --privileged \ |
| 77 |
--security-opt label=type:unconfined_t \ |
| 78 |
-v /var/lib/containers/storage:/var/lib/containers/storage \ |
| 79 |
-v "$OUTPUT":/output \ |
| 80 |
-v "$DEF":/usr/share/bootc-image-builder/defs/alloy-0.0.yaml:ro \ |
| 81 |
"$BIB_IMAGE" \ |
| 82 |
--type "$TYPE" \ |
| 83 |
--log-level info \ |
| 84 |
"$IMAGE" |
| 85 |
|
| 86 |
|
| 87 |
case "$TYPE" in |
| 88 |
iso) ARTIFACT="$OUTPUT/bootiso/install.iso" ;; |
| 89 |
raw) ARTIFACT="$OUTPUT/image/disk.raw" ;; |
| 90 |
qcow2) ARTIFACT="$OUTPUT/qcow2/disk.qcow2" ;; |
| 91 |
*) ARTIFACT="$(sudo find "$OUTPUT" -type f ! -name '*.json' | head -1)" ;; |
| 92 |
esac |
| 93 |
[ -n "$ARTIFACT" ] && sudo test -f "$ARTIFACT" || die "expected artifact not found for type $TYPE" |
| 94 |
echo "==> Built: $ARTIFACT ($(sudo du -h "$ARTIFACT" | cut -f1))" |
| 95 |
|
| 96 |
|
| 97 |
if [ -n "$WRITE_DEV" ]; then |
| 98 |
[ -b "$WRITE_DEV" ] || die "$WRITE_DEV is not a block device" |
| 99 |
|
| 100 |
if lsblk -nro MOUNTPOINT "$WRITE_DEV" | grep -qE '^/$|^/boot'; then |
| 101 |
die "$WRITE_DEV has a system mountpoint; refusing to write" |
| 102 |
fi |
| 103 |
echo |
| 104 |
lsblk -o NAME,SIZE,TYPE,MOUNTPOINT,MODEL,SERIAL,TRAN "$WRITE_DEV" |
| 105 |
echo |
| 106 |
printf 'This ERASES all data on %s. Type the device path to confirm: ' "$WRITE_DEV" |
| 107 |
read -r reply |
| 108 |
[ "$reply" = "$WRITE_DEV" ] || die "confirmation did not match; not writing" |
| 109 |
echo "==> Writing $ARTIFACT to $WRITE_DEV" |
| 110 |
sudo dd if="$ARTIFACT" of="$WRITE_DEV" bs=4M oflag=direct conv=fsync status=progress |
| 111 |
sync |
| 112 |
echo "==> Done. $WRITE_DEV is now a bootable Alloy $TYPE." |
| 113 |
else |
| 114 |
echo "==> To write it to a USB stick:" |
| 115 |
echo " sudo dd if=$ARTIFACT of=/dev/sdX bs=4M oflag=direct conv=fsync status=progress" |
| 116 |
echo " (or re-run with --write /dev/sdX to rebuild and write in one step)" |
| 117 |
fi |
| 118 |
|