# Platform Services Setup Module # Manages deployment and initialization of platform services (Orchestrator, Control Center, KMS) # Follows Nushell guidelines: explicit types, single purpose, no try-catch # Selective imports (ADR-025 Phase 3 Layer 2). # setup/validation.nu star-import was dead — dropped. use platform/setup/mod.nu [ get-config-base-path get-cpu-count get-system-memory-gb get-timestamp-iso8601 load-config-toml print-setup-error print-setup-header print-setup-info print-setup-success print-setup-warning save-config-toml ] use platform/setup/detection.nu [ has-docker has-docker-compose has-kubectl has-ssh has-systemd ] use platform/bootstrap.nu [bootstrap-platform] # ============================================================================ # DEPLOYMENT MODE VALIDATION # ============================================================================ # Validate deployment mode is supported export def validate-deployment-mode [ mode: string ] { let valid_modes = ["docker-compose", "kubernetes", "remote-ssh", "systemd"] let is_valid = ($mode | inside $valid_modes) { mode: $mode valid: $is_valid valid_modes: $valid_modes error: (if not $is_valid { $"Invalid deployment mode: ($mode)" } else { null }) } } # Check deployment mode support on current system export def check-deployment-mode-support [ mode: string ] { let support = (match $mode { "docker-compose" => { let docker_ok = (has-docker) let compose_ok = (has-docker-compose) { supported: ($docker_ok and $compose_ok) docker: $docker_ok docker_compose: $compose_ok reason: (if not $docker_ok { "Docker not installed" } else if not $compose_ok { "Docker Compose not found" } else { "OK" }) } } "kubernetes" => { let kubectl_ok = (has-kubectl) { supported: $kubectl_ok kubectl: $kubectl_ok reason: (if not $kubectl_ok { "kubectl not installed" } else { "OK" }) } } "remote-ssh" => { let ssh_ok = (has-ssh) { supported: $ssh_ok ssh: $ssh_ok reason: (if not $ssh_ok { "SSH not installed" } else { "OK" }) } } "systemd" => { let systemd_ok = (has-systemd) { supported: $systemd_ok systemd: $systemd_ok reason: (if not $systemd_ok { "systemd not available" } else { "OK" }) } } _ => { { supported: false reason: $"Unknown deployment mode: ($mode)" } } }) { mode: $mode support: $support } } # ============================================================================ # SERVICE PORT MANAGEMENT # ============================================================================ # Reserve ports for platform services export def reserve-service-ports [ orchestrator_port: int = 9090 control_center_port: int = 3000 kms_port: int = 3001 ] { mut reserved_ports = [] mut port_conflicts = [] # Check orchestrator port let orch_validation = (validate-port-available $orchestrator_port) if not $orch_validation.valid { $port_conflicts = ($port_conflicts | append $orch_validation.error) } else { $reserved_ports = ($reserved_ports | append {name: "orchestrator", port: $orchestrator_port}) } # Check control center port let cc_validation = (validate-port-available $control_center_port) if not $cc_validation.valid { $port_conflicts = ($port_conflicts | append $cc_validation.error) } else { $reserved_ports = ($reserved_ports | append {name: "control-center", port: $control_center_port}) } # Check KMS port let kms_validation = (validate-port-available $kms_port) if not $kms_validation.valid { $port_conflicts = ($port_conflicts | append $kms_validation.error) } else { $reserved_ports = ($reserved_ports | append {name: "kms-service", port: $kms_port}) } { reserved_ports: $reserved_ports, conflicts: $port_conflicts, all_available: (($port_conflicts | length) == 0) } } # ============================================================================ # PLATFORM SERVICES STARTUP # ============================================================================ # Bootstrap and start platform services export def start-platform-services [ deployment_mode: string --auto_start = true --verbose = false ] { # Validate deployment mode let mode_validation = (validate-deployment-mode $deployment_mode) if not $mode_validation.valid { print-setup-error $mode_validation.error return { success: false error: $mode_validation.error } } # Check deployment mode support let support_check = (check-deployment-mode-support $deployment_mode) if not $support_check.support.supported { print-setup-error $support_check.support.reason return { success: false error: $support_check.support.reason } } print-setup-info $"Starting platform services using ($deployment_mode) mode..." # Bootstrap services (from bootstrap.nu) let bootstrap_result = (do { bootstrap-platform --auto-start=$auto_start --verbose=$verbose --timeout=60 } | complete) if ($bootstrap_result.exit_code != 0) { print-setup-warning "Platform services bootstrap encountered issues" return { success: true warning: "Bootstrap completed with warnings" deployment_mode: $deployment_mode } } print-setup-success "Platform services started successfully" { success: true deployment_mode: $deployment_mode timestamp: (get-timestamp-iso8601) } } # ============================================================================ # SERVICE CONFIGURATION # ============================================================================ # Apply platform services configuration export def apply-platform-config [ config_base: string config_data: record ] { let deployment_config_path = $"($config_base)/platform/deployment.toml" # Load current deployment config if it exists let current_config = (do { if ($deployment_config_path | path exists) { load-config-toml $deployment_config_path } else { {} } } | complete) # Merge with new configuration let updated_config = ( if ($current_config.exit_code == 0) { $current_config.stdout | merge $config_data } else { $config_data } ) # Save updated configuration let save_result = (save-config-toml $deployment_config_path $updated_config) { success: $save_result config_path: $deployment_config_path timestamp: (get-timestamp-iso8601) } } # ============================================================================ # SERVICE VERIFICATION # ============================================================================ # Verify platform services are running export def verify-platform-services [] { let orch_health = (do { curl -s -f http://localhost:9090/health o> /dev/null e> /dev/null } | complete).exit_code == 0 let cc_health = (do { curl -s -f http://localhost:3000/health o> /dev/null e> /dev/null } | complete).exit_code == 0 let kms_health = (do { curl -s -f http://localhost:3001/health o> /dev/null e> /dev/null } | complete).exit_code == 0 { orchestrator: { running: $orch_health endpoint: "http://localhost:9090" } control_center: { running: $cc_health endpoint: "http://localhost:3000" } kms_service: { running: $kms_health endpoint: "http://localhost:3001" } all_healthy: ($orch_health and $cc_health and $kms_health) } } # ============================================================================ # PLATFORM SETUP MODES # ============================================================================ # Setup platform for solo development export def setup-platform-solo [ config_base: string --verbose = false ] { print-setup-header "Setting up Platform (Solo Mode)" print "" print "Solo mode: Single-user local development setup" print "" # Check Docker availability if not (has-docker) { print-setup-error "Docker is required for solo mode" return { success: false error: "Docker not installed" } } # Reserve ports let port_check = (reserve-service-ports) if not $port_check.all_available { print-setup-warning $"Port conflicts: ($port_check.conflicts | str join ', ')" } # Apply configuration let config_result = (apply-platform-config $config_base { deployment: { mode: "docker-compose" location_type: "local" } }) # Start services let start_result = (start-platform-services "docker-compose" --verbose=$verbose) { success: ($config_result.success and $start_result.success) mode: "solo" deployment: "docker-compose" timestamp: (get-timestamp-iso8601) } } # Setup platform for multi-user team export def setup-platform-multiuser [ config_base: string --verbose = false ] { print-setup-header "Setting up Platform (Multi-user Mode)" print "" print "Multi-user mode: Shared team environment" print "" # Check Docker Compose availability (preferred) let preferred_mode = if (has-docker-compose) { "docker-compose" } else if (has-kubectl) { "kubernetes" } else if (has-systemd) { "systemd" } else { "" } if ($preferred_mode == "") { print-setup-error "No suitable deployment method found for multi-user setup" return { success: false error: "Missing required tools" } } print-setup-info $"Using deployment mode: ($preferred_mode)" # Reserve ports let port_check = (reserve-service-ports) if not $port_check.all_available { print-setup-warning $"Port conflicts: ($port_check.conflicts | str join ', ')" } # Apply configuration let config_result = (apply-platform-config $config_base { deployment: { mode: $preferred_mode location_type: "local" } }) # Start services let start_result = (start-platform-services $preferred_mode --verbose=$verbose) { success: ($config_result.success and $start_result.success) mode: "multiuser" deployment: $preferred_mode timestamp: (get-timestamp-iso8601) } } # Setup platform for CI/CD export def setup-platform-cicd [ config_base: string --verbose = false ] { print-setup-header "Setting up Platform (CI/CD Mode)" print "" print "CI/CD mode: Automated deployment pipeline setup" print "" # Check Kubernetes availability let deployment_mode = if (has-kubectl) { "kubernetes" } else if (has-docker-compose) { "docker-compose" } else { "" } if ($deployment_mode == "") { print-setup-error "Kubernetes or Docker Compose required for CI/CD mode" return { success: false error: "Missing required tools" } } print-setup-info $"Using deployment mode: ($deployment_mode)" # Apply configuration let config_result = (apply-platform-config $config_base { deployment: { mode: $deployment_mode location_type: "local" } }) # Start services with longer timeouts let start_result = (start-platform-services $deployment_mode --verbose=$verbose) { success: ($config_result.success and $start_result.success) mode: "cicd" deployment: $deployment_mode timestamp: (get-timestamp-iso8601) } } # ============================================================================ # PROFILE-BASED SETUP (NICKEL-ALWAYS) # ============================================================================ # Setup platform for developer profile (fast, local, type-safe) export def setup-platform-developer [ config_base: string = "" --verbose = false ] { print-setup-header "Setting up Platform (Developer Profile)" print "" print "Developer profile: Fast local setup with type-safe Nickel validation" print "" let base = (if ($config_base == "") { (get-config-base-path) } else { $config_base }) # Check Docker availability if not (has-docker) { print-setup-error "Docker is required for developer profile" return { success: false error: "Docker not installed" } } print-setup-info "Generating Nickel platform configuration..." if not (create-platform-config-nickel $base "docker-compose" "developer") { print-setup-error "Failed to generate Nickel platform config" return { success: false error: "Failed to generate Nickel platform config" } } print-setup-info "Validating Nickel configuration..." let validation = (validate-nickel-config $"($base)/platform/deployment.ncl") if not $validation { print-setup-error "Nickel validation failed" return { success: false error: "Nickel validation failed" } } # Reserve ports let port_check = (reserve-service-ports) if not $port_check.all_available { print-setup-warning $"Port conflicts: ($port_check.conflicts | str join ', ')" } # Start services let start_result = (start-platform-services "docker-compose" --verbose=$verbose) { success: $start_result.success profile: "developer" deployment: "docker-compose" config_base: $base timestamp: (get-timestamp-iso8601) } } # Setup platform for production profile (validated, secure, HA) export def setup-platform-production [ config_base: string = "" --verbose = false ] { print-setup-header "Setting up Platform (Production Profile)" print "" print "Production profile: Validated deployment with security and HA" print "" let base = (if ($config_base == "") { (get-config-base-path) } else { $config_base }) # Check Kubernetes availability (preferred for production) let deployment_mode = if (has-kubectl) { "kubernetes" } else if (has-docker-compose) { "docker-compose" } else { "" } if ($deployment_mode == "") { print-setup-error "Kubernetes or Docker Compose required for production profile" return { success: false error: "Missing required tools" } } print-setup-info $"Using deployment mode: ($deployment_mode)" # Check Nickel is available for production-grade validation let nickel_check = (do { which nickel } | complete) if ($nickel_check.exit_code != 0) { print-setup-warning "Nickel not installed - validation will be skipped (recommended to install for production)" } print-setup-info "Generating Nickel platform configuration..." if not (create-platform-config-nickel $base $deployment_mode "production") { print-setup-error "Failed to generate Nickel platform config" return { success: false error: "Failed to generate Nickel platform config" } } print-setup-info "Validating Nickel configuration..." let validation = (validate-nickel-config $"($base)/platform/deployment.ncl") if not $validation { print-setup-error "Nickel validation failed" return { success: false error: "Nickel validation failed" } } # Pre-flight checks for production print-setup-info "Running production pre-flight checks..." let cpu_count = (get-cpu-count) let memory_gb = (get-system-memory-gb) if ($deployment_mode == "kubernetes") { if ($cpu_count < 4) { print-setup-warning "Production Kubernetes deployment recommended with at least 4 CPUs" } if ($memory_gb < 8) { print-setup-warning "Production Kubernetes deployment recommended with at least 8GB RAM" } } # Reserve ports let port_check = (reserve-service-ports) if not $port_check.all_available { print-setup-warning $"Port conflicts: ($port_check.conflicts | str join ', ')" } # Start services let start_result = (start-platform-services $deployment_mode --verbose=$verbose) { success: $start_result.success profile: "production" deployment: $deployment_mode config_base: $base timestamp: (get-timestamp-iso8601) } } # Setup platform for CI/CD profile (ephemeral, automated, fast) export def setup-platform-cicd-nickel [ config_base: string = "" --verbose = false ] { print-setup-header "Setting up Platform (CI/CD Profile)" print "" print "CI/CD profile: Ephemeral deployment for automated pipelines" print "" let base = (if ($config_base == "") { (get-config-base-path) } else { $config_base }) # Prefer Docker Compose for CI/CD (faster startup) let deployment_mode = if (has-docker-compose) { "docker-compose" } else if (has-kubectl) { "kubernetes" } else { "" } if ($deployment_mode == "") { print-setup-error "Docker Compose or Kubernetes required for CI/CD profile" return { success: false error: "Missing required tools" } } print-setup-info $"Using deployment mode: ($deployment_mode)" print-setup-info "Generating Nickel platform configuration..." if not (create-platform-config-nickel $base $deployment_mode "cicd") { print-setup-error "Failed to generate Nickel platform config" return { success: false error: "Failed to generate Nickel platform config" } } print-setup-info "Validating Nickel configuration..." let validation = (validate-nickel-config $"($base)/platform/deployment.ncl") if not $validation { print-setup-warning "Nickel validation skipped - continuing with setup" } # Start services (CI/CD uses longer timeouts for reliability) let start_result = (start-platform-services $deployment_mode --verbose=$verbose) { success: $start_result.success profile: "cicd" deployment: $deployment_mode config_base: $base timestamp: (get-timestamp-iso8601) } } # ============================================================================ # COMPLETE PLATFORM SETUP # ============================================================================ # Execute complete platform setup by profile export def setup-platform-complete-by-profile [ profile: string = "developer" config_base: string = "" --verbose = false ] { match $profile { "developer" => { setup-platform-developer $config_base --verbose=$verbose } "production" => { setup-platform-production $config_base --verbose=$verbose } "cicd" => { setup-platform-cicd-nickel $config_base --verbose=$verbose } _ => { print-setup-error $"Unknown profile: ($profile)" { success: false error: $"Unknown profile: ($profile)" } } } } # Execute complete platform setup (backward compatible) export def setup-platform-complete [ setup_mode: string = "solo" config_base: string = "" --verbose = false ] { let base = (if ($config_base == "") { (get-config-base-path) } else { $config_base }) # Map legacy modes to profiles (backward compatibility) let profile = match $setup_mode { "solo" => "developer" "developer" => "developer" "multiuser" => "production" "production" => "production" "cicd" => "cicd" _ => "developer" } setup-platform-complete-by-profile $profile $base --verbose=$verbose } # Print platform services status report export def print-platform-status [] { let status = (verify-platform-services) print "" print "╔═══════════════════════════════════════════════════════════════╗" print "║ PLATFORM SERVICES STATUS REPORT ║" print "╚═══════════════════════════════════════════════════════════════╝" print "" let orch_icon = if $status.orchestrator.running { "✅" } else { "❌" } let cc_icon = if $status.control_center.running { "✅" } else { "❌" } let kms_icon = if $status.kms_service.running { "✅" } else { "❌" } print $"($orch_icon) Orchestrator" print $" Endpoint: ($status.orchestrator.endpoint)" print $" Status: (if $status.orchestrator.running { 'Running' } else { 'Not Running' })" print "" print $"($cc_icon) Control Center" print $" Endpoint: ($status.control_center.endpoint)" print $" Status: (if $status.control_center.running { 'Running' } else { 'Not Running' })" print "" print $"($kms_icon) KMS Service" print $" Endpoint: ($status.kms_service.endpoint)" print $" Status: (if $status.kms_service.running { 'Running' } else { 'Not Running' })" print "" if $status.all_healthy { print "✅ All platform services are healthy!" } else { print "❌ Some platform services are not running" } print "" print "═══════════════════════════════════════════════════════════════" print "" }