Add real runtime materialization pipeline and bundle artifacts

This commit is contained in:
Thales Maciel 2026-03-06 19:26:29 -03:00
parent cbf212bb7b
commit c43c718c83
32 changed files with 1456 additions and 27 deletions

View file

@ -0,0 +1,97 @@
#!/usr/bin/env bash
set -euo pipefail
builder_image=""
debian_release=""
debian_snapshot=""
packages_file=""
guest_agent=""
guest_init=""
agent_service=""
workdir=""
output=""
while [[ $# -gt 0 ]]; do
case "$1" in
--builder-image) builder_image="$2"; shift 2 ;;
--debian-release) debian_release="$2"; shift 2 ;;
--debian-snapshot) debian_snapshot="$2"; shift 2 ;;
--packages-file) packages_file="$2"; shift 2 ;;
--guest-agent) guest_agent="$2"; shift 2 ;;
--guest-init) guest_init="$2"; shift 2 ;;
--agent-service) agent_service="$2"; shift 2 ;;
--workdir) workdir="$2"; shift 2 ;;
--output) output="$2"; shift 2 ;;
*) echo "unknown arg: $1" >&2; exit 1 ;;
esac
done
: "${builder_image:?missing --builder-image}"
: "${debian_release:?missing --debian-release}"
: "${debian_snapshot:?missing --debian-snapshot}"
: "${packages_file:?missing --packages-file}"
: "${guest_agent:?missing --guest-agent}"
: "${guest_init:?missing --guest-init}"
: "${agent_service:?missing --agent-service}"
: "${workdir:?missing --workdir}"
: "${output:?missing --output}"
rm -rf "$workdir"
mkdir -p "$workdir/in" "$workdir/out" "$(dirname "$output")"
workdir="$(cd "$workdir" && pwd)"
output_dir="$(cd "$(dirname "$output")" && pwd)"
output="$output_dir/$(basename "$output")"
cp "$packages_file" "$workdir/in/packages.txt"
cp "$guest_agent" "$workdir/in/pyro_guest_agent.py"
cp "$guest_init" "$workdir/in/pyro-init"
cp "$agent_service" "$workdir/in/pyro-guest-agent.service"
container_script="$workdir/build-rootfs-container.sh"
cat > "$container_script" <<'SCRIPT'
#!/usr/bin/env bash
set -euo pipefail
export DEBIAN_FRONTEND=noninteractive
apt-get update
apt-get install -y --no-install-recommends ca-certificates debootstrap e2fsprogs systemd-container
mirror="http://snapshot.debian.org/archive/debian/${DEBIAN_SNAPSHOT}/"
packages_csv="$(paste -sd, /work/in/packages.txt)"
rootfs_dir="/work/rootfs"
rm -rf "$rootfs_dir"
mkdir -p "$rootfs_dir"
debootstrap \
--arch=amd64 \
--variant=minbase \
--include="$packages_csv" \
--no-check-gpg \
"$DEBIAN_RELEASE" \
"$rootfs_dir" \
"$mirror"
cat > "$rootfs_dir/etc/apt/sources.list" <<APT
deb [check-valid-until=no] http://snapshot.debian.org/archive/debian/${DEBIAN_SNAPSHOT}/ ${DEBIAN_RELEASE} main
deb [check-valid-until=no] http://snapshot.debian.org/archive/debian-security/${DEBIAN_SNAPSHOT}/ ${DEBIAN_RELEASE}-security main
APT
mkdir -p "$rootfs_dir/opt/pyro/bin" "$rootfs_dir/etc/systemd/system/multi-user.target.wants"
install -m 0755 /work/in/pyro_guest_agent.py "$rootfs_dir/opt/pyro/bin/pyro_guest_agent.py"
install -m 0755 /work/in/pyro-init "$rootfs_dir/opt/pyro/bin/pyro-init"
install -m 0644 /work/in/pyro-guest-agent.service "$rootfs_dir/etc/systemd/system/pyro-guest-agent.service"
ln -sf /etc/systemd/system/pyro-guest-agent.service \
"$rootfs_dir/etc/systemd/system/multi-user.target.wants/pyro-guest-agent.service"
ln -sf /opt/pyro/bin/pyro-init "$rootfs_dir/sbin/init"
printf '127.0.0.1 localhost\n' > "$rootfs_dir/etc/hosts"
truncate -s 2G /work/out/rootfs.ext4
mkfs.ext4 -F -d "$rootfs_dir" /work/out/rootfs.ext4 >/dev/null
SCRIPT
chmod +x "$container_script"
docker run --rm \
-e DEBIAN_RELEASE="$debian_release" \
-e DEBIAN_SNAPSHOT="$debian_snapshot" \
-v "$workdir:/work" \
"$builder_image" \
/work/build-rootfs-container.sh
cp "$workdir/out/rootfs.ext4" "$output"

View file

@ -0,0 +1,64 @@
#!/usr/bin/env bash
set -euo pipefail
builder_image=""
linux_version=""
source_url=""
config_url=""
workdir=""
output=""
while [[ $# -gt 0 ]]; do
case "$1" in
--builder-image) builder_image="$2"; shift 2 ;;
--linux-version) linux_version="$2"; shift 2 ;;
--source-url) source_url="$2"; shift 2 ;;
--config-url) config_url="$2"; shift 2 ;;
--workdir) workdir="$2"; shift 2 ;;
--output) output="$2"; shift 2 ;;
*) echo "unknown arg: $1" >&2; exit 1 ;;
esac
done
: "${builder_image:?missing --builder-image}"
: "${linux_version:?missing --linux-version}"
: "${source_url:?missing --source-url}"
: "${config_url:?missing --config-url}"
: "${workdir:?missing --workdir}"
: "${output:?missing --output}"
mkdir -p "$workdir" "$(dirname "$output")"
workdir="$(cd "$workdir" && pwd)"
output_dir="$(cd "$(dirname "$output")" && pwd)"
output="$output_dir/$(basename "$output")"
container_script="$workdir/build-kernel-container.sh"
cat > "$container_script" <<'SCRIPT'
#!/usr/bin/env bash
set -euo pipefail
export DEBIAN_FRONTEND=noninteractive
apt-get update
apt-get install -y --no-install-recommends \
bc bison build-essential ca-certificates curl flex libelf-dev libssl-dev pahole python3 rsync xz-utils
cd /work
curl -fsSL "$KERNEL_SOURCE_URL" -o linux.tar.xz
curl -fsSL "$KERNEL_CONFIG_URL" -o kernel.config
rm -rf linux-src out
mkdir -p linux-src out
tar -xf linux.tar.xz -C linux-src --strip-components=1
cd linux-src
cp /work/kernel.config .config
make olddefconfig
make -j"$(nproc)" vmlinux
cp vmlinux /work/out/vmlinux
SCRIPT
chmod +x "$container_script"
mkdir -p "$workdir/out"
docker run --rm \
-e KERNEL_SOURCE_URL="$source_url" \
-e KERNEL_CONFIG_URL="$config_url" \
-v "$workdir:/work" \
"$builder_image" \
/work/build-kernel-container.sh
cp "$workdir/out/vmlinux" "$output"

View file

@ -0,0 +1,12 @@
[Unit]
Description=Pyro guest exec agent
After=network-online.target
[Service]
Type=simple
ExecStart=/usr/bin/python3 /opt/pyro/bin/pyro_guest_agent.py
Restart=always
RestartSec=1
[Install]
WantedBy=multi-user.target

View file

@ -0,0 +1,56 @@
#!/bin/sh
set -eu
PATH=/usr/sbin:/usr/bin:/sbin:/bin
AGENT=/opt/pyro/bin/pyro_guest_agent.py
mount -t proc proc /proc || true
mount -t sysfs sysfs /sys || true
mount -t devtmpfs devtmpfs /dev || true
mkdir -p /run /tmp
hostname pyro-vm || true
cmdline="$(cat /proc/cmdline 2>/dev/null || true)"
get_arg() {
key="$1"
for token in $cmdline; do
case "$token" in
"$key"=*)
printf '%s' "${token#*=}"
return 0
;;
esac
done
return 1
}
ip link set lo up || true
if ip link show eth0 >/dev/null 2>&1; then
ip link set eth0 up || true
guest_ip="$(get_arg pyro.guest_ip || true)"
gateway_ip="$(get_arg pyro.gateway_ip || true)"
netmask="$(get_arg pyro.netmask || true)"
dns_csv="$(get_arg pyro.dns || true)"
if [ -n "$guest_ip" ] && [ -n "$netmask" ]; then
ip addr add "$guest_ip/$netmask" dev eth0 || true
fi
if [ -n "$gateway_ip" ]; then
ip route add default via "$gateway_ip" dev eth0 || true
fi
if [ -n "$dns_csv" ]; then
: > /etc/resolv.conf
old_ifs="$IFS"
IFS=,
for dns in $dns_csv; do
printf 'nameserver %s\n' "$dns" >> /etc/resolv.conf
done
IFS="$old_ifs"
fi
fi
if [ -f "$AGENT" ]; then
python3 "$AGENT" &
fi
exec /bin/sh -lc 'trap : TERM INT; while true; do sleep 3600; done'