forked from wrenn/wrenn
v0.2.0 (#50)
Co-authored-by: Tasnim Kabir Sadik <tksadik@omukk.dev> Reviewed-on: wrenn/wrenn#50
This commit is contained in:
@ -1,32 +1,46 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# update-debug-rootfs.sh — Build envd and inject it (plus wrenn-init + tini) into the debug rootfs.
|
||||
# update-minimal-rootfs.sh — Rebuild envd and inject it (plus wrenn-init + tini)
|
||||
# into the system base rootfs images.
|
||||
#
|
||||
# This script:
|
||||
# 1. Builds a fresh envd static binary via make
|
||||
# 2. Mounts the rootfs image
|
||||
# 3. Copies envd, wrenn-init, and tini into the image
|
||||
# 4. Unmounts cleanly
|
||||
# 1. Builds a fresh envd static binary via make (once)
|
||||
# 2. For each system base rootfs (ubuntu/alpine/arch/fedora): mounts it,
|
||||
# copies envd + wrenn-init + tini in, and unmounts cleanly
|
||||
#
|
||||
# Usage:
|
||||
# bash scripts/update-debug-rootfs.sh [rootfs_path]
|
||||
# bash scripts/update-minimal-rootfs.sh [rootfs_path]
|
||||
#
|
||||
# Defaults to /var/lib/wrenn/images/minimal/rootfs.ext4
|
||||
# With no argument it updates all four system base rootfs images under
|
||||
# ${WRENN_DIR}/images/teams/<platform>/<id>/rootfs.ext4
|
||||
# With a path argument it updates only that single rootfs.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||
WRENN_DIR="${WRENN_DIR:-/var/lib/wrenn}"
|
||||
ROOTFS="${1:-${WRENN_DIR}/images/minimal/rootfs.ext4}"
|
||||
MOUNT_DIR="/tmp/wrenn-rootfs-update"
|
||||
|
||||
if [ ! -f "${ROOTFS}" ]; then
|
||||
echo "ERROR: Rootfs not found at ${ROOTFS}"
|
||||
exit 1
|
||||
# base36(all-zeros UUID) = platform team that owns every system base template.
|
||||
PLATFORM_TEAM_B36="0000000000000000000000000"
|
||||
|
||||
# System base template IDs (well-known reserved IDs 0..3). Single-digit IDs, so
|
||||
# the 25-char base36 string is just the zero-padded decimal.
|
||||
SYSTEM_TEMPLATE_IDS=(0 1 2 3)
|
||||
|
||||
# Resolve which rootfs images to update.
|
||||
ROOTFS_LIST=()
|
||||
if [ $# -ge 1 ]; then
|
||||
ROOTFS_LIST=("$1")
|
||||
else
|
||||
for tid in "${SYSTEM_TEMPLATE_IDS[@]}"; do
|
||||
tmpl_b36="$(printf '%025d' "${tid}")"
|
||||
ROOTFS_LIST+=("${WRENN_DIR}/images/teams/${PLATFORM_TEAM_B36}/${tmpl_b36}/rootfs.ext4")
|
||||
done
|
||||
fi
|
||||
|
||||
# Step 1: Build envd.
|
||||
# Step 1: Build envd (once).
|
||||
echo "==> Building envd..."
|
||||
cd "${PROJECT_ROOT}"
|
||||
make build-envd
|
||||
@ -42,64 +56,84 @@ if ! ldd "${ENVD_BIN}" | grep -q "statically linked"; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Step 2: Mount the rootfs.
|
||||
echo "==> Mounting rootfs at ${MOUNT_DIR}..."
|
||||
mkdir -p "${MOUNT_DIR}"
|
||||
sudo mount -o loop,rw "${ROOTFS}" "${MOUNT_DIR}"
|
||||
|
||||
cleanup() {
|
||||
echo "==> Unmounting rootfs..."
|
||||
sudo umount "${MOUNT_DIR}" 2>/dev/null || true
|
||||
rmdir "${MOUNT_DIR}" 2>/dev/null || true
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
# Step 3: Copy files into rootfs.
|
||||
echo "==> Installing envd..."
|
||||
sudo mkdir -p "${MOUNT_DIR}/usr/local/bin"
|
||||
sudo cp "${ENVD_BIN}" "${MOUNT_DIR}/usr/local/bin/envd"
|
||||
sudo chmod 755 "${MOUNT_DIR}/usr/local/bin/envd"
|
||||
|
||||
echo "==> Installing wrenn-init..."
|
||||
sudo cp "${PROJECT_ROOT}/images/wrenn-init.sh" "${MOUNT_DIR}/usr/local/bin/wrenn-init"
|
||||
sudo chmod 755 "${MOUNT_DIR}/usr/local/bin/wrenn-init"
|
||||
|
||||
echo "==> Installing tini..."
|
||||
TINI_BIN=""
|
||||
# 1. Already in the rootfs?
|
||||
for p in "${MOUNT_DIR}/usr/bin/tini" "${MOUNT_DIR}/sbin/tini" "${MOUNT_DIR}/usr/local/bin/tini"; do
|
||||
if [ -f "$p" ]; then TINI_BIN="$p"; break; fi
|
||||
done
|
||||
# 2. Available on the host?
|
||||
if [ -z "${TINI_BIN}" ]; then
|
||||
for p in /usr/bin/tini /usr/local/bin/tini /sbin/tini; do
|
||||
if [ -f "$p" ]; then TINI_BIN="$p"; break; fi
|
||||
# resolve_tini ROOTFS_MOUNT — echo a path to a tini binary suitable for the
|
||||
# mounted rootfs. Prefers one already in the image, then a static download.
|
||||
resolve_tini() {
|
||||
local mount_dir="$1" p tini_arch arch
|
||||
for p in "${mount_dir}/usr/bin/tini" "${mount_dir}/sbin/tini" "${mount_dir}/usr/local/bin/tini"; do
|
||||
if [ -f "$p" ]; then echo "$p"; return; fi
|
||||
done
|
||||
fi
|
||||
# 3. Download from GitHub releases.
|
||||
if [ -z "${TINI_BIN}" ]; then
|
||||
ARCH="$(uname -m)"
|
||||
case "${ARCH}" in
|
||||
x86_64) TINI_ARCH="amd64" ;;
|
||||
aarch64) TINI_ARCH="arm64" ;;
|
||||
*) echo "ERROR: Unsupported architecture: ${ARCH}"; exit 1 ;;
|
||||
arch="$(uname -m)"
|
||||
case "${arch}" in
|
||||
x86_64) tini_arch="amd64" ;;
|
||||
aarch64) tini_arch="arm64" ;;
|
||||
*) echo "ERROR: Unsupported architecture: ${arch}" >&2; exit 1 ;;
|
||||
esac
|
||||
TINI_VERSION="v0.19.0"
|
||||
TINI_URL="https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-${TINI_ARCH}"
|
||||
TINI_TMP="/tmp/tini-${TINI_ARCH}"
|
||||
echo " Downloading tini ${TINI_VERSION} (${TINI_ARCH})..."
|
||||
curl -fsSL "${TINI_URL}" -o "${TINI_TMP}"
|
||||
chmod +x "${TINI_TMP}"
|
||||
TINI_BIN="${TINI_TMP}"
|
||||
# Static tini runs under any libc (glibc or musl).
|
||||
local tmp="/tmp/tini-static-${tini_arch}"
|
||||
if [ ! -f "${tmp}" ]; then
|
||||
echo " Downloading tini v0.19.0 static (${tini_arch})..." >&2
|
||||
curl -fsSL "https://github.com/krallin/tini/releases/download/v0.19.0/tini-static-${tini_arch}" -o "${tmp}"
|
||||
chmod +x "${tmp}"
|
||||
fi
|
||||
echo "${tmp}"
|
||||
}
|
||||
|
||||
# inject_rootfs ROOTFS — mount, copy guest binaries in, unmount.
|
||||
inject_rootfs() {
|
||||
local rootfs="$1" tini_bin
|
||||
echo ""
|
||||
echo "==> Updating ${rootfs}"
|
||||
|
||||
mkdir -p "${MOUNT_DIR}"
|
||||
sudo mount -o loop,rw "${rootfs}" "${MOUNT_DIR}"
|
||||
|
||||
local mounted=1
|
||||
cleanup_mount() {
|
||||
if [ "${mounted}" = "1" ]; then
|
||||
sudo umount "${MOUNT_DIR}" 2>/dev/null || true
|
||||
rmdir "${MOUNT_DIR}" 2>/dev/null || true
|
||||
mounted=0
|
||||
fi
|
||||
}
|
||||
trap cleanup_mount RETURN
|
||||
|
||||
sudo mkdir -p "${MOUNT_DIR}/usr/local/bin"
|
||||
sudo cp "${ENVD_BIN}" "${MOUNT_DIR}/usr/local/bin/envd"
|
||||
sudo chmod 755 "${MOUNT_DIR}/usr/local/bin/envd"
|
||||
|
||||
sudo cp "${PROJECT_ROOT}/images/wrenn-init.sh" "${MOUNT_DIR}/usr/local/bin/wrenn-init"
|
||||
sudo chmod 755 "${MOUNT_DIR}/usr/local/bin/wrenn-init"
|
||||
|
||||
tini_bin="$(resolve_tini "${MOUNT_DIR}")"
|
||||
sudo mkdir -p "${MOUNT_DIR}/sbin"
|
||||
# On usr-merged distros (e.g. Fedora) /sbin -> /usr/bin, so a tini already at
|
||||
# /usr/bin/tini IS /sbin/tini — copying onto itself errors. Skip then.
|
||||
if [ "${tini_bin}" -ef "${MOUNT_DIR}/sbin/tini" ]; then
|
||||
echo " tini already at /sbin/tini (usr-merged); skipping copy"
|
||||
else
|
||||
sudo cp "${tini_bin}" "${MOUNT_DIR}/sbin/tini"
|
||||
fi
|
||||
sudo chmod 755 "${MOUNT_DIR}/sbin/tini"
|
||||
|
||||
ls -la "${MOUNT_DIR}/usr/local/bin/envd" "${MOUNT_DIR}/usr/local/bin/wrenn-init" "${MOUNT_DIR}/sbin/tini"
|
||||
cleanup_mount
|
||||
}
|
||||
|
||||
# Step 2: Update each rootfs that exists.
|
||||
UPDATED=0
|
||||
for rootfs in "${ROOTFS_LIST[@]}"; do
|
||||
if [ ! -f "${rootfs}" ]; then
|
||||
echo "==> Skipping (not found): ${rootfs}"
|
||||
continue
|
||||
fi
|
||||
inject_rootfs "${rootfs}"
|
||||
UPDATED=$((UPDATED + 1))
|
||||
done
|
||||
|
||||
echo ""
|
||||
if [ "${UPDATED}" -eq 0 ]; then
|
||||
echo "==> No rootfs images updated. Build them first with: make images"
|
||||
exit 1
|
||||
fi
|
||||
sudo mkdir -p "${MOUNT_DIR}/sbin"
|
||||
sudo cp "${TINI_BIN}" "${MOUNT_DIR}/sbin/tini"
|
||||
sudo chmod 755 "${MOUNT_DIR}/sbin/tini"
|
||||
|
||||
# Step 4: Verify.
|
||||
echo ""
|
||||
echo "==> Installed files:"
|
||||
ls -la "${MOUNT_DIR}/usr/local/bin/envd" "${MOUNT_DIR}/usr/local/bin/wrenn-init" "${MOUNT_DIR}/sbin/tini"
|
||||
|
||||
echo ""
|
||||
echo "==> Done. Rootfs updated: ${ROOTFS}"
|
||||
echo "==> Done. Updated ${UPDATED} rootfs image(s)."
|
||||
|
||||
Reference in New Issue
Block a user