diff --git a/alpine/install-packages.sh b/alpine/install-packages.sh index d87444e..9038ab3 100755 --- a/alpine/install-packages.sh +++ b/alpine/install-packages.sh @@ -28,9 +28,6 @@ mv /etc/cni/net.d/10-crio-bridge.conflist.disabled \ sed -i "s/default_runtime = \"crun\"/\0\ncgroup_manager = \"cgroupfs\"/g" /etc/crio/crio.conf.d/10-crio.conf grep cgroup_manager /etc/crio/crio.conf.d/10-crio.conf || exit 1 -chmod +x /opt/scripts/* -chmod +x /etc/init.d/* - mkdir -p /var/run/crio mkdir -p /var/lib/containers/storage mkdir -p /var/lib/cni diff --git a/alpine/merge-rootfs.sh b/alpine/merge-rootfs.sh index 4dd0aae..3f992f1 100755 --- a/alpine/merge-rootfs.sh +++ b/alpine/merge-rootfs.sh @@ -75,21 +75,60 @@ check_template_vars() { [[ "$missing" -eq 0 ]] } +preserve_exec_bit() { + local old="$1" + local new="$2" + + if [[ -e "$old" && -x "$old" ]]; then + chmod +x "$new" + fi +} + +get_envsubst_vars() { + local rel="$1" + + case "$rel" in + bin/flash-emmc.sh.tmpl) + echo '${BUILD_TAG}' + ;; + *) + echo '' + ;; + esac +} + render_template() { local src="$1" local out="$2" + local allowed="${3:-}" mkdir -p "$(dirname "$out")" - check_template_vars "$src" - envsubst < "$src" > "$out" + + if [[ -n "$allowed" ]]; then + envsubst "$allowed" < "$src" > "$out" + else + check_template_vars "$src" + envsubst < "$src" > "$out" + fi + if [[ -x "$src" ]]; then + chmod +x "$out" + fi } replace_file() { local src="$1" local dst="$2" + local had_exec=0 + [[ -e "$dst" && -x "$dst" ]] && had_exec=1 + mkdir -p "$(dirname "$dst")" cp -a "$src" "$dst" + + if [[ "$had_exec" -eq 1 ]]; then + chmod +x "$dst" + fi + echo "Replaced file: $dst" } @@ -101,11 +140,19 @@ merge_or_copy_file() { mkdir -p "$(dirname "$dst")" # scripts: replace - if [[ "$rel" == opt/scripts/* ]]; then - cp -a "$src" "$dst" - echo "Replaced script: $dst" - return - fi + if [[ "$rel" == opt/scripts/* ]]; then + local had_exec=0 + [[ -e "$dst" && -x "$dst" ]] && had_exec=1 + + cp -a "$src" "$dst" + + if [[ "$had_exec" -eq 1 ]]; then + chmod +x "$dst" + fi + + echo "Replaced script: $dst" + return + fi # /etc: merge missing lines if [[ "$rel" == etc/* ]]; then @@ -177,12 +224,12 @@ find "$SRC_ROOT" -mindepth 1 | while IFS= read -r src_path; do mode="override" rel_for_target="${rel_for_target%.override}" - elif [[ "$rel_for_target" == *.tmpl ]]; then - rel_for_target="${rel_for_target%.tmpl}" - rendered="$TMP_DIR/$rel_for_target" - render_template "$src_path" "$rendered" - src_for_merge="$rendered" - fi + elif [[ "$rel_for_target" == *.tmpl ]]; then + rel_for_target="${rel_for_target%.tmpl}" + rendered="$TMP_DIR/$rel_for_target" + render_template "$src_path" "$rendered" "$(get_envsubst_vars "$rel_path")" + src_for_merge="$rendered" + fi dst_path="$DST_ROOT/$rel_for_target" diff --git a/alpine/rootfs-extra/etc/init.d/crio b/alpine/rootfs-extra/etc/init.d/crio index c0c49d3..901a50d 100755 --- a/alpine/rootfs-extra/etc/init.d/crio +++ b/alpine/rootfs-extra/etc/init.d/crio @@ -15,7 +15,7 @@ start_stop_daemon_args=" \ --stderr /var/log/${RC_SVCNAME}/${RC_SVCNAME}.log" depend() { - need net + need loopback localmount } checkconfig() { diff --git a/build.env b/build.env index ead4d6d..9f5bbb5 100644 --- a/build.env +++ b/build.env @@ -27,3 +27,6 @@ ALPINE_ARCH=aarch64 # Only applies to new installations ALPINE_HOSTNAME=monok8s-hostname + +# Upper case [A-Z]_ only, used for naming env vars +BUILD_TAG=MONOK8S diff --git a/docker/initramfs.Dockerfile b/docker/initramfs.Dockerfile index ff73516..db0cdc3 100644 --- a/docker/initramfs.Dockerfile +++ b/docker/initramfs.Dockerfile @@ -25,19 +25,18 @@ RUN make ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE} defconfig \ RUN make CROSS_COMPILE=${CROSS_COMPILE} -j"$(nproc)" RUN make CROSS_COMPILE=${CROSS_COMPILE} CONFIG_PREFIX=/out/initramfs install -WORKDIR /out/initramfs +WORKDIR /build -COPY initramfs/init init -RUN chmod +x init -RUN mkdir -p bin sbin etc proc sys dev lib mnt usr/bin usr/sbin +ARG BUILD_TAG -# Selective mods -RUN mkdir -p /out/selected-mods /out/kernel -COPY initramfs/selective-mods.sh / +COPY alpine/*.sh ./ +COPY initramfs/*.sh ./ COPY out/rootfs /out/rootfs -RUN /selective-mods.sh /out/rootfs/lib/modules/$(ls /out/rootfs/lib/modules/) ./lib/ +COPY initramfs/rootfs-extra ./rootfs-extra +COPY out/build-info ./rootfs-extra/etc/build-info -RUN find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../initramfs.cpio.gz +WORKDIR /out/initramfs +RUN /build/build-rootfs.sh FROM scratch COPY --from=build /out/initramfs.cpio.gz /initramfs.cpio.gz diff --git a/initramfs/build-rootfs.sh b/initramfs/build-rootfs.sh new file mode 100755 index 0000000..f044640 --- /dev/null +++ b/initramfs/build-rootfs.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -euo pipefail + +mkdir -p bin sbin etc proc sys dev lib mnt usr/bin usr/sbin + +/build/selective-mods.sh /out/rootfs/lib/modules/$(ls /out/rootfs/lib/modules/) ./ +/build/merge-rootfs.sh "/build/rootfs-extra" "./" + +find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../initramfs.cpio.gz diff --git a/initramfs/rootfs-extra/bin/flash-emmc.sh.tmpl b/initramfs/rootfs-extra/bin/flash-emmc.sh.tmpl new file mode 100755 index 0000000..af75fcf --- /dev/null +++ b/initramfs/rootfs-extra/bin/flash-emmc.sh.tmpl @@ -0,0 +1,67 @@ +#!/bin/sh +set -eu + +MNT=/mnt +USB_DEV=/dev/sda +EMMC_DEV=/dev/mmcblk0 +DEFAULT_GLOB="${MNT}/$${BUILD_TAG}_RELEASE_IMAGE" + +mkdir -p "$MNT" + +echo "[*] Mounting USB..." +mount "$USB_DEV" "$MNT" + +# Find a default image (first match) +DEFAULT_IMG="$(ls $DEFAULT_GLOB 2>/dev/null | head -n1 || true)" + +echo +if [ -n "$DEFAULT_IMG" ]; then + echo "Default image found:" + echo " $DEFAULT_IMG" +else + echo "No default image found under $DEFAULT_GLOB" +fi +echo + +# Prompt user +printf "Image Location (%s): " "${DEFAULT_IMG:-/mnt/...}" +read -r IMG + +# Use default if empty +if [ -z "$IMG" ]; then + IMG="$DEFAULT_IMG" +fi + +# Validate +if [ -z "$IMG" ] || [ ! -f "$IMG" ]; then + echo "Invalid image: $IMG" + umount "$MNT" || true + exit 1 +fi + +echo +echo "About to write:" +echo " Image: $IMG" +echo " Target: $EMMC_DEV" +echo + +printf "Type 'YES' to continue: " +read -r CONFIRM + +if [ "$CONFIRM" != "YES" ]; then + echo "Aborted." + umount "$MNT" || true + exit 1 +fi + +echo "[*] Flashing..." +gunzip -c "$IMG" > "$EMMC_DEV" + +echo "[*] Syncing..." +sync + +echo "[*] Done." +umount "$MNT" || true + +echo "[*] Rebooting..." +reboot -f diff --git a/initramfs/init b/initramfs/rootfs-extra/init similarity index 95% rename from initramfs/init rename to initramfs/rootfs-extra/init index 1b674e3..cc1495e 100755 --- a/initramfs/init +++ b/initramfs/rootfs-extra/init @@ -14,6 +14,8 @@ mount -t devpts devpts /dev/pts echo "Booting kernel took $(cut -d' ' -f1 /proc/uptime) seconds." echo "Dropping to shell on ttyS0..." +. /etc/build-info + while true; do setsid cttyhack /bin/sh echo "Shell exited. Starting another one..." diff --git a/makefile b/makefile index 4c40939..7fed2b7 100644 --- a/makefile +++ b/makefile @@ -26,6 +26,11 @@ BUILD_BASE_STAMP := $(OUT_DIR)/.build-base-$(TAG).stamp ALPINE_SERIES := $(word 1,$(subst ., ,$(ALPINE_VER))).$(word 2,$(subst ., ,$(ALPINE_VER))) +BUILD_VERSION ?= $(KUBE_VERSION) +BUILD_DATE := $(shell date -u +%Y-%m-%dT%H:%M:%SZ) +BUILD_GIT := $(shell git rev-parse --short HEAD 2>/dev/null || echo unknown) +BUILD_INFO_FILE := $(OUT_DIR)/build-info + # ---- File groups ------------------------------------------------------------- # Use find so adding new files under these dirs is automatically picked up. @@ -52,6 +57,7 @@ INITRAMFS_DEPS := \ $(BUSYBOX_TAR) \ docker/initramfs.Dockerfile \ $(INITRAMFS_SRCS) \ + $(BUILD_INFO_FILE) \ build.env \ makefile @@ -64,6 +70,7 @@ ITB_DEPS := \ RELEASE_DEPS := \ $(BUILD_BASE_STAMP) \ + $(BUILD_INFO_FILE) \ $(BOARD_ITB) \ $(ALPINE_TAR) \ $(CRIO_TAR) \ @@ -111,6 +118,15 @@ $(CRIO_TAR): | $(PACKAGES_DIR) # ---- Build stages ------------------------------------------------------------ +$(BUILD_INFO_FILE): + @mkdir -p $(dir $@) + @printf '%s\n' \ + 'export $(BUILD_TAG)_VERSION="$(BUILD_VERSION)"' \ + 'export $(BUILD_TAG)_BUILD_DATE="$(BUILD_DATE)"' \ + 'export $(BUILD_TAG)_GIT="$(BUILD_GIT)"' \ + 'export $(BUILD_TAG)_RELEASE_IMAGE="$(notdir $(RELEASE_IMAGE))"' \ + > $@ + $(BUILD_BASE_STAMP): $(BUILD_BASE_DEPS) | $(OUT_DIR) docker build \ -f docker/build-base.Dockerfile \ @@ -138,6 +154,7 @@ $(INITRAMFS): $(INITRAMFS_DEPS) | $(OUT_DIR) --build-arg ARCH=$(ARCH) \ --build-arg CROSS_COMPILE=$(CROSS_COMPILE) \ --build-arg BUSYBOX_VERSION=$(BUSYBOX_VERSION) \ + --build-arg BUILD_TAG=$(BUILD_TAG) \ --output type=local,dest=./$(OUT_DIR) . test -f $@