359 lines
10 KiB
Plaintext
359 lines
10 KiB
Plaintext
#!/usr/bin/env nu
|
|
|
|
# Pre-flight Check System
|
|
# Validates service prerequisites before operations
|
|
|
|
use manager.nu [load-service-registry is-service-running get-service-definition]
|
|
use dependencies.nu [resolve-dependencies get-startup-order]
|
|
|
|
# Check required services for operation
|
|
export def check-required-services [
|
|
operation: string
|
|
] -> record {
|
|
let registry = (load-service-registry)
|
|
|
|
# Find all services required for this operation
|
|
let required_services = (
|
|
$registry
|
|
| transpose name config
|
|
| where { |row|
|
|
$operation in $row.config.required_for
|
|
}
|
|
| get name
|
|
)
|
|
|
|
if ($required_services | is-empty) {
|
|
return {
|
|
operation: $operation
|
|
required_services: []
|
|
all_running: true
|
|
missing_services: []
|
|
can_auto_start: true
|
|
message: "No services required for this operation"
|
|
}
|
|
}
|
|
|
|
# Check which services are running
|
|
let mut running = []
|
|
let mut missing = []
|
|
|
|
for service in $required_services {
|
|
if (is-service-running $service) {
|
|
$running = ($running | append $service)
|
|
} else {
|
|
$missing = ($missing | append $service)
|
|
}
|
|
}
|
|
|
|
# Check if missing services can be auto-started
|
|
let can_auto_start = (
|
|
$missing
|
|
| all { |service|
|
|
let service_def = (get-service-definition $service)
|
|
$service_def.startup.auto_start
|
|
}
|
|
)
|
|
|
|
{
|
|
operation: $operation
|
|
required_services: $required_services
|
|
running_services: $running
|
|
missing_services: $missing
|
|
all_running: ($missing | is-empty)
|
|
can_auto_start: $can_auto_start
|
|
message: (if ($missing | is-empty) {
|
|
"All required services are running"
|
|
} else if $can_auto_start {
|
|
$"Services need to be started: ($missing | str join ', ')"
|
|
} else {
|
|
$"Required services not running and cannot auto-start: ($missing | str join ', ')"
|
|
})
|
|
}
|
|
}
|
|
|
|
# Validate service prerequisites
|
|
export def validate-service-prerequisites [
|
|
service_name: string
|
|
] -> record {
|
|
let service_def = (get-service-definition $service_name)
|
|
|
|
let mut issues = []
|
|
let mut warnings = []
|
|
|
|
# Check deployment mode requirements
|
|
match $service_def.deployment.mode {
|
|
"docker" | "docker-compose" => {
|
|
# Check if Docker is available
|
|
try {
|
|
docker --version | ignore
|
|
} catch {
|
|
$issues = ($issues | append "Docker is not installed or not running")
|
|
}
|
|
}
|
|
"kubernetes" => {
|
|
# Check if kubectl is available
|
|
try {
|
|
kubectl version --client | ignore
|
|
} catch {
|
|
$issues = ($issues | append "kubectl is not installed")
|
|
}
|
|
}
|
|
"binary" => {
|
|
# Check if binary exists
|
|
let binary_path = ($service_def.deployment.binary.binary_path | str replace -a '${HOME}' $env.HOME)
|
|
if not ($binary_path | path exists) {
|
|
$issues = ($issues | append $"Binary not found: ($binary_path)")
|
|
}
|
|
}
|
|
_ => {}
|
|
}
|
|
|
|
# Check dependencies
|
|
for dep in $service_def.dependencies {
|
|
if not (is-service-running $dep) {
|
|
$warnings = ($warnings | append $"Dependency '($dep)' is not running")
|
|
}
|
|
}
|
|
|
|
# Check conflicts
|
|
for conflict in $service_def.conflicts {
|
|
if (is-service-running $conflict) {
|
|
$issues = ($issues | append $"Conflicting service '($conflict)' is running")
|
|
}
|
|
}
|
|
|
|
{
|
|
service: $service_name
|
|
valid: ($issues | is-empty)
|
|
issues: $issues
|
|
warnings: $warnings
|
|
can_start: ($issues | is-empty)
|
|
message: (if ($issues | is-empty) {
|
|
"All prerequisites met"
|
|
} else {
|
|
$"Prerequisites not met: ($issues | str join '; ')"
|
|
})
|
|
}
|
|
}
|
|
|
|
# Auto-start required services
|
|
export def auto-start-required-services [
|
|
operation: string
|
|
] -> record {
|
|
let check = (check-required-services $operation)
|
|
|
|
if $check.all_running {
|
|
return {
|
|
success: true
|
|
message: "All required services already running"
|
|
started_services: []
|
|
}
|
|
}
|
|
|
|
if not $check.can_auto_start {
|
|
return {
|
|
success: false
|
|
message: "Some required services cannot be auto-started"
|
|
failed_services: $check.missing_services
|
|
}
|
|
}
|
|
|
|
# Get startup order for missing services
|
|
let startup_order = (get-startup-order $check.missing_services)
|
|
|
|
print $"Starting required services in order: ($startup_order | str join ' -> ')"
|
|
|
|
let mut started = []
|
|
let mut failed = []
|
|
|
|
for service in $startup_order {
|
|
print $"Starting ($service)..."
|
|
|
|
use manager.nu start-service
|
|
try {
|
|
let result = (start-service $service)
|
|
|
|
if $result {
|
|
$started = ($started | append $service)
|
|
print $"✅ ($service) started successfully"
|
|
} else {
|
|
$failed = ($failed | append $service)
|
|
print $"❌ Failed to start ($service)"
|
|
break
|
|
}
|
|
} catch {
|
|
$failed = ($failed | append $service)
|
|
print $"❌ Error starting ($service)"
|
|
break
|
|
}
|
|
}
|
|
|
|
{
|
|
success: ($failed | is-empty)
|
|
message: (if ($failed | is-empty) {
|
|
$"Successfully started ($started | length) services"
|
|
} else {
|
|
$"Failed to start some services: ($failed | str join ', ')"
|
|
})
|
|
started_services: $started
|
|
failed_services: $failed
|
|
}
|
|
}
|
|
|
|
# Check service conflicts
|
|
export def check-service-conflicts [
|
|
service_name: string
|
|
] -> record {
|
|
let service_def = (get-service-definition $service_name)
|
|
|
|
let mut conflicts = []
|
|
|
|
for conflict in $service_def.conflicts {
|
|
if (is-service-running $conflict) {
|
|
$conflicts = ($conflicts | append {
|
|
service: $conflict
|
|
status: "running"
|
|
action_required: "stop"
|
|
})
|
|
}
|
|
}
|
|
|
|
{
|
|
service: $service_name
|
|
has_conflicts: (not ($conflicts | is-empty))
|
|
conflicts: $conflicts
|
|
can_start: ($conflicts | is-empty)
|
|
message: (if ($conflicts | is-empty) {
|
|
"No conflicting services running"
|
|
} else {
|
|
$"Conflicting services running: (($conflicts | get service) | str join ', ')"
|
|
})
|
|
}
|
|
}
|
|
|
|
# Validate all services
|
|
export def validate-all-services [] -> record {
|
|
let registry = (load-service-registry)
|
|
|
|
let validation_results = (
|
|
$registry
|
|
| transpose name config
|
|
| each { |row|
|
|
validate-service-prerequisites $row.name
|
|
}
|
|
)
|
|
|
|
let total = ($validation_results | length)
|
|
let valid = ($validation_results | where valid | length)
|
|
let invalid = ($validation_results | where { |r| not $r.valid } | length)
|
|
|
|
{
|
|
total_services: $total
|
|
valid_services: $valid
|
|
invalid_services: $invalid
|
|
all_valid: ($invalid == 0)
|
|
results: $validation_results
|
|
message: $"($valid)/($total) services have valid configurations"
|
|
}
|
|
}
|
|
|
|
# Pre-flight check for service start
|
|
export def preflight-start-service [
|
|
service_name: string
|
|
] -> record {
|
|
print $"Running pre-flight checks for ($service_name)..."
|
|
|
|
# 1. Validate prerequisites
|
|
let prereq_check = (validate-service-prerequisites $service_name)
|
|
if not $prereq_check.valid {
|
|
return {
|
|
can_start: false
|
|
reason: "prerequisites"
|
|
details: $prereq_check
|
|
}
|
|
}
|
|
|
|
# 2. Check conflicts
|
|
let conflict_check = (check-service-conflicts $service_name)
|
|
if $conflict_check.has_conflicts {
|
|
return {
|
|
can_start: false
|
|
reason: "conflicts"
|
|
details: $conflict_check
|
|
}
|
|
}
|
|
|
|
# 3. Check dependencies
|
|
let service_def = (get-service-definition $service_name)
|
|
let mut missing_deps = []
|
|
|
|
for dep in $service_def.dependencies {
|
|
if not (is-service-running $dep) {
|
|
let dep_def = (get-service-definition $dep)
|
|
$missing_deps = ($missing_deps | append {
|
|
service: $dep
|
|
auto_start: $dep_def.startup.auto_start
|
|
})
|
|
}
|
|
}
|
|
|
|
if not ($missing_deps | is-empty) {
|
|
let can_auto_start = ($missing_deps | all { |d| $d.auto_start })
|
|
|
|
return {
|
|
can_start: $can_auto_start
|
|
reason: "dependencies"
|
|
details: {
|
|
missing_dependencies: $missing_deps
|
|
can_auto_start: $can_auto_start
|
|
}
|
|
}
|
|
}
|
|
|
|
# All checks passed
|
|
{
|
|
can_start: true
|
|
reason: "all_checks_passed"
|
|
details: {
|
|
message: "Pre-flight checks passed"
|
|
}
|
|
}
|
|
}
|
|
|
|
# Get service readiness report
|
|
export def get-readiness-report [] -> record {
|
|
let registry = (load-service-registry)
|
|
|
|
let services = (
|
|
$registry
|
|
| transpose name config
|
|
| each { |row|
|
|
let is_running = (is-service-running $row.name)
|
|
let prereq_check = (validate-service-prerequisites $row.name)
|
|
|
|
{
|
|
name: $row.name
|
|
type: $row.config.type
|
|
category: $row.config.category
|
|
running: $is_running
|
|
auto_start: $row.config.startup.auto_start
|
|
valid_config: $prereq_check.valid
|
|
can_start: $prereq_check.can_start
|
|
issues: ($prereq_check.issues | length)
|
|
}
|
|
}
|
|
)
|
|
|
|
let total = ($services | length)
|
|
let running = ($services | where running | length)
|
|
let ready = ($services | where can_start | length)
|
|
|
|
{
|
|
total_services: $total
|
|
running_services: $running
|
|
ready_to_start: $ready
|
|
services: $services
|
|
summary: $"($running) running, ($ready) ready to start out of ($total) total"
|
|
}
|
|
}
|