#!/bin/bash # Particle-OS Bootc Deployment Test Script # Tests all critical requirements identified in scope.md set -e echo "๐Ÿ” Particle-OS Bootc Deployment Validation" echo "==========================================" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color # Function to print colored output print_status() { local status=$1 local message=$2 if [ "$status" = "PASS" ]; then echo -e "${GREEN}โœ… PASS${NC}: $message" elif [ "$status" = "FAIL" ]; then echo -e "${RED}โŒ FAIL${NC}: $message" else echo -e "${YELLOW}โš ๏ธ WARN${NC}: $message" fi } # Function to check if command exists and is working check_command() { local cmd=$1 local description=$2 local required=$3 if command -v "$cmd" >/dev/null 2>&1; then # Handle commands that don't support --version or -V if [ "$cmd" = "mkfs.fat" ]; then if "$cmd" --help >/dev/null 2>&1; then print_status "PASS" "$description: $cmd is available and working" return 0 else print_status "FAIL" "$description: $cmd exists but not working properly" return 1 fi elif "$cmd" --version >/dev/null 2>&1 || "$cmd" -V >/dev/null 2>&1; then print_status "PASS" "$description: $cmd is available and working" return 0 else print_status "FAIL" "$description: $cmd exists but not working properly" return 1 fi else if [ "$required" = "true" ]; then print_status "FAIL" "$description: $cmd is missing (REQUIRED)" return 1 else print_status "WARN" "$description: $cmd is missing (optional)" return 0 fi fi } # Function to check PATH environment check_path() { echo -e "\n๐Ÿ” Checking PATH environment..." echo "Current PATH: $PATH" # Check if critical directories are in PATH if [[ ":$PATH:" == *":/usr/sbin:"* ]] && [[ ":$PATH:" == *":/sbin:"* ]]; then print_status "PASS" "PATH includes /usr/sbin and /sbin" else print_status "FAIL" "PATH missing /usr/sbin or /sbin (CRITICAL for bootc)" echo "Fixing PATH..." export PATH="/usr/sbin:/sbin:$PATH" echo "Updated PATH: $PATH" fi # Check if critical utilities are accessible via PATH echo -e "\n๐Ÿ” Checking utility accessibility via PATH..." if command -v sfdisk >/dev/null 2>&1; then print_status "PASS" "sfdisk accessible via PATH" else print_status "FAIL" "sfdisk not accessible via PATH (should be in /usr/sbin)" echo "Checking if sfdisk exists in /usr/sbin..." if [ -x "/usr/sbin/sfdisk" ]; then print_status "PASS" "sfdisk exists in /usr/sbin but not in PATH" else print_status "FAIL" "sfdisk missing from /usr/sbin" fi fi } # Function to check disk utilities (CRITICAL from scope.md) check_disk_utilities() { echo -e "\n๐Ÿ”ง Checking disk utilities (CRITICAL for bootc deployment)..." local all_passed=true # Check required disk utilities with explicit path checking echo -e "\n๐Ÿ” Checking disk utilities in their correct locations..." # Check sfdisk (critical - should be in /usr/sbin) if [ -x "/usr/sbin/sfdisk" ]; then if /usr/sbin/sfdisk --version >/dev/null 2>&1; then print_status "PASS" "sfdisk available in /usr/sbin and working" else print_status "FAIL" "sfdisk in /usr/sbin but not working properly" all_passed=false fi else print_status "FAIL" "sfdisk missing from /usr/sbin (CRITICAL)" all_passed=false fi # Check other utilities check_command "parted" "Alternative partitioning tool" "true" || all_passed=false check_command "mkfs.ext4" "Ext4 filesystem creation" "true" || all_passed=false check_command "mkfs.fat" "FAT filesystem creation" "true" || all_passed=false # Check for GRUB installation (handle different names and locations) if [ -x "/usr/sbin/grub-install" ]; then if /usr/sbin/grub-install --version >/dev/null 2>&1; then print_status "PASS" "grub-install available in /usr/sbin and working" else print_status "FAIL" "grub-install in /usr/sbin but not working properly" all_passed=false fi elif [ -x "/usr/bin/grub-install" ]; then if /usr/bin/grub-install --version >/dev/null 2>&1; then print_status "PASS" "grub-install available in /usr/bin and working" else print_status "FAIL" "grub-install in /usr/bin but not working properly" all_passed=false fi elif command -v "grub2-install" >/dev/null 2>&1; then check_command "grub2-install" "GRUB2 bootloader installation" "true" || all_passed=false else print_status "FAIL" "GRUB bootloader installation: neither grub-install nor grub2-install found (REQUIRED)" all_passed=false fi check_command "efibootmgr" "UEFI boot manager" "true" || all_passed=false # Check additional utilities check_command "fdisk" "Disk partitioning utility" "false" check_command "gdisk" "GPT partitioning utility" "false" if [ "$all_passed" = "false" ]; then echo -e "\n${RED}โŒ CRITICAL: Some required disk utilities are missing!${NC}" echo "This will prevent bootc from deploying successfully." echo "" echo "Common solutions:" echo "1. Install missing packages: apt install util-linux parted e2fsprogs dosfstools grub-efi-amd64 efibootmgr" echo "2. Fix PATH: export PATH=\"/usr/sbin:/sbin:\$PATH\"" echo "3. Check utility locations: ls -la /usr/sbin/sfdisk /usr/sbin/grub-install" return 1 fi print_status "PASS" "All critical disk utilities are available" return 0 } # Function to check bootc functionality check_bootc() { echo -e "\n๐Ÿš€ Checking bootc functionality..." if command -v bootc >/dev/null 2>&1; then local version=$(bootc --version 2>/dev/null || echo "unknown") print_status "PASS" "bootc is available: $version" # Test basic bootc commands if bootc --help >/dev/null 2>&1; then print_status "PASS" "bootc --help works correctly" else print_status "FAIL" "bootc --help failed" return 1 fi else print_status "FAIL" "bootc is not available (CRITICAL)" return 1 fi return 0 } # Function to check OSTree functionality check_ostree() { echo -e "\n๐ŸŒณ Checking OSTree functionality..." if command -v ostree >/dev/null 2>&1; then local version=$(ostree --version 2>/dev/null || echo "unknown") print_status "PASS" "ostree is available: $version" # Test basic ostree commands if ostree --help >/dev/null 2>&1; then print_status "PASS" "ostree --help works correctly" else print_status "FAIL" "ostree --help failed" return 1 fi else print_status "FAIL" "ostree is not available (CRITICAL)" return 1 fi return 0 } # Function to check filesystem structure check_filesystem_structure() { echo -e "\n๐Ÿ“ Checking OSTree filesystem structure..." local all_passed=true # Check required directories local required_dirs=( "/ostree" "/sysroot" "/usr/lib/ostree-boot" "/usr/lib/modules" "/usr/lib/kernel" "/etc/ostree" "/var/lib/ostree" "/var/home" ) for dir in "${required_dirs[@]}"; do if [ -d "$dir" ]; then print_status "PASS" "Directory exists: $dir" else print_status "FAIL" "Directory missing: $dir" all_passed=false fi done # Check home symlink if [ -L "/home" ] && [ "$(readlink /home)" = "../var/home" ]; then print_status "PASS" "Home symlink correctly points to /var/home" else print_status "FAIL" "Home symlink incorrect or missing" all_passed=false fi if [ "$all_passed" = "false" ]; then return 1 fi return 0 } # Function to check container runtime check_container_runtime() { echo -e "\n๐Ÿณ Checking container runtime..." if command -v podman >/dev/null 2>&1; then local version=$(podman --version 2>/dev/null || echo "unknown") print_status "PASS" "podman is available: $version" # Test podman functionality if podman --help >/dev/null 2>&1; then print_status "PASS" "podman --help works correctly" else print_status "FAIL" "podman --help failed" return 1 fi else print_status "FAIL" "podman is not available (CRITICAL)" return 1 fi return 0 } # Function to run deployment test test_deployment() { echo -e "\n๐Ÿงช Testing bootc deployment capabilities..." # Check if we're in a container if [ -f /.dockerenv ] || grep -q docker /proc/1/cgroup 2>/dev/null; then print_status "WARN" "Running in container - deployment test limited" echo "Note: Full deployment test requires host system access" return 0 fi # Check if we have access to block devices if [ -b /dev/sda ] || [ -b /dev/vda ]; then print_status "PASS" "Block devices accessible for deployment testing" else print_status "WARN" "No block devices accessible for deployment testing" fi # Check if we have sufficient privileges if [ "$(id -u)" -eq 0 ]; then print_status "PASS" "Running with root privileges for deployment" else print_status "WARN" "Not running with root privileges - some tests may fail" fi } # Main validation function main() { echo "Starting comprehensive validation..." local exit_code=0 # Run all checks check_path || exit_code=1 check_disk_utilities || exit_code=1 check_bootc || exit_code=1 check_ostree || exit_code=1 check_filesystem_structure || exit_code=1 check_container_runtime || exit_code=1 test_deployment || exit_code=1 # Summary echo -e "\n๐Ÿ“Š Validation Summary" echo "====================" if [ $exit_code -eq 0 ]; then echo -e "${GREEN}๐ŸŽ‰ All critical checks passed!${NC}" echo "Your Particle-OS image is ready for bootc deployment." echo "" echo "Next steps:" echo "1. Test image in VM: just test-image" echo "2. Validate boot process" echo "3. Test OSTree functionality" else echo -e "${RED}โŒ Some critical checks failed!${NC}" echo "Please fix the issues above before attempting deployment." echo "" echo "Common solutions:" echo "1. Install missing packages: apt install util-linux parted e2fsprogs dosfstools" echo "2. Fix PATH: export PATH=\"/usr/sbin:/sbin:\$PATH\"" echo "3. Ensure all Containerfile requirements are met" fi return $exit_code } # Run main function main "$@"