#!/usr/bin/env bash # provisioning/bootstrap/install.sh # Bootstrap script for provisioning platform (POSIX Bash + Nushell) # Pure Bash implementation to avoid Nushell IR mode limitations set -e # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # Configuration SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" WORKSPACE_NAME="workspace_librecloud" WORKSPACE_PATH="$PROJECT_ROOT/$WORKSPACE_NAME" # Helper functions print_header() { echo -e "${GREEN}╔════════════════════════════════════════════════════════════════╗${NC}" echo -e "${GREEN}║ PROVISIONING BOOTSTRAP (Bash) ║${NC}" echo -e "${GREEN}╚════════════════════════════════════════════════════════════════╝${NC}" } print_stage() { local stage="$1" local description="$2" echo "" echo "$stage $description" echo "─────────────────────────────────────────────────────────────────" } print_success() { echo " ✅ $1" } print_warning() { echo " ⚠️ $1" } print_error() { echo " ❌ $1" } check_command() { command -v "$1" &> /dev/null } # Main bootstrap logic print_header echo "" # ════════════════════════════════════════════════════════════════════════ # STAGE 1: SYSTEM DETECTION # ════════════════════════════════════════════════════════════════════════ print_stage "📊" "Stage 1: System Detection" OS=$(uname -s) ARCH=$(uname -m) CPU_COUNT=$(sysctl -n hw.physicalcpu 2>/dev/null || nproc 2>/dev/null || echo "unknown") # Get RAM in GB if [[ "$OS" == "Darwin" ]]; then MEM_GB=$(($(sysctl -n hw.memsize) / 1024 / 1024 / 1024)) else MEM_GB=$(($(grep MemTotal /proc/meminfo | awk '{print $2}') / 1024 / 1024)) fi echo " OS: $OS" echo " Architecture: $ARCH" echo " CPU Cores: $CPU_COUNT" echo " Memory: ${MEM_GB} GB" # Validate minimum requirements MIN_RAM=2 if [[ $MEM_GB -lt $MIN_RAM ]]; then print_error "Requires at least $MIN_RAM GB RAM (have $MEM_GB GB)" exit 1 fi print_success "System requirements met" # ════════════════════════════════════════════════════════════════════════ # STAGE 2: DEPENDENCY CHECK # ════════════════════════════════════════════════════════════════════════ print_stage "📦" "Stage 2: Checking Dependencies" REQUIRED_TOOLS=("git" "docker" "rustc" "cargo" "nu") MISSING_TOOLS=() for tool in "${REQUIRED_TOOLS[@]}"; do if ! check_command "$tool"; then MISSING_TOOLS+=("$tool") fi done if [[ ${#MISSING_TOOLS[@]} -gt 0 ]]; then print_warning "Missing tools:" for tool in "${MISSING_TOOLS[@]}"; do echo " - $tool" done if [[ " ${MISSING_TOOLS[*]} " =~ " docker " ]]; then echo "" echo " 📥 Docker is required. Install from: https://docs.docker.com/get-docker/" fi if [[ " ${MISSING_TOOLS[*]} " =~ " rustc " ]]; then echo "" echo " 📥 Rust is required. Install from: https://rustup.rs/" echo " Then run: rustup default stable" fi echo "" print_error "Please install missing dependencies and run again" exit 1 fi print_success "All dependencies found" # Show versions echo "" echo " Versions:" echo " Docker: $(docker --version)" echo " Rust: $(rustc --version)" echo " Nushell: $(nu --version)" # ════════════════════════════════════════════════════════════════════════ # STAGE 3: CREATE DIRECTORY STRUCTURE # ════════════════════════════════════════════════════════════════════════ print_stage "📁" "Stage 3: Creating Directory Structure" mkdir -p "$WORKSPACE_PATH/config/generated/providers" mkdir -p "$WORKSPACE_PATH/config/generated/platform" mkdir -p "$WORKSPACE_PATH/.orchestrator/data/queue" mkdir -p "$WORKSPACE_PATH/.kms" mkdir -p "$WORKSPACE_PATH/.providers" mkdir -p "$WORKSPACE_PATH/.taskservs" mkdir -p "$WORKSPACE_PATH/.clusters" print_success "Directory structure created" # ════════════════════════════════════════════════════════════════════════ # STAGE 4: VALIDATE CONFIGURATION # ════════════════════════════════════════════════════════════════════════ print_stage "⚙️ " "Stage 4: Validating Configuration" CONFIG_NCL="$WORKSPACE_PATH/config/config.ncl" if [[ ! -f "$CONFIG_NCL" ]]; then print_warning "config.ncl not found at $CONFIG_NCL" echo " Creating default config..." TEMPLATE="$PROJECT_ROOT/workspace_librecloud/config/config.ncl" if [[ -f "$TEMPLATE" ]]; then cp "$TEMPLATE" "$CONFIG_NCL" print_success "Copied from template" else print_error "Cannot find config template" exit 1 fi fi # Validate Nickel syntax if ! nickel typecheck "$CONFIG_NCL" > /dev/null 2>&1; then print_error "Nickel configuration validation failed" nickel typecheck "$CONFIG_NCL" exit 1 fi print_success "Configuration syntax valid" # ════════════════════════════════════════════════════════════════════════ # STAGE 5: EXPORT CONFIGURATION # ════════════════════════════════════════════════════════════════════════ print_stage "📤" "Stage 5: Exporting Configuration to TOML" cd "$PROJECT_ROOT" # Use Nushell for config export (IT requires module imports) if nu -c " use provisioning/core/nulib/lib_provisioning/config/export.nu * export-all-configs '$WORKSPACE_PATH' " 2>/dev/null; then print_success "Configuration exported" else print_warning "Configuration export encountered issues (may continue)" fi # ════════════════════════════════════════════════════════════════════════ # STAGE 6: INITIALIZE ORCHESTRATOR # ════════════════════════════════════════════════════════════════════════ print_stage "🚀" "Stage 6: Initializing Orchestrator Service" ORCHESTRATOR_PATH="$PROJECT_ROOT/provisioning/platform/orchestrator" if [[ -d "$ORCHESTRATOR_PATH" ]]; then echo " Starting orchestrator service in background..." if cd "$ORCHESTRATOR_PATH" && \ ./scripts/start-orchestrator.nu --background \ --provisioning-path "$PROJECT_ROOT/provisioning/core/cli/provisioning" 2>/dev/null; then print_success "Orchestrator started" echo " 📝 Check logs: tail -f $ORCHESTRATOR_PATH/data/orchestrator.log" else print_warning "Orchestrator may not have started (check logs)" fi else print_warning "Orchestrator not found at $ORCHESTRATOR_PATH" fi # ════════════════════════════════════════════════════════════════════════ # STAGE 7: VERIFY INSTALLATION # ════════════════════════════════════════════════════════════════════════ print_stage "✅" "Stage 7: Verification" FILES_CHECK=( "config/generated/workspace.toml" "config/generated/providers/upcloud.toml" "config/generated/platform/orchestrator.toml" ) MISSING_FILES=() for file in "${FILES_CHECK[@]}"; do if [[ ! -f "$WORKSPACE_PATH/$file" ]]; then MISSING_FILES+=("$file") fi done if [[ ${#MISSING_FILES[@]} -gt 0 ]]; then print_warning "Missing generated files:" for file in "${MISSING_FILES[@]}"; do echo " - $file" done else print_success "All configuration files generated" fi DIRECTORIES_CHECK=( ".orchestrator/data/queue" ".kms" ".providers" ".taskservs" ".clusters" ) ALL_DIRS_EXIST=true for dir in "${DIRECTORIES_CHECK[@]}"; do if [[ ! -d "$WORKSPACE_PATH/$dir" ]]; then ALL_DIRS_EXIST=false break fi done if $ALL_DIRS_EXIST; then print_success "All required directories created" else print_warning "Some directories missing" fi # ════════════════════════════════════════════════════════════════════════ # FINAL STATUS # ════════════════════════════════════════════════════════════════════════ echo "" echo -e "${GREEN}╔════════════════════════════════════════════════════════════════╗${NC}" echo -e "${GREEN}║ BOOTSTRAP COMPLETE ✅ ║${NC}" echo -e "${GREEN}╚════════════════════════════════════════════════════════════════╝${NC}" echo "" echo "📍 Next Steps:" echo "" echo "1. Verify configuration:" echo " cat $WORKSPACE_PATH/config/config.ncl" echo "" echo "2. Check orchestrator is running:" echo " curl http://localhost:9090/health" echo "" echo "3. Start provisioning:" echo " provisioning server create --infra sgoyol --name web-01" echo "" echo "4. Monitor workflow:" echo " provisioning workflow monitor " echo "" echo "📚 Documentation:" echo " - User Guide: docs/user/TYPEDIALOG_PLATFORM_CONFIG_GUIDE.md" echo " - Architecture: ARCHITECTURE_CLARIFICATION.md" echo " - Workflow: PROVISIONING_WORKFLOW.md" echo ""