Files
kubesolo-os/build/scripts/fetch-components.sh
Adolfo Delorenzo 1b44c9d621
Some checks failed
ARM64 Build / Build generic ARM64 disk image (push) Failing after 3s
CI / Go Tests (push) Successful in 1m27s
CI / Shellcheck (push) Failing after 50s
CI / Build Go Binaries (amd64, linux, linux-amd64) (push) Failing after 1m33s
CI / Build Go Binaries (arm64, linux, linux-arm64) (push) Failing after 1m15s
feat: bump KubeSolo to v1.1.5 + cross-arch CI workflow
Phase 4 of v0.3 — KubeSolo version bump and CI gating.

KubeSolo v1.1.0 → v1.1.5 brings:
- New flag --disable-ipv6 (v1.1.5)
- New flag --db-wal-repair (v1.1.5) — important for power-loss resilience
  on edge appliances; surfaced as kubesolo.db-wal-repair in cloud-init
- New flag --full (v1.1.4) — disables edge-optimised k8s overrides
- Pod egress connectivity fix after reboot (v1.1.4)
- Registry config persistence fix (v1.1.5)
- k8s 1.34.7, CoreDNS 1.14.3, Go 1.26.2

All three new flags wired into cloud-init: config.go fields, kubesolo.go
extra-flag emission, full-config.yaml example.

Supply-chain hygiene:
- Per-arch checksums: KUBESOLO_SHA256_AMD64 and KUBESOLO_SHA256_ARM64 in
  versions.env. Replaces the single shared KUBESOLO_SHA256 that couldn't
  meaningfully verify both binaries at once.
- Checksum now applied to the tarball (the immutable upstream artifact)
  rather than the post-extract binary.

CI:
- New .gitea/workflows/build-arm64.yaml routes the full kernel + rootfs +
  disk-image build to the Odroid arm64-linux runner. Triggers on push to
  main, tags, and manual workflow_dispatch. The boot smoke test is
  continue-on-error because KubeSolo's first-boot image import deadline
  fires under QEMU TCG on the Odroid.

VERSION bumped to 0.3.0-dev. CHANGELOG entry under [0.3.0-dev] captures all
Phase 1-4 work + the known limitations documented in arm64-status.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 16:26:20 -06:00

250 lines
9.8 KiB
Bash
Executable File

#!/bin/bash
# fetch-components.sh — Download Tiny Core ISO and KubeSolo binary
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
CACHE_DIR="${CACHE_DIR:-$PROJECT_ROOT/build/cache}"
# Load versions
# shellcheck source=../config/versions.env
. "$SCRIPT_DIR/../config/versions.env"
# Verify SHA256 checksum of a downloaded file
verify_checksum() {
local file="$1" expected="$2" name="$3"
# Skip if no expected checksum provided
[ -z "$expected" ] && return 0
local actual
actual=$(sha256sum "$file" | awk '{print $1}')
if [ "$actual" = "$expected" ]; then
echo " Checksum OK: $name"
return 0
else
echo "ERROR: Checksum mismatch for $name"
echo " Expected: $expected"
echo " Got: $actual"
rm -f "$file"
return 1
fi
}
mkdir -p "$CACHE_DIR"
# Detect target architecture
FETCH_ARCH="${TARGET_ARCH:-amd64}"
# --- ARM64: piCore64 image instead of x86_64 ISO ---
if [ "$FETCH_ARCH" = "arm64" ]; then
PICORE_IMG="$CACHE_DIR/$PICORE_IMAGE"
if [ -f "$PICORE_IMG" ]; then
echo "==> piCore64 image already cached: $PICORE_IMG"
else
echo "==> Downloading piCore64 ${PICORE_VERSION} (${PICORE_ARCH})..."
echo " URL: $PICORE_IMAGE_URL"
wget -q --show-progress -O "$PICORE_IMG" "$PICORE_IMAGE_URL" 2>/dev/null || \
curl -fSL "$PICORE_IMAGE_URL" -o "$PICORE_IMG"
echo "==> Downloaded: $PICORE_IMG ($(du -h "$PICORE_IMG" | cut -f1))"
fi
# Also fetch RPi firmware
echo "==> Fetching RPi firmware..."
"$SCRIPT_DIR/fetch-rpi-firmware.sh"
# Download ARM64 KubeSolo binary (KUBESOLO_VERSION set from versions.env)
KUBESOLO_BIN_ARM64="$CACHE_DIR/kubesolo-arm64"
if [ -f "$KUBESOLO_BIN_ARM64" ]; then
echo "==> KubeSolo ARM64 binary already cached: $KUBESOLO_BIN_ARM64"
else
echo "==> Downloading KubeSolo ${KUBESOLO_VERSION} (arm64)..."
BIN_URL="https://github.com/portainer/kubesolo/releases/download/${KUBESOLO_VERSION}/kubesolo-${KUBESOLO_VERSION}-linux-arm64-musl.tar.gz"
BIN_URL_FALLBACK="https://github.com/portainer/kubesolo/releases/download/${KUBESOLO_VERSION}/kubesolo-${KUBESOLO_VERSION}-linux-arm64.tar.gz"
TEMP_DIR=$(mktemp -d)
TARBALL="$TEMP_DIR/kubesolo.tar.gz"
echo " URL: $BIN_URL"
if curl -fSL "$BIN_URL" -o "$TARBALL" 2>/dev/null; then
echo " Downloaded musl variant (arm64)"
elif curl -fSL "$BIN_URL_FALLBACK" -o "$TARBALL" 2>/dev/null; then
echo " Downloaded glibc variant (arm64 fallback)"
else
echo "ERROR: Failed to download KubeSolo ARM64 from GitHub."
rm -rf "$TEMP_DIR"
exit 1
fi
verify_checksum "$TARBALL" "${KUBESOLO_SHA256_ARM64:-}" "KubeSolo arm64 tarball"
tar -xzf "$TARBALL" -C "$TEMP_DIR"
FOUND_BIN=$(find "$TEMP_DIR" -name "kubesolo" -type f ! -name "*.tar.gz" | head -1)
if [ -z "$FOUND_BIN" ]; then
echo "ERROR: Could not find kubesolo binary in extracted archive"
rm -rf "$TEMP_DIR"
exit 1
fi
cp "$FOUND_BIN" "$KUBESOLO_BIN_ARM64"
chmod +x "$KUBESOLO_BIN_ARM64"
rm -rf "$TEMP_DIR"
echo "==> KubeSolo ARM64 binary: $KUBESOLO_BIN_ARM64 ($(du -h "$KUBESOLO_BIN_ARM64" | cut -f1))"
fi
# Skip x86_64 ISO and TCZ downloads for ARM64
echo ""
echo "==> ARM64 fetch complete."
echo "==> Component cache:"
ls -lh "$CACHE_DIR"/ 2>/dev/null || true
exit 0
fi
# --- x86_64: Tiny Core Linux ISO ---
TC_ISO="$CACHE_DIR/$TINYCORE_ISO"
TC_URL="${TINYCORE_MIRROR}/${TINYCORE_VERSION%%.*}.x/${TINYCORE_ARCH}/release/${TINYCORE_ISO}"
if [ -f "$TC_ISO" ]; then
echo "==> Tiny Core ISO already cached: $TC_ISO"
else
echo "==> Downloading Tiny Core Linux ${TINYCORE_VERSION} (${TINYCORE_ARCH})..."
echo " URL: $TC_URL"
wget -q --show-progress -O "$TC_ISO" "$TC_URL" || {
# Fallback: try alternate mirror structure
TC_URL_ALT="${TINYCORE_MIRROR}/${TINYCORE_VERSION%%.*}.x/${TINYCORE_ARCH}/release/CorePure64-current.iso"
echo " Primary URL failed, trying: $TC_URL_ALT"
wget -q --show-progress -O "$TC_ISO" "$TC_URL_ALT"
}
echo "==> Downloaded: $TC_ISO ($(du -h "$TC_ISO" | cut -f1))"
verify_checksum "$TC_ISO" "$TINYCORE_ISO_SHA256" "Tiny Core ISO"
fi
# --- KubeSolo ---
# KUBESOLO_VERSION sourced from versions.env
KUBESOLO_BIN="$CACHE_DIR/kubesolo"
if [ -f "$KUBESOLO_BIN" ]; then
echo "==> KubeSolo binary already cached: $KUBESOLO_BIN"
else
echo "==> Downloading KubeSolo ${KUBESOLO_VERSION}..."
# Determine architecture
ARCH="${TARGET_ARCH:-amd64}"
OS="linux"
# Build download URL from GitHub releases
# Available variants: kubesolo-v1.1.0-linux-amd64.tar.gz, kubesolo-v1.1.0-linux-amd64-musl.tar.gz
# We use the musl variant for maximum compatibility with Tiny Core Linux (musl-based)
BIN_URL="https://github.com/portainer/kubesolo/releases/download/${KUBESOLO_VERSION}/kubesolo-${KUBESOLO_VERSION}-${OS}-${ARCH}-musl.tar.gz"
BIN_URL_FALLBACK="https://github.com/portainer/kubesolo/releases/download/${KUBESOLO_VERSION}/kubesolo-${KUBESOLO_VERSION}-${OS}-${ARCH}.tar.gz"
TEMP_DIR=$(mktemp -d)
trap 'rm -rf "$TEMP_DIR"' EXIT
TARBALL="$TEMP_DIR/kubesolo.tar.gz"
echo " URL: $BIN_URL"
if curl -fSL "$BIN_URL" -o "$TARBALL" 2>/dev/null; then
echo " Downloaded musl variant"
elif curl -fSL "$BIN_URL_FALLBACK" -o "$TARBALL" 2>/dev/null; then
echo " Downloaded glibc variant (fallback)"
else
echo "ERROR: Failed to download KubeSolo from GitHub."
echo " Tried: $BIN_URL"
echo " Tried: $BIN_URL_FALLBACK"
echo ""
echo " Manual step:"
echo " 1. Download from: https://github.com/portainer/kubesolo/releases"
echo " 2. Extract and copy binary to: $KUBESOLO_BIN"
echo " 3. Re-run: make rootfs"
exit 1
fi
verify_checksum "$TARBALL" "${KUBESOLO_SHA256_AMD64:-}" "KubeSolo amd64 tarball"
# Extract binary from tarball
tar -xzf "$TARBALL" -C "$TEMP_DIR"
# Find the kubesolo binary in extracted contents
FOUND_BIN=$(find "$TEMP_DIR" -name "kubesolo" -type f ! -name "*.tar.gz" | head -1)
if [ -z "$FOUND_BIN" ]; then
echo "ERROR: Could not find kubesolo binary in extracted archive"
echo " Archive contents:"
ls -la "$TEMP_DIR"/
exit 1
fi
cp "$FOUND_BIN" "$KUBESOLO_BIN"
chmod +x "$KUBESOLO_BIN"
trap - EXIT
rm -rf "$TEMP_DIR"
echo "==> KubeSolo binary: $KUBESOLO_BIN ($(du -h "$KUBESOLO_BIN" | cut -f1))"
fi
# --- Tiny Core kernel module extensions (netfilter, iptables) ---
# The base Tiny Core initramfs does NOT include netfilter kernel modules.
# They are distributed as separate TCZ (squashfs) extensions.
# KubeSolo requires netfilter for kube-proxy, iptables NAT, conntrack, etc.
# Detect kernel version from the cached ISO
KVER=""
if [ -f "$TC_ISO" ]; then
# Try to detect kernel version from ISO without mounting
# Tiny Core 17.0 uses 6.18.2-tinycore64
KVER="6.18.2-tinycore64"
fi
NETFILTER_TCZ="$CACHE_DIR/ipv6-netfilter-${KVER}.tcz"
NETFILTER_TCZ_URL="https://distro.ibiblio.org/tinycorelinux/${TINYCORE_VERSION%%.*}.x/${TINYCORE_ARCH}/tcz/ipv6-netfilter-${KVER}.tcz"
if [ -f "$NETFILTER_TCZ" ]; then
echo "==> Netfilter modules already cached: $NETFILTER_TCZ"
else
echo "==> Downloading netfilter kernel modules (ipv6-netfilter-${KVER}.tcz)..."
echo " URL: $NETFILTER_TCZ_URL"
if wget -q --show-progress -O "$NETFILTER_TCZ" "$NETFILTER_TCZ_URL" 2>/dev/null || \
curl -fSL "$NETFILTER_TCZ_URL" -o "$NETFILTER_TCZ" 2>/dev/null; then
echo "==> Downloaded: $NETFILTER_TCZ ($(du -h "$NETFILTER_TCZ" | cut -f1))"
verify_checksum "$NETFILTER_TCZ" "$NETFILTER_TCZ_SHA256" "netfilter TCZ"
else
echo "WARN: Failed to download netfilter modules. kube-proxy may not work."
rm -f "$NETFILTER_TCZ"
fi
fi
NET_BRIDGING_TCZ="$CACHE_DIR/net-bridging-${KVER}.tcz"
NET_BRIDGING_TCZ_URL="https://distro.ibiblio.org/tinycorelinux/${TINYCORE_VERSION%%.*}.x/${TINYCORE_ARCH}/tcz/net-bridging-${KVER}.tcz"
if [ -f "$NET_BRIDGING_TCZ" ]; then
echo "==> Net-bridging modules already cached: $NET_BRIDGING_TCZ"
else
echo "==> Downloading net-bridging kernel modules (net-bridging-${KVER}.tcz)..."
echo " URL: $NET_BRIDGING_TCZ_URL"
if wget -q --show-progress -O "$NET_BRIDGING_TCZ" "$NET_BRIDGING_TCZ_URL" 2>/dev/null || \
curl -fSL "$NET_BRIDGING_TCZ_URL" -o "$NET_BRIDGING_TCZ" 2>/dev/null; then
echo "==> Downloaded: $NET_BRIDGING_TCZ ($(du -h "$NET_BRIDGING_TCZ" | cut -f1))"
verify_checksum "$NET_BRIDGING_TCZ" "$NET_BRIDGING_TCZ_SHA256" "net-bridging TCZ"
else
echo "WARN: Failed to download net-bridging modules. CNI bridge may not work."
rm -f "$NET_BRIDGING_TCZ"
fi
fi
IPTABLES_TCZ="$CACHE_DIR/iptables.tcz"
IPTABLES_TCZ_URL="https://distro.ibiblio.org/tinycorelinux/${TINYCORE_VERSION%%.*}.x/${TINYCORE_ARCH}/tcz/iptables.tcz"
if [ -f "$IPTABLES_TCZ" ]; then
echo "==> iptables userspace already cached: $IPTABLES_TCZ"
else
echo "==> Downloading iptables userspace tools..."
echo " URL: $IPTABLES_TCZ_URL"
if wget -q --show-progress -O "$IPTABLES_TCZ" "$IPTABLES_TCZ_URL" 2>/dev/null || \
curl -fSL "$IPTABLES_TCZ_URL" -o "$IPTABLES_TCZ" 2>/dev/null; then
echo "==> Downloaded: $IPTABLES_TCZ ($(du -h "$IPTABLES_TCZ" | cut -f1))"
verify_checksum "$IPTABLES_TCZ" "$IPTABLES_TCZ_SHA256" "iptables TCZ"
else
echo "WARN: Failed to download iptables. KubeSolo bundles its own but this is a fallback."
rm -f "$IPTABLES_TCZ"
fi
fi
# --- Summary ---
echo ""
echo "==> Component cache:"
ls -lh "$CACHE_DIR"/ 2>/dev/null || true
echo ""
echo "==> Fetch complete."