From f4a3eb7f1ab17c32d9bc2e516b1e4352e0d0d3f1 Mon Sep 17 00:00:00 2001 From: Carlos Eduardo Arango Gutierrez Date: Wed, 18 Feb 2026 14:36:58 +0100 Subject: [PATCH] feat(templates): add RPM support to kernel template Add OS-family branching to the kernel template for RPM-based distributions (Rocky Linux, Amazon Linux, RHEL): Debian branch: - DEBIAN_FRONTEND, debconf-set-selections for non-interactive apt - apt-cache show for kernel availability check - linux-image, linux-headers, linux-modules packages - update-grub and update-initramfs for bootloader - --allow-downgrades flag for apt-get install RPM branch: - dnf list available for kernel availability check - kernel and kernel-devel packages (modules bundled on RPM) - grub2-mkconfig with BIOS/UEFI path fallback - dracut --force for initramfs regeneration - --allowerasing flag for dnf install Common (moved outside case block): - pkg_update replaces bare apt-get update - Kernel version check, reboot logic, state management Follows the established case/HOLODECK_OS_FAMILY pattern. Signed-off-by: Carlos Eduardo Arango Gutierrez --- pkg/provisioner/templates/kernel.go | 102 ++++++++++++++++------- pkg/provisioner/templates/kernel_test.go | 65 +++++++++++++++ 2 files changed, 135 insertions(+), 32 deletions(-) diff --git a/pkg/provisioner/templates/kernel.go b/pkg/provisioner/templates/kernel.go index 3e8ec48c2..c78096518 100644 --- a/pkg/provisioner/templates/kernel.go +++ b/pkg/provisioner/templates/kernel.go @@ -29,11 +29,6 @@ const kernelTemplate = ` COMPONENT="kernel" KERNEL_VERSION="{{ .Spec.Kernel.Version }}" -# Set non-interactive frontend for apt and disable editor prompts -export DEBIAN_FRONTEND=noninteractive -export EDITOR=/bin/true -echo 'debconf debconf/frontend select Noninteractive' | sudo debconf-set-selections - holodeck_progress "$COMPONENT" 1 4 "Checking current kernel" # Get current kernel version @@ -60,33 +55,76 @@ fi holodeck_progress "$COMPONENT" 2 4 "Installing kernel packages" # Update package lists -holodeck_retry 3 "$COMPONENT" sudo apt-get update - -# Check if kernel packages are available -if ! apt-cache show "linux-image-${KERNEL_VERSION}" &>/dev/null; then - holodeck_error 4 "$COMPONENT" \ - "Kernel version ${KERNEL_VERSION} not found in repositories" \ - "Check available kernels with: apt-cache search linux-image" -fi - -holodeck_progress "$COMPONENT" 3 4 "Installing kernel ${KERNEL_VERSION}" - -# Clean up old kernel files (optional, preserves space) -sudo rm -rf /boot/*"${CURRENT_KERNEL}"* 2>/dev/null || true -sudo rm -rf /lib/modules/*"${CURRENT_KERNEL}"* 2>/dev/null || true -sudo rm -rf /boot/*.old 2>/dev/null || true - -# Install new kernel and related packages -holodeck_retry 3 "$COMPONENT" sudo apt-get install --allow-downgrades -y \ - "linux-image-${KERNEL_VERSION}" \ - "linux-headers-${KERNEL_VERSION}" \ - "linux-modules-${KERNEL_VERSION}" - -holodeck_progress "$COMPONENT" 4 4 "Updating bootloader" - -holodeck_log "INFO" "$COMPONENT" "Updating grub and initramfs" -sudo update-grub || true -sudo update-initramfs -u -k "${KERNEL_VERSION}" || true +holodeck_retry 3 "$COMPONENT" pkg_update + +case "${HOLODECK_OS_FAMILY}" in + debian) + # Set non-interactive frontend for apt and disable editor prompts + export DEBIAN_FRONTEND=noninteractive + export EDITOR=/bin/true + echo 'debconf debconf/frontend select Noninteractive' | sudo debconf-set-selections + + # Check if kernel packages are available + if ! apt-cache show "linux-image-${KERNEL_VERSION}" &>/dev/null; then + holodeck_error 4 "$COMPONENT" \ + "Kernel version ${KERNEL_VERSION} not found in repositories" \ + "Check available kernels with: apt-cache search linux-image" + fi + + holodeck_progress "$COMPONENT" 3 4 "Installing kernel ${KERNEL_VERSION}" + + # Clean up old kernel files (optional, preserves space) + sudo rm -rf /boot/*"${CURRENT_KERNEL}"* 2>/dev/null || true + sudo rm -rf /lib/modules/*"${CURRENT_KERNEL}"* 2>/dev/null || true + sudo rm -rf /boot/*.old 2>/dev/null || true + + # Install new kernel and related packages + holodeck_retry 3 "$COMPONENT" sudo apt-get install --allow-downgrades -y \ + "linux-image-${KERNEL_VERSION}" \ + "linux-headers-${KERNEL_VERSION}" \ + "linux-modules-${KERNEL_VERSION}" + + holodeck_progress "$COMPONENT" 4 4 "Updating bootloader" + + holodeck_log "INFO" "$COMPONENT" "Updating grub and initramfs" + sudo update-grub || true + sudo update-initramfs -u -k "${KERNEL_VERSION}" || true + ;; + + amazon|rhel) + # Check if kernel packages are available + if ! dnf list available "kernel-${KERNEL_VERSION}" &>/dev/null; then + holodeck_error 4 "$COMPONENT" \ + "Kernel version ${KERNEL_VERSION} not found in repositories" \ + "Check available kernels with: dnf list available kernel-*" + fi + + holodeck_progress "$COMPONENT" 3 4 "Installing kernel ${KERNEL_VERSION}" + + # Clean up old kernel files (optional, preserves space) + sudo rm -rf /boot/*"${CURRENT_KERNEL}"* 2>/dev/null || true + sudo rm -rf /lib/modules/*"${CURRENT_KERNEL}"* 2>/dev/null || true + sudo rm -rf /boot/*.old 2>/dev/null || true + + # Install new kernel and related packages + # On RPM, modules are bundled with the kernel package + holodeck_retry 3 "$COMPONENT" sudo dnf install --allowerasing -y \ + "kernel-${KERNEL_VERSION}" \ + "kernel-devel-${KERNEL_VERSION}" + + holodeck_progress "$COMPONENT" 4 4 "Updating bootloader" + + holodeck_log "INFO" "$COMPONENT" "Updating grub and initramfs" + sudo grub2-mkconfig -o /boot/grub2/grub.cfg || \ + sudo grub2-mkconfig -o /boot/efi/EFI/$(. /etc/os-release && echo "$ID")/grub.cfg || true + sudo dracut --force --kver "${KERNEL_VERSION}" || true + ;; + + *) + holodeck_error 2 "$COMPONENT" "Unsupported OS family: ${HOLODECK_OS_FAMILY}" \ + "Supported: debian, amazon, rhel" + ;; +esac # Mark as pending reboot installed_at="$(date -Iseconds)" diff --git a/pkg/provisioner/templates/kernel_test.go b/pkg/provisioner/templates/kernel_test.go index ec632687e..f6e62f006 100644 --- a/pkg/provisioner/templates/kernel_test.go +++ b/pkg/provisioner/templates/kernel_test.go @@ -166,6 +166,71 @@ func TestKernelTemplateContent(t *testing.T) { } } +func TestKernelTemplate_OSFamilyBranching(t *testing.T) { + env := v1alpha1.Environment{ + Spec: v1alpha1.EnvironmentSpec{ + Kernel: v1alpha1.Kernel{ + Version: "6.1.0", + }, + }, + } + + buf, err := NewKernelTemplate(env) + if err != nil { + t.Fatalf("Failed to create kernel template: %v", err) + } + + out := buf.String() + + // Must have OS-family case statement + if !strings.Contains(out, `case "${HOLODECK_OS_FAMILY}" in`) { + t.Error("kernel template should branch on HOLODECK_OS_FAMILY") + } + + // Debian branch must have Debian-specific elements + debianElements := []string{ + "DEBIAN_FRONTEND=noninteractive", + "debconf-set-selections", + "apt-cache show", + "linux-image-", + "linux-headers-", + "linux-modules-", + "update-grub", + "update-initramfs", + "--allow-downgrades", + } + for _, elem := range debianElements { + if !strings.Contains(out, elem) { + t.Errorf("kernel template should contain Debian element: %s", elem) + } + } + + // RPM branch must have RPM-specific elements + rpmElements := []string{ + "dnf list available", + "kernel-${KERNEL_VERSION}", + "kernel-devel-${KERNEL_VERSION}", + "grub2-mkconfig", + "dracut --force", + "--allowerasing", + } + for _, elem := range rpmElements { + if !strings.Contains(out, elem) { + t.Errorf("kernel template should contain RPM element: %s", elem) + } + } + + // Default case must have holodeck_error + if !strings.Contains(out, `holodeck_error 2 "$COMPONENT" "Unsupported OS family`) { + t.Error("kernel template should have holodeck_error for unsupported OS family") + } + + // pkg_update should be used instead of bare apt-get update + if !strings.Contains(out, "pkg_update") { + t.Error("kernel template should use pkg_update abstraction") + } +} + func TestKernelTemplateErrorHandling(t *testing.T) { // Test with invalid template invalidTemplate := "{{ .InvalidField }}"