provisioning-core/nulib/platform/setup/platform.nu

698 lines
22 KiB
Text
Raw Permalink Normal View History

# 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 ""
}