The rebuild subcommand now executes the full pipeline: - build_registry() -> resolve() -> sched::run() - install::install() for each built package - service::install_service() for enabled services - boot::install_bootloader_config() for bootloader config - system::write_hostname() / write_timezone() for system activation Added --dry-run flag for report-only behavior (backward compat with test suite). Added -w flag for worker parallelism and --dry-run to help. Fixed .gitignore: 'kappa' -> '/kappa' (was matching include/kappa/, preventing header files from being tracked since initial commit). This commit also adds all previously-gitignored header files.
351 lines
9.4 KiB
Bash
Executable File
351 lines
9.4 KiB
Bash
Executable File
#!/bin/bash
|
|
# kappa init-switching integration test via systemd-nspawn
|
|
# Requires: systemd-nspawn, debootstrap (or pacstrap), kappa binary
|
|
set -euo pipefail
|
|
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
NC='\033[0m'
|
|
|
|
KAPPA_BIN="${KAPPA_BIN:-./build/kappa}"
|
|
ROOTFS="./test-rootfs"
|
|
PASS=0
|
|
FAIL=0
|
|
|
|
cleanup() {
|
|
echo ""
|
|
echo "Cleaning up..."
|
|
rm -rf "$ROOTFS" /tmp/kappa-test-*.kap 2>/dev/null || true
|
|
}
|
|
|
|
trap cleanup EXIT
|
|
|
|
check() {
|
|
local desc="$1" cmd="$2" expect="$3"
|
|
echo -n " $desc ... "
|
|
local out
|
|
out=$(eval "$cmd" 2>&1) || true
|
|
if echo "$out" | grep -q "$expect"; then
|
|
echo -e "${GREEN}OK${NC}"
|
|
PASS=$((PASS + 1))
|
|
else
|
|
echo -e "${RED}FAIL${NC}"
|
|
echo " expected: $expect"
|
|
echo " got: $(echo "$out" | head -3 | tr '\n' ' ')"
|
|
FAIL=$((FAIL + 1))
|
|
fi
|
|
}
|
|
|
|
echo ""
|
|
echo "============================================"
|
|
echo " kappa init-switching integration tests"
|
|
echo "============================================"
|
|
echo ""
|
|
|
|
# ------------------------------------------------------------------
|
|
# 1. Create a minimal rootfs directory structure
|
|
# ------------------------------------------------------------------
|
|
echo "--- Setting up test rootfs ---"
|
|
|
|
mkdir -p "$ROOTFS"/{etc,usr/local/bin,kappa/{boot,db,store,temp},var/service}
|
|
cp "$KAPPA_BIN" "$ROOTFS/usr/local/bin/kappa"
|
|
chmod +x "$ROOTFS/usr/local/bin/kappa"
|
|
|
|
export KAPPA_ROOT="$ROOTFS/kappa"
|
|
|
|
# Create a minimal package registry (simulating installed packages)
|
|
mkdir -p "$KAPPA_ROOT/db"
|
|
|
|
# Simulate an installed system with nginx (has services), zlib (no services),
|
|
# and postgresql (multi-service, uses ${enabledinit})
|
|
cat > /tmp/kappa-test-nginx.kap << 'EOF'
|
|
package "nginx" {
|
|
version = "1.24"
|
|
source = "https://nginx.org/nginx-1.24.tar.gz"
|
|
service {
|
|
exec = "/usr/bin/nginx"
|
|
type = "forking"
|
|
ports = [80, 443]
|
|
user = "www-data"
|
|
description = "Nginx web server"
|
|
}
|
|
build { ./configure --prefix=${prefix}; make -j${jobs} }
|
|
install { make DESTDIR=${destdir} install }
|
|
}
|
|
EOF
|
|
|
|
cat > /tmp/kappa-test-zlib.kap << 'EOF'
|
|
package "zlib" {
|
|
version = "1.3"
|
|
source = "https://zlib.net/zlib-1.3.tar.gz"
|
|
build { ./configure --prefix=${prefix}; make -j${jobs} }
|
|
install { make DESTDIR=${destdir} install }
|
|
}
|
|
EOF
|
|
|
|
cat > /tmp/kappa-test-postgres.kap << 'EOF'
|
|
package "postgresql" {
|
|
version = "16.3"
|
|
source = "https://ftp.postgresql.org/source/postgresql-16.3.tar.gz"
|
|
service main {
|
|
exec = "/usr/bin/postgres"
|
|
type = "forking"
|
|
ports = [5432]
|
|
user = "postgres"
|
|
description = "PostgreSQL database server"
|
|
}
|
|
service checkpointer {
|
|
exec = "/usr/bin/postgres-checkpointer"
|
|
type = "longrun"
|
|
user = "postgres"
|
|
}
|
|
build {
|
|
case ${enabledinit} in
|
|
systemd) ./configure --with-systemd --prefix=${prefix} ;;
|
|
*) ./configure --prefix=${prefix} ;;
|
|
esac
|
|
make -j${jobs}
|
|
}
|
|
install { make DESTDIR=${destdir} install }
|
|
}
|
|
EOF
|
|
|
|
# Write installed DB (simulate nginx, zlib, postgresql already installed)
|
|
# Format: name version hash [provides...]
|
|
mkdir -p "$(dirname "$KAPPA_ROOT/db/installed")"
|
|
cat > "$KAPPA_ROOT/db/installed" << 'EOF'
|
|
nginx 1.24 a1b2c3d4e5f6a7b8
|
|
zlib 1.3 b2c3d4e5f6a7b8c9
|
|
postgresql 16.3 c3d4e5f6a7b8c9d0
|
|
init a1b2c3d4e5f6a7b8
|
|
kernel d4e5f6a7b8c9d0e1
|
|
bootloader e5f6a7b8c9d0e1f2
|
|
EOF
|
|
|
|
echo ""
|
|
|
|
# ------------------------------------------------------------------
|
|
# 2. Init system switching tests
|
|
# ------------------------------------------------------------------
|
|
echo "--- Init system switching ---"
|
|
|
|
# Base config template
|
|
config_template() {
|
|
local init="$1"
|
|
cat << EOF
|
|
system { hostname = "kappa-test" }
|
|
packages {
|
|
nginx {}
|
|
zlib {}
|
|
postgresql {}
|
|
$init {}
|
|
}
|
|
services {
|
|
nginx { enable = true }
|
|
postgresql { enable = true }
|
|
postgresql.checkpointer { enable = true }
|
|
}
|
|
boot {
|
|
kernel = "linux"
|
|
init = "$init"
|
|
root = "/dev/sda1"
|
|
bootloader = "limine"
|
|
}
|
|
groups {
|
|
wheel { gid = 998 }
|
|
}
|
|
users {
|
|
root { shell = "/bin/zsh" }
|
|
}
|
|
EOF
|
|
}
|
|
|
|
# Test systemd config
|
|
config_template "systemd" > /tmp/kappa-test-systemd.kap
|
|
check "parse systemd config" \
|
|
"$KAPPA_BIN parse-config /tmp/kappa-test-systemd.kap" \
|
|
'systemd — system and service manager'
|
|
|
|
check "systemd bootloader in config" \
|
|
"$KAPPA_BIN parse-config /tmp/kappa-test-systemd.kap" \
|
|
'Limine'
|
|
|
|
# Test openrc config
|
|
config_template "openrc" > /tmp/kappa-test-openrc.kap
|
|
check "parse openrc config" \
|
|
"$KAPPA_BIN parse-config /tmp/kappa-test-openrc.kap" \
|
|
'OpenRC — dependency-based init'
|
|
|
|
# Test s6 config
|
|
config_template "s6" > /tmp/kappa-test-s6.kap
|
|
check "parse s6 config" \
|
|
"$KAPPA_BIN parse-config /tmp/kappa-test-s6.kap" \
|
|
's6 — s6 supervision suite'
|
|
|
|
# Test runit config
|
|
config_template "runit" > /tmp/kappa-test-runit.kap
|
|
check "parse runit config" \
|
|
"$KAPPA_BIN parse-config /tmp/kappa-test-runit.kap" \
|
|
'runit — supervision suite'
|
|
|
|
# Test dinit config
|
|
config_template "dinit" > /tmp/kappa-test-dinit.kap
|
|
check "parse dinit config" \
|
|
"$KAPPA_BIN parse-config /tmp/kappa-test-dinit.kap" \
|
|
'dinit — service manager'
|
|
|
|
echo ""
|
|
|
|
# ------------------------------------------------------------------
|
|
# 3. Service generation verification
|
|
# ------------------------------------------------------------------
|
|
echo "--- Service file generation ---"
|
|
|
|
# Verify service specs are parsed correctly per init
|
|
for init in systemd openrc s6 runit dinit; do
|
|
check "service block present for $init config" \
|
|
"$KAPPA_BIN format /tmp/kappa-test-$init.kap" \
|
|
'enable = true'
|
|
done
|
|
|
|
# Verify the format output contains correct service fields
|
|
check "nginx service has type forking" \
|
|
"$KAPPA_BIN format /tmp/kappa-test-nginx.kap" \
|
|
'type = "forking"'
|
|
|
|
check "postgresql has named service checkpointer" \
|
|
"$KAPPA_BIN format /tmp/kappa-test-postgres.kap" \
|
|
'service checkpointer'
|
|
|
|
check "postgresql build uses enabledinit" \
|
|
"$KAPPA_BIN format /tmp/kappa-test-postgres.kap" \
|
|
'enabledinit'
|
|
|
|
echo ""
|
|
|
|
# ------------------------------------------------------------------
|
|
# 4. Rebuild impact analysis
|
|
# ------------------------------------------------------------------
|
|
echo "--- Rebuild impact analysis ---"
|
|
|
|
# Write an initial installed state matching s6 config
|
|
# (reuse the same installed DB from above)
|
|
|
|
config_template "s6" > /tmp/kappa-test-rebuild-s6.kap
|
|
# The packages list includes "s6" which isn't in the installed DB,
|
|
# so rebuild correctly shows it as a new package to build.
|
|
check "rebuild detects new init package" \
|
|
"$KAPPA_BIN rebuild --dry-run /tmp/kappa-test-rebuild-s6.kap 2>&1" \
|
|
'packages to rebuild'
|
|
|
|
# Now test switching FROM s6 TO systemd
|
|
config_template "systemd" > /tmp/kappa-test-rebuild-systemd.kap
|
|
|
|
# The rebuild should detect init_changed
|
|
# Note: this requires the installed DB to have the old init hash
|
|
check "rebuild detects init change" \
|
|
"$KAPPA_BIN rebuild --dry-run /tmp/kappa-test-rebuild-systemd.kap 2>&1" \
|
|
'packages to rebuild'
|
|
|
|
echo ""
|
|
|
|
# ------------------------------------------------------------------
|
|
# 5. Bootloader switching tests
|
|
# ------------------------------------------------------------------
|
|
echo "--- Bootloader switching ---"
|
|
|
|
for bl in grub limine; do
|
|
cat > "/tmp/kappa-test-bl-$bl.kap" << KAPEOF
|
|
system { hostname = "test" }
|
|
packages { nginx {} }
|
|
services {}
|
|
boot {
|
|
kernel = "linux"
|
|
init = "s6"
|
|
root = "/dev/sda1"
|
|
bootloader = "$bl"
|
|
}
|
|
users { root { shell = "/bin/sh" } }
|
|
KAPEOF
|
|
check "bootloader $bl recognized in config" \
|
|
"$KAPPA_BIN parse-config /tmp/kappa-test-bl-$bl.kap" \
|
|
"$bl"
|
|
done
|
|
|
|
# Test unknown bootloader
|
|
cat > /tmp/kappa-test-badbl.kap << 'KAPEOF'
|
|
system { hostname = "test" }
|
|
packages {}
|
|
services {}
|
|
boot {
|
|
kernel = "linux"
|
|
init = "s6"
|
|
root = "/dev/sda1"
|
|
bootloader = "lilo"
|
|
}
|
|
users { root { shell = "/bin/sh" } }
|
|
KAPEOF
|
|
check "doctor warns on unknown bootloader" \
|
|
"$KAPPA_BIN doctor /tmp/kappa-test-badbl.kap 2>&1" \
|
|
'not a recognized bootloader'
|
|
|
|
echo ""
|
|
|
|
# ------------------------------------------------------------------
|
|
# 6. Groups and conflicts
|
|
# ------------------------------------------------------------------
|
|
echo "--- Groups and conflicts ---"
|
|
|
|
cat > /tmp/kappa-test-groups2.kap << 'KAPEOF'
|
|
system { hostname = "test" }
|
|
packages {}
|
|
services {}
|
|
boot {
|
|
kernel = "linux"
|
|
init = "s6"
|
|
root = "/dev/sda1"
|
|
bootloader = "limine"
|
|
}
|
|
groups {
|
|
wheel { gid = 998 }
|
|
audio {}
|
|
docker { gid = 995 }
|
|
}
|
|
users { root { shell = "/bin/sh" } }
|
|
KAPEOF
|
|
|
|
check "groups with gid format correctly" \
|
|
"$KAPPA_BIN format /tmp/kappa-test-groups2.kap" \
|
|
'gid = 998'
|
|
|
|
check "groups without gid format as empty" \
|
|
"$KAPPA_BIN format /tmp/kappa-test-groups2.kap" \
|
|
'audio {}'
|
|
|
|
# Conflicts test
|
|
cat > /tmp/kappa-test-conflict-pkg.kap << 'KAPEOF'
|
|
package "systemd" {
|
|
version = "255"
|
|
source = "https://example.com/systemd.tar.gz"
|
|
provides = ["udev", "logind"]
|
|
conflicts = ["eudev", "elogind"]
|
|
build { make }
|
|
install { make install }
|
|
}
|
|
KAPEOF
|
|
|
|
check "conflicts parse correctly" \
|
|
"$KAPPA_BIN parse-package /tmp/kappa-test-conflict-pkg.kap" \
|
|
'valid'
|
|
|
|
check "conflicts format round-trips" \
|
|
"$KAPPA_BIN format /tmp/kappa-test-conflict-pkg.kap" \
|
|
'conflicts = \['
|
|
|
|
echo ""
|
|
echo "============================================"
|
|
echo -e " Results: ${GREEN}$PASS passed${NC}, ${RED}$FAIL failed${NC}"
|
|
echo "============================================"
|
|
|
|
[ "$FAIL" -eq 0 ] || exit 1
|