284 lines
13 KiB
Plaintext
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 ""
|