particle-os-tools/src/apt-layer/compile.sh
robojerk 74c7bede5f Initial commit: Particle-OS tools repository
- Complete Particle-OS rebranding from uBlue-OS
- Professional installation system with standardized paths
- Self-initialization system with --init and --reset commands
- Enhanced error messages and dependency checking
- Comprehensive testing infrastructure
- All source scriptlets updated with runtime improvements
- Clean codebase with redundant files moved to archive
- Complete documentation suite
2025-07-11 21:14:33 -07:00

593 lines
23 KiB
Bash

#!/bin/bash
# Particle-OS apt-layer Compiler
# Merges multiple scriptlets into a single self-contained apt-layer.sh
# Based on ParticleOS installer compile.sh and ComposeFS compile.sh
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m'
# Function to print colored output
print_status() {
echo -e "${GREEN}[INFO]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
print_header() {
echo -e "${BLUE}================================${NC}"
echo -e "${BLUE}$1${NC}"
echo -e "${BLUE}================================${NC}"
}
# Function to show progress
update_progress() {
local status_message="$1"
local percent="$2"
local activity="${3:-Compiling}"
echo -e "${CYAN}[$activity]${NC} $status_message (${percent}%)"
}
# Check dependencies
check_dependencies() {
local missing_deps=()
# Check for jq (required for JSON processing)
if ! command -v jq &> /dev/null; then
missing_deps+=("jq")
fi
# Check for bash (required for syntax validation)
if ! command -v bash &> /dev/null; then
missing_deps+=("bash")
fi
# Check for dos2unix (for Windows line ending conversion)
if ! command -v dos2unix &> /dev/null; then
# Check if our custom dos2unix.sh exists
if [[ ! -f "$(dirname "$SCRIPT_DIR")/../dos2unix.sh" ]]; then
missing_deps+=("dos2unix")
fi
fi
if [[ ${#missing_deps[@]} -gt 0 ]]; then
print_error "Missing required dependencies: ${missing_deps[*]}"
print_error "Please install missing packages and try again"
exit 1
fi
print_status "All dependencies found"
}
# Validate JSON files
validate_json_files() {
local config_dir="$1"
if [[ -d "$config_dir" ]]; then
print_status "Validating JSON files in $config_dir"
local json_files=($(find "$config_dir" -name "*.json" -type f))
for json_file in "${json_files[@]}"; do
# Convert line endings before validation
convert_line_endings "$json_file"
if ! jq empty "$json_file" 2>/dev/null; then
print_error "Invalid JSON in file: $json_file"
exit 1
fi
print_status "✓ Validated: $json_file"
done
fi
}
# Convert Windows line endings to Unix line endings
convert_line_endings() {
local file="$1"
local dos2unix_cmd=""
# Try to use system dos2unix first
if command -v dos2unix &> /dev/null; then
dos2unix_cmd="dos2unix"
elif [[ -f "$(dirname "$SCRIPT_DIR")/../dos2unix.sh" ]]; then
dos2unix_cmd="$(dirname "$SCRIPT_DIR")/../dos2unix.sh"
# Make sure our dos2unix.sh is executable
chmod +x "$dos2unix_cmd" 2>/dev/null || true
else
print_warning "dos2unix not available, skipping line ending conversion for: $file"
return 0
fi
# Check if file has Windows line endings
if grep -q $'\r' "$file" 2>/dev/null; then
print_status "Converting Windows line endings to Unix: $file"
if "$dos2unix_cmd" -q "$file"; then
print_status "✓ Converted: $file"
else
print_warning "Failed to convert line endings for: $file"
fi
fi
}
# Get script directory and project root
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SCRIPTLETS_DIR="$SCRIPT_DIR/scriptlets"
TEMP_DIR="$SCRIPT_DIR/temp"
# Parse command line arguments
OUTPUT_FILE="$(dirname "$SCRIPT_DIR")/../apt-layer.sh" # Default output path
while [[ $# -gt 0 ]]; do
case $1 in
-o|--output)
OUTPUT_FILE="$2"
shift 2
;;
-h|--help)
echo "Usage: $0 [-o|--output OUTPUT_PATH]"
echo " -o, --output Specify output file path (default: ../apt-layer.sh)"
echo " -h, --help Show this help message"
exit 0
;;
*)
print_error "Unknown option: $1"
echo "Use -h or --help for usage information"
exit 1
;;
esac
done
# Ensure output directory exists
OUTPUT_DIR="$(dirname "$OUTPUT_FILE")"
if [[ ! -d "$OUTPUT_DIR" ]]; then
print_status "Creating output directory: $OUTPUT_DIR"
mkdir -p "$OUTPUT_DIR"
fi
print_header "Particle-OS apt-layer Compiler"
# Check dependencies first
check_dependencies
# Check if scriptlets directory exists
if [[ ! -d "$SCRIPTLETS_DIR" ]]; then
print_error "Scriptlets directory not found: $SCRIPTLETS_DIR"
exit 1
fi
# Validate JSON files if config directory exists
if [[ -d "$SCRIPT_DIR/config" ]]; then
validate_json_files "$SCRIPT_DIR/config"
fi
# Create temporary directory
rm -rf "$TEMP_DIR"
mkdir -p "$TEMP_DIR"
# Variable to sync between sections
update_progress "Pre-req: Creating temporary directory" 0
# Create the script in memory
script_content=()
# Add header
update_progress "Adding: Header" 5
header="#!/bin/bash
################################################################################################################
# #
# WARNING: This file is automatically generated #
# DO NOT modify this file directly as it will be overwritten #
# #
# Particle-OS apt-layer Tool #
# Generated on: $(date '+%Y-%m-%d %H:%M:%S') #
# #
################################################################################################################
set -euo pipefail
# Particle-OS apt-layer Tool - Self-contained version
# This script contains all components merged into a single file
# Enhanced version with container support, multiple package managers, and LIVE SYSTEM LAYERING
# Inspired by Vanilla OS Apx approach, ParticleOS apt-layer, and rpm-ostree live layering
"
script_content+=("$header")
# Add version info
update_progress "Adding: Version" 10
version_info="# Version: $(date '+%y.%m.%d')
# Particle-OS apt-layer Tool
# Enhanced with Container Support and LIVE SYSTEM LAYERING
"
script_content+=("$version_info")
# Add fallback logging functions (always defined first)
update_progress "Adding: Fallback Logging" 11
fallback_logging="# Fallback logging functions (always defined first)
# Color definitions
RED='\\033[0;31m'
GREEN='\\033[0;32m'
YELLOW='\\033[1;33m'
BLUE='\\033[0;34m'
CYAN='\\033[0;36m'
PURPLE='\\033[0;35m'
NC='\\033[0m'
log_info() {
local message=\"\$1\"
local script_name=\"\${2:-apt-layer}\"
echo -e \"\${BLUE}[INFO]\${NC} [\$script_name] \$message\"
}
log_debug() {
local message=\"\$1\"
local script_name=\"\${2:-apt-layer}\"
echo -e \"\${YELLOW}[DEBUG]\${NC} [\$script_name] \$message\"
}
log_error() {
local message=\"\$1\"
local script_name=\"\${2:-apt-layer}\"
echo -e \"\${RED}[ERROR]\${NC} [\$script_name] \$message\" >&2
}
log_warning() {
local message=\"\$1\"
local script_name=\"\${2:-apt-layer}\"
echo -e \"\${YELLOW}[WARNING]\${NC} [\$script_name] \$message\" >&2
}
log_success() {
local message=\"\$1\"
local script_name=\"\${2:-apt-layer}\"
echo -e \"\${GREEN}[SUCCESS]\${NC} [\$script_name] \$message\"
}
log_layer() {
local message=\"\$1\"
local script_name=\"\${2:-apt-layer}\"
echo -e \"\${PURPLE}[LAYER]\${NC} [\$script_name] \$message\"
}
log_transaction() {
local message=\"\$1\"
local script_name=\"\${2:-apt-layer}\"
echo -e \"\${CYAN}[TRANSACTION]\${NC} [\$script_name] \$message\"
}
"
script_content+=("$fallback_logging")
# Add Particle-OS configuration sourcing
update_progress "Adding: Configuration Sourcing" 12
config_sourcing="# Source Particle-OS configuration (if available, skip for help commands)
# Skip configuration loading for help commands to avoid permission issues
if [[ \"\${1:-}\" != \"--help\" && \"\${1:-}\" != \"-h\" && \"\${1:-}\" != \"--help-full\" && \"\${1:-}\" != \"--examples\" ]]; then
if [[ -f \"/usr/local/etc/particle-config.sh\" ]]; then
source \"/usr/local/etc/particle-config.sh\"
log_info \"Loaded Particle-OS configuration\" \"apt-layer\"
else
log_warning \"Particle-OS configuration not found, using defaults\" \"apt-layer\"
fi
else
log_info \"Skipping configuration loading for help command\" \"apt-layer\"
fi
"
script_content+=("$config_sourcing")
# Function to add scriptlet content with error handling
add_scriptlet() {
local scriptlet_name="$1"
local scriptlet_file="$SCRIPTLETS_DIR/$scriptlet_name"
local description="$2"
local is_critical="${3:-false}"
if [[ -f "$scriptlet_file" ]]; then
print_status "Including $scriptlet_name"
# Convert line endings before processing
convert_line_endings "$scriptlet_file"
script_content+=("# ============================================================================")
script_content+=("# $description")
script_content+=("# ============================================================================")
# Read and add scriptlet content, excluding the shebang if present
local content
if head -1 "$scriptlet_file" | grep -q "^#!/"; then
content=$(tail -n +2 "$scriptlet_file")
else
content=$(cat "$scriptlet_file")
fi
script_content+=("$content")
script_content+=("")
script_content+=("# --- END OF SCRIPTLET: $scriptlet_name ---")
script_content+=("")
else
if [[ "$is_critical" == "true" ]]; then
print_error "CRITICAL: $scriptlet_name not found - compilation cannot continue"
exit 1
else
print_warning "$scriptlet_name not found, skipping"
fi
fi
}
# Add scriptlets in logical dependency order
update_progress "Adding: Header and Shared Functions" 13
add_scriptlet "00-header.sh" "Header and Shared Functions" "true"
update_progress "Adding: Dependencies" 16
add_scriptlet "01-dependencies.sh" "Dependency Checking and Validation" "true"
update_progress "Adding: Transaction Management" 21
add_scriptlet "02-transactions.sh" "Transaction Management" "true"
update_progress "Adding: Traditional Layer Creation" 26
add_scriptlet "03-traditional.sh" "Traditional Layer Creation"
update_progress "Adding: Container-based Layer Creation" 31
add_scriptlet "04-container.sh" "Container-based Layer Creation (Apx-style)"
update_progress "Adding: OCI Integration" 36
add_scriptlet "06-oci-integration.sh" "OCI Export/Import Integration"
update_progress "Adding: Atomic Deployment System" 41
add_scriptlet "09-atomic-deployment.sh" "Atomic Deployment System"
update_progress "Adding: rpm-ostree Compatibility" 46
add_scriptlet "10-rpm-ostree-compat.sh" "rpm-ostree Compatibility Layer"
update_progress "Adding: Live Overlay System" 51
add_scriptlet "05-live-overlay.sh" "Live Overlay System (rpm-ostree style)"
update_progress "Adding: Bootloader Integration" 56
add_scriptlet "07-bootloader.sh" "Bootloader Integration (UEFI/GRUB/systemd-boot)"
update_progress "Adding: Advanced Package Management" 61
add_scriptlet "08-advanced-package-management.sh" "Advanced Package Management (Enterprise Features)"
update_progress "Adding: Layer Signing & Verification" 66
add_scriptlet "11-layer-signing.sh" "Layer Signing & Verification (Enterprise Security)"
update_progress "Adding: Centralized Audit & Reporting" 71
add_scriptlet "12-audit-reporting.sh" "Centralized Audit & Reporting (Enterprise Compliance)"
update_progress "Adding: Automated Security Scanning" 76
add_scriptlet "13-security-scanning.sh" "Automated Security Scanning (Enterprise Security)"
update_progress "Adding: Admin Utilities" 81
add_scriptlet "14-admin-utilities.sh" "Admin Utilities (Health Monitoring, Analytics, Maintenance)"
update_progress "Adding: Multi-Tenant Support" 86
add_scriptlet "15-multi-tenant.sh" "Multi-Tenant Support (Enterprise Features)"
update_progress "Adding: Advanced Compliance Frameworks" 87
add_scriptlet "16-compliance-frameworks.sh" "Advanced Compliance Frameworks (Enterprise Features)"
update_progress "Adding: Enterprise Integration" 88
add_scriptlet "17-enterprise-integration.sh" "Enterprise Integration (Enterprise Features)"
update_progress "Adding: Advanced Monitoring & Alerting" 89
add_scriptlet "18-monitoring-alerting.sh" "Advanced Monitoring & Alerting (Enterprise Features)"
update_progress "Adding: Cloud Integration" 90
add_scriptlet "19-cloud-integration.sh" "Cloud Integration (AWS, Azure, GCP)"
update_progress "Adding: Kubernetes Integration" 91
add_scriptlet "20-kubernetes-integration.sh" "Kubernetes Integration (EKS, AKS, GKE, OpenShift)"
update_progress "Adding: Container Orchestration" 92
add_scriptlet "21-container-orchestration.sh" "Container Orchestration (Multi-cluster, Service Mesh, GitOps)"
update_progress "Adding: Multi-Cloud Deployment" 93
add_scriptlet "22-multicloud-deployment.sh" "Multi-Cloud Deployment (AWS, Azure, GCP, Migration, Policies)"
update_progress "Adding: Cloud-Native Security" 94
add_scriptlet "23-cloud-security.sh" "Cloud-Native Security (Workload Scanning, Policy Enforcement, Compliance)"
update_progress "Adding: Direct dpkg Installation" 95
add_scriptlet "24-dpkg-direct-install.sh" "Direct dpkg Installation (Performance Optimization)"
update_progress "Adding: Main Dispatch" 96
add_scriptlet "99-main.sh" "Main Dispatch and Help" "true"
# Add embedded configuration files if they exist
update_progress "Adding: Embedded Configuration" 98
if [[ -d "$SCRIPT_DIR/config" ]]; then
script_content+=("# ============================================================================")
script_content+=("# Embedded Configuration Files")
script_content+=("# ============================================================================")
script_content+=("")
script_content+=("# Enterprise-grade JSON configuration system")
script_content+=("# All configuration files are embedded for self-contained operation")
script_content+=("# Configuration can be overridden via command-line arguments")
script_content+=("")
# Find and embed JSON files
json_files=($(find "$SCRIPT_DIR/config" -name "*.json" -type f | sort))
# Add configuration summary
script_content+=("# Configuration files to be embedded:")
for json_file in "${json_files[@]}"; do
filename=$(basename "$json_file" .json)
script_content+=("# - $filename.json")
done
script_content+=("")
for json_file in "${json_files[@]}"; do
filename=$(basename "$json_file" .json)
# Convert filename to valid variable name (replace hyphens with underscores)
variable_name=$(echo "${filename^^}" | tr '-' '_')"_CONFIG"
print_status "Processing configuration: $filename"
# Check file size first
file_size=$(stat -c%s "$json_file" 2>/dev/null || echo "0")
# For very large files (>5MB), suggest external loading
if [[ $file_size -gt 5242880 ]]; then # 5MB
print_warning "Very large configuration file detected ($(numfmt --to=iec $file_size)): $json_file"
print_warning "Consider using external file loading for better performance"
print_warning "This file will be embedded but may impact script startup time"
# Add external loading option as comment
script_content+=("# Large configuration file: $filename")
script_content+=("# Consider using external loading for better performance")
script_content+=("# Example: load_config_from_file \"$filename\"")
elif [[ $file_size -gt 1048576 ]]; then # 1MB
print_warning "Large configuration file detected ($(numfmt --to=iec $file_size)): $json_file"
fi
# Convert line endings before processing
convert_line_endings "$json_file"
# Validate JSON before processing
if ! jq '.' "$json_file" >> /dev/null; then
print_error "Invalid JSON in configuration file: $json_file"
exit 1
fi
# Embed with safety comment
script_content+=("# Embedded configuration: $filename")
script_content+=("# File size: $(numfmt --to=iec $file_size)")
script_content+=("$variable_name=\$(cat << 'EOF'")
# Use jq to ensure safe JSON output (prevents shell injection)
script_content+=("$(jq -r '.' "$json_file")")
script_content+=("EOF")
script_content+=(")")
script_content+=("")
done
# Add external loading function for future use
script_content+=("# ============================================================================")
script_content+=("# External Configuration Loading (Future Enhancement)")
script_content+=("# ============================================================================")
script_content+=("")
script_content+=("# Function to load configuration from external files")
script_content+=("# Usage: load_config_from_file \"config-name\"")
script_content+=("load_config_from_file() {")
script_content+=(" local config_name=\"\$1\"")
script_content+=(" local config_file=\"/etc/apt-layer/config/\${config_name}.json\"")
script_content+=(" if [[ -f \"\$config_file\" ]]; then")
script_content+=(" jq -r '.' \"\$config_file\"")
script_content+=(" else")
script_content+=(" log_error \"Configuration file not found: \$config_file\" \"apt-layer\"")
script_content+=(" exit 1")
script_content+=(" fi")
script_content+=("}")
script_content+=("")
fi
# Add main function call
script_content+=("# ============================================================================")
script_content+=("# Main Execution")
script_content+=("# ============================================================================")
script_content+=("")
script_content+=("# Run main function if script is executed directly")
script_content+=("if [[ \"\${BASH_SOURCE[0]}\" == \"\${0}\" ]]; then")
script_content+=(" main \"\$@\"")
script_content+=("fi")
# Write the compiled script
update_progress "Writing: Compiled script" 99
printf '%s\n' "${script_content[@]}" > "$OUTPUT_FILE"
# Make it executable
chmod +x "$OUTPUT_FILE"
# Validate the script
update_progress "Validating: Script syntax" 100
if bash -n "$OUTPUT_FILE"; then
print_status "Syntax validation passed"
else
print_error "Syntax validation failed"
print_error "Removing invalid script: $OUTPUT_FILE"
rm -f "$OUTPUT_FILE"
exit 1
fi
# Clean up
rm -rf "$TEMP_DIR"
print_header "Compilation Complete!"
print_status "Output file: $OUTPUT_FILE"
print_status "File size: $(du -h "$OUTPUT_FILE" | cut -f1)"
print_status "Lines of code: $(wc -l < "$OUTPUT_FILE")"
print_status ""
print_status "The compiled apt-layer.sh is now self-contained and includes:"
print_status "✅ Particle-OS configuration integration"
print_status "✅ Transactional operations with automatic rollback"
print_status "✅ Traditional chroot-based layer creation"
print_status "✅ Container-based layer creation (Apx-style)"
print_status "✅ OCI export/import integration"
print_status "✅ Live overlay system (rpm-ostree style)"
print_status "✅ Bootloader integration (UEFI/GRUB/systemd-boot)"
print_status "✅ Advanced package management (Enterprise features)"
print_status "✅ Layer signing & verification (Enterprise security)"
print_status "✅ Centralized audit & reporting (Enterprise compliance)"
print_status "✅ Automated security scanning (Enterprise security)"
print_status "✅ Admin utilities (Health monitoring, performance analytics, maintenance)"
print_status "✅ Multi-tenant support (Enterprise features)"
print_status "✅ Atomic deployment system with rollback"
print_status "✅ rpm-ostree compatibility layer (1:1 command mapping)"
print_status "✅ ComposeFS backend integration"
print_status "✅ Dependency validation and error handling"
print_status "✅ Comprehensive JSON configuration system"
print_status "✅ Direct dpkg installation (Performance optimization)"
print_status "✅ All dependencies merged into a single file"
print_status ""
print_status "🎉 Particle-OS apt-layer compilation complete with all features!"
print_status ""
print_status "Usage:"
print_status " sudo ./apt-layer.sh particle-os/base/24.04 particle-os/gaming/24.04 steam wine"
print_status " sudo ./apt-layer.sh --container particle-os/base/24.04 particle-os/dev/24.04 vscode git"
print_status " sudo ./apt-layer.sh --live-overlay start"
print_status " sudo ./apt-layer.sh --live-install steam wine"
print_status " sudo ./apt-layer.sh --live-overlay commit \"Add gaming packages\""
print_status " sudo ./apt-layer.sh kargs add \"console=ttyS0\""
print_status " sudo ./apt-layer.sh kargs list"
print_status " sudo ./apt-layer.sh --advanced-install steam wine"
print_status " sudo ./apt-layer.sh --advanced-remove package-name"
print_status " sudo ./apt-layer.sh --add-user username package_manager"
print_status " sudo ./apt-layer.sh --list-users"
print_status " sudo ./apt-layer.sh --generate-key my-signing-key sigstore"
print_status " sudo ./apt-layer.sh --sign-layer layer.squashfs my-signing-key"
print_status " sudo ./apt-layer.sh --verify-layer layer.squashfs"
print_status " sudo ./apt-layer.sh --query-audit json --user=admin --since=2024-01-01"
print_status " sudo ./apt-layer.sh --export-audit csv --output=audit-export.csv"
print_status " sudo ./apt-layer.sh --generate-compliance-report sox monthly html"
print_status " sudo ./apt-layer.sh --audit-status"
print_status " sudo ./apt-layer.sh --scan-package package-name"
print_status " sudo ./apt-layer.sh --scan-layer layer.squashfs"
print_status " sudo ./apt-layer.sh --generate-security-report package html"
print_status " sudo ./apt-layer.sh --security-status"
print_status " sudo ./apt-layer.sh --update-cve-database"
print_status " sudo ./apt-layer.sh --dpkg-install curl wget"
print_status " sudo ./apt-layer.sh --container-dpkg base-image new-image packages"
print_status " sudo ./apt-layer.sh --live-dpkg firefox"
print_status " sudo ./apt-layer.sh admin health"
print_status " sudo ./apt-layer.sh admin perf"
print_status " sudo ./apt-layer.sh admin cleanup --dry-run --days 30"
print_status " sudo ./apt-layer.sh admin backup"
print_status " sudo ./apt-layer.sh admin restore"
print_status " sudo ./apt-layer.sh --list"
print_status " sudo ./apt-layer.sh --help"
print_status ""
print_status "Ready for distribution! 🚀"