provisioning/bootstrap/install.nu
Jesús Pérez 44648e3206
chore: complete nickel migration and consolidate legacy configs
- Remove KCL ecosystem (~220 files deleted)
- Migrate all infrastructure to Nickel schema system
- Consolidate documentation: legacy docs → provisioning/docs/src/
- Add CI/CD workflows (.github/) and Rust build config (.cargo/)
- Update core system for Nickel schema parsing
- Update README.md and CHANGES.md for v5.0.0 release
- Fix pre-commit hooks: end-of-file, trailing-whitespace
- Breaking changes: KCL workspaces require migration
- Migration bridge available in docs/src/development/
2026-01-08 09:55:37 +00:00

284 lines
13 KiB
Plaintext

# provisioning/bootstrap/install.nu
# Main bootstrap orchestrator (NO Rust required)
# Receives project root via pipeline input
# Get project root from command-line argument or input
# In Nushell scripts, arguments are passed via input when using nu <script> <arg>
let project_root = $in | default (pwd)
print "╔════════════════════════════════════════════════════════════════╗"
print "║ PROVISIONING BOOTSTRAP (Nushell) ║"
print "╚════════════════════════════════════════════════════════════════╝"
print ""
# ════════════════════════════════════════════════════════════════════════
# STAGE 1: SYSTEM DETECTION
# ════════════════════════════════════════════════════════════════════════
print "📊 Stage 1: System Detection"
print "─────────────────────────────────────────────────────────────────"
let system_info = (sys)
let os_type = ($system_info | get host.os_family)
let arch = ($system_info | get host.arch)
let cpu_count = ($system_info | get cpu.physical_cores | default "unknown")
let mem_gb = (($system_info | get mem.total | default 0) / (1024 * 1024 * 1024) | math round)
print $" OS: ($os_type)"
print $" Architecture: ($arch)"
print $" CPU Cores: ($cpu_count)"
print $" Memory: ($mem_gb) GB"
# Validate minimum requirements
let min_ram_gb = 2
if ($mem_gb < $min_ram_gb) {
print $" ❌ ERROR: Requires at least ($min_ram_gb) GB RAM (have ($mem_gb) GB)"
exit 1
}
print " ✅ System requirements met"
print ""
# ════════════════════════════════════════════════════════════════════════
# STAGE 2: DEPENDENCY CHECK
# ════════════════════════════════════════════════════════════════════════
print "📦 Stage 2: Checking Dependencies"
print "─────────────────────────────────────────────────────────────────"
let required_tools = [
"git",
"docker",
"rustc",
"cargo",
"nu"
]
let missing_tools = ($required_tools | where {|tool|
(do { which $tool } | complete).exit_code != 0
})
if ($missing_tools | is-not-empty) {
print " ⚠️ Missing tools:"
$missing_tools | each {|tool| print $" - ($tool)"}
if ("docker" in $missing_tools) {
print ""
print " 📥 Docker is required. Install from: https://docs.docker.com/get-docker/"
}
if ("rustc" in $missing_tools) {
print ""
print " 📥 Rust is required. Install from: https://rustup.rs/"
print " Then run: rustup default stable"
}
print ""
print " ❌ Please install missing dependencies and run again"
exit 1
}
print " ✅ All dependencies found"
# Show versions
print ""
print " Versions:"
let docker_version = (do { docker --version } | complete | get stdout | str trim)
print $" Docker: ($docker_version)"
let rustc_version = (do { rustc --version } | complete | get stdout | str trim)
print $" Rust: ($rustc_version)"
let nu_version = (do { nu --version } | complete | get stdout | str trim)
print $" Nushell: ($nu_version)"
print ""
# ════════════════════════════════════════════════════════════════════════
# STAGE 3: CREATE DIRECTORY STRUCTURE
# ════════════════════════════════════════════════════════════════════════
print "📁 Stage 3: Creating Directory Structure"
print "─────────────────────────────────────────────────────────────────"
let workspace_name = "workspace_librecloud"
let workspace_path = ($project_root | path join $workspace_name)
# Create directories
mkdir ($workspace_path | path join "config" | path join "generated" | path join "providers") 2>/dev/null | null
mkdir ($workspace_path | path join "config" | path join "generated" | path join "platform") 2>/dev/null | null
mkdir ($workspace_path | path join ".orchestrator" | path join "data" | path join "queue") 2>/dev/null | null
mkdir ($workspace_path | path join ".kms") 2>/dev/null | null
mkdir ($workspace_path | path join ".providers") 2>/dev/null | null
mkdir ($workspace_path | path join ".taskservs") 2>/dev/null | null
mkdir ($workspace_path | path join ".clusters") 2>/dev/null | null
print " ✅ Directory structure created"
print ""
# ════════════════════════════════════════════════════════════════════════
# STAGE 4: VALIDATE CONFIGURATION
# ════════════════════════════════════════════════════════════════════════
print "⚙️ Stage 4: Validating Configuration"
print "─────────────────────────────────────────────────────────────────"
let config_ncl = ($workspace_path | path join "config" | path join "config.ncl")
if not ($config_ncl | path exists) {
print " ⚠️ config.ncl not found at ($config_ncl)"
print " Creating default config..."
# Use existing config.ncl if available
let template = ($project_root | path join "workspace_librecloud" | path join "config" | path join "config.ncl")
if ($template | path exists) {
cp $template $config_ncl
print " ✅ Copied from template"
} else {
print " ❌ ERROR: Cannot find config template"
exit 1
}
}
# Validate Nickel syntax
let typecheck_result = (do { nickel typecheck $config_ncl } | complete)
if $typecheck_result.exit_code != 0 {
print " ❌ Nickel configuration validation failed:"
print $typecheck_result.stderr
exit 1
}
print " ✅ Configuration syntax valid"
print ""
# ════════════════════════════════════════════════════════════════════════
# STAGE 5: EXPORT CONFIGURATION
# ════════════════════════════════════════════════════════════════════════
print "📤 Stage 5: Exporting Configuration to TOML"
print "─────────────────────────────────────────────────────────────────"
# Change to project root to enable module imports
cd $project_root
# Use provisioning config export CLI command
let export_result = (do {
nu -c $"use provisioning/core/nulib/lib_provisioning/config/export.nu *; export-all-configs ($workspace_path)"
} | complete)
if $export_result.exit_code == 0 {
print " ✅ Configuration exported"
} else {
print " ⚠️ Export output:"
print $export_result.stdout
}
print ""
# ════════════════════════════════════════════════════════════════════════
# STAGE 6: INITIALIZE ORCHESTRATOR
# ════════════════════════════════════════════════════════════════════════
print "🚀 Stage 6: Initializing Orchestrator Service"
print "─────────────────────────────────────────────────────────────────"
let orchestrator_path = ($project_root | path join "provisioning" | path join "platform" | path join "orchestrator")
if ($orchestrator_path | path exists) {
print " Starting orchestrator service in background..."
let start_result = (do {
cd $orchestrator_path
./scripts/start-orchestrator.nu --background --provisioning-path ($project_root | path join "provisioning" | path join "core" | path join "cli" | path join "provisioning")
} | complete)
if $start_result.exit_code == 0 {
print " ✅ Orchestrator started"
print " 📝 Check logs: tail -f ($orchestrator_path)/data/orchestrator.log"
} else {
print " ⚠️ Orchestrator start note:"
print $start_result.stdout
if ($start_result.stderr | is-not-empty) {
print $start_result.stderr
}
}
} else {
print " ⚠️ Orchestrator not found at ($orchestrator_path)"
}
print ""
# ════════════════════════════════════════════════════════════════════════
# STAGE 7: VERIFY INSTALLATION
# ════════════════════════════════════════════════════════════════════════
print "✅ Stage 7: Verification"
print "─────────────────────────────────────────────────────────────────"
# Check generated files
let files_check = [
"config/generated/workspace.toml",
"config/generated/providers/upcloud.toml",
"config/generated/platform/orchestrator.toml"
]
let missing_files = ($files_check | where {|f|
not (($workspace_path | path join $f) | path exists)
})
if ($missing_files | is-not-empty) {
print " ⚠️ Missing generated files:"
$missing_files | each {|f| print $" - ($f)"}
} else {
print " ✅ All configuration files generated"
}
# Check directories
let directories = [
".orchestrator/data/queue",
".kms",
".providers",
".taskservs",
".clusters"
]
let all_dirs_exist = ($directories | all {|d|
($workspace_path | path join $d) | path exists
})
if $all_dirs_exist {
print " ✅ All required directories created"
} else {
print " ⚠️ Some directories missing"
}
print ""
# ════════════════════════════════════════════════════════════════════════
# FINAL STATUS
# ════════════════════════════════════════════════════════════════════════
print "╔════════════════════════════════════════════════════════════════╗"
print "║ BOOTSTRAP COMPLETE ✅ ║"
print "╚════════════════════════════════════════════════════════════════╝"
print ""
print "📍 Next Steps:"
print ""
print "1. Verify configuration:"
print $" cat ($workspace_path)/config/config.ncl"
print ""
print "2. Check orchestrator is running:"
print " curl http://localhost:9090/health"
print ""
print "3. Start provisioning:"
print " provisioning server create --infra sgoyol --name web-01"
print ""
print "4. Monitor workflow:"
print " provisioning workflow monitor <workflow_id>"
print ""
print "📚 Documentation:"
print " - User Guide: docs/user/TYPEDIALOG_PLATFORM_CONFIG_GUIDE.md"
print " - Architecture: ARCHITECTURE_CLARIFICATION.md"
print " - Workflow: PROVISIONING_WORKFLOW.md"
print ""