356 lines
14 KiB
Plaintext
356 lines
14 KiB
Plaintext
|
|
# Environment Detection Module
|
||
|
|
# Detects system capabilities, available tools, network configuration, and existing setup
|
||
|
|
# Follows Nushell guidelines: explicit types, single purpose, no try-catch
|
||
|
|
|
||
|
|
use ./mod.nu *
|
||
|
|
|
||
|
|
# ============================================================================
|
||
|
|
# SYSTEM CAPABILITY DETECTION
|
||
|
|
# ============================================================================
|
||
|
|
|
||
|
|
# Check if Docker is installed and running
|
||
|
|
export def has-docker []: nothing -> bool {
|
||
|
|
let which_check = (bash -c "which docker > /dev/null 2>&1; echo $?" | str trim | into int)
|
||
|
|
if ($which_check != 0) {
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
|
||
|
|
let docker_check = (bash -c "docker ps > /dev/null 2>&1; echo $?" | str trim | into int)
|
||
|
|
($docker_check == 0)
|
||
|
|
}
|
||
|
|
|
||
|
|
# Check if Kubernetes (kubectl) is installed
|
||
|
|
export def has-kubectl []: nothing -> bool {
|
||
|
|
let kubectl_check = (bash -c "which kubectl > /dev/null 2>&1; echo $?" | str trim | into int)
|
||
|
|
($kubectl_check == 0)
|
||
|
|
}
|
||
|
|
|
||
|
|
# Check if Docker Compose is installed
|
||
|
|
export def has-docker-compose []: nothing -> bool {
|
||
|
|
let compose_check = (bash -c "docker compose version > /dev/null 2>&1; echo $?" | str trim | into int)
|
||
|
|
($compose_check == 0)
|
||
|
|
}
|
||
|
|
|
||
|
|
# Check if Podman is installed
|
||
|
|
export def has-podman []: nothing -> bool {
|
||
|
|
let podman_check = (bash -c "which podman > /dev/null 2>&1; echo $?" | str trim | into int)
|
||
|
|
($podman_check == 0)
|
||
|
|
}
|
||
|
|
|
||
|
|
# Check if systemd is available
|
||
|
|
export def has-systemd []: nothing -> bool {
|
||
|
|
let systemctl_check = (bash -c "systemctl --version > /dev/null 2>&1; echo $?" | str trim | into int)
|
||
|
|
($systemctl_check == 0)
|
||
|
|
}
|
||
|
|
|
||
|
|
# Check if SSH is available
|
||
|
|
export def has-ssh []: nothing -> bool {
|
||
|
|
let ssh_check = (bash -c "which ssh > /dev/null 2>&1; echo $?" | str trim | into int)
|
||
|
|
($ssh_check == 0)
|
||
|
|
}
|
||
|
|
|
||
|
|
# Check if KCL is installed
|
||
|
|
export def has-kcl []: nothing -> bool {
|
||
|
|
let kcl_check = (bash -c "which kcl > /dev/null 2>&1; echo $?" | str trim | into int)
|
||
|
|
($kcl_check == 0)
|
||
|
|
}
|
||
|
|
|
||
|
|
# Check if SOPS is installed
|
||
|
|
export def has-sops []: nothing -> bool {
|
||
|
|
let sops_check = (bash -c "which sops > /dev/null 2>&1; echo $?" | str trim | into int)
|
||
|
|
($sops_check == 0)
|
||
|
|
}
|
||
|
|
|
||
|
|
# Check if Age is installed
|
||
|
|
export def has-age []: nothing -> bool {
|
||
|
|
let age_check = (bash -c "which age > /dev/null 2>&1; echo $?" | str trim | into int)
|
||
|
|
($age_check == 0)
|
||
|
|
}
|
||
|
|
|
||
|
|
# Get detailed deployment capabilities
|
||
|
|
export def get-deployment-capabilities []: nothing -> record {
|
||
|
|
{
|
||
|
|
docker_available: (has-docker)
|
||
|
|
docker_compose_available: (has-docker-compose)
|
||
|
|
podman_available: (has-podman)
|
||
|
|
kubectl_available: (has-kubectl)
|
||
|
|
systemd_available: (has-systemd)
|
||
|
|
ssh_available: (has-ssh)
|
||
|
|
kcl_available: (has-kcl)
|
||
|
|
sops_available: (has-sops)
|
||
|
|
age_available: (has-age)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
# ============================================================================
|
||
|
|
# NETWORK DETECTION
|
||
|
|
# ============================================================================
|
||
|
|
|
||
|
|
# Check if port is available
|
||
|
|
export def is-port-available [
|
||
|
|
port: int
|
||
|
|
]: nothing -> bool {
|
||
|
|
let os_type = (detect-os)
|
||
|
|
|
||
|
|
let port_check = if $os_type == "macos" {
|
||
|
|
bash -c $"lsof -i :($port) > /dev/null 2>&1; echo $?" | str trim | into int
|
||
|
|
} else {
|
||
|
|
bash -c $"netstat -tuln 2>/dev/null | grep -q :($port); echo $?" | str trim | into int
|
||
|
|
}
|
||
|
|
|
||
|
|
($port_check != 0) # Port is available if check returns non-zero
|
||
|
|
}
|
||
|
|
|
||
|
|
# Get available ports in range
|
||
|
|
export def get-available-ports [
|
||
|
|
start_port: int
|
||
|
|
end_port: int
|
||
|
|
]: nothing -> list<int> {
|
||
|
|
mut available = []
|
||
|
|
|
||
|
|
for port in ($start_port..$end_port) {
|
||
|
|
if (is-port-available $port) {
|
||
|
|
$available = ($available | append $port)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
$available
|
||
|
|
}
|
||
|
|
|
||
|
|
# Check internet connectivity
|
||
|
|
export def has-internet-connectivity []: nothing -> bool {
|
||
|
|
let curl_check = (bash -c "curl -s -I --max-time 3 https://www.google.com > /dev/null 2>&1; echo $?" | str trim | into int)
|
||
|
|
($curl_check == 0)
|
||
|
|
}
|
||
|
|
|
||
|
|
# ============================================================================
|
||
|
|
# EXISTING CONFIGURATION DETECTION
|
||
|
|
# ============================================================================
|
||
|
|
|
||
|
|
# Check if provisioning is already configured
|
||
|
|
export def is-provisioning-configured []: nothing -> bool {
|
||
|
|
let config_base = (get-config-base-path)
|
||
|
|
let system_config = $"($config_base)/system.toml"
|
||
|
|
|
||
|
|
($system_config | path exists)
|
||
|
|
}
|
||
|
|
|
||
|
|
# Get existing provisioning configuration summary
|
||
|
|
export def get-existing-config-summary []: nothing -> record {
|
||
|
|
let config_base = (get-config-base-path)
|
||
|
|
let system_config_exists = ($"($config_base)/system.toml" | path exists)
|
||
|
|
let workspaces_exists = ($"($config_base)/workspaces" | path exists)
|
||
|
|
let user_prefs_exists = ($"($config_base)/user_preferences.toml" | path exists)
|
||
|
|
|
||
|
|
{
|
||
|
|
config_path: $config_base
|
||
|
|
has_system_config: $system_config_exists
|
||
|
|
has_workspaces: $workspaces_exists
|
||
|
|
has_user_prefs: $user_prefs_exists
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
# ============================================================================
|
||
|
|
# PLATFORM SERVICES DETECTION
|
||
|
|
# ============================================================================
|
||
|
|
|
||
|
|
# Check if orchestrator is running
|
||
|
|
export def is-orchestrator-running []: nothing -> bool {
|
||
|
|
let endpoint = "http://localhost:9090/health"
|
||
|
|
let result = (do { curl -s -f --max-time 2 $endpoint o> /dev/null e> /dev/null } | complete)
|
||
|
|
($result.exit_code == 0)
|
||
|
|
}
|
||
|
|
|
||
|
|
# Check if control-center is running
|
||
|
|
export def is-control-center-running []: nothing -> bool {
|
||
|
|
let endpoint = "http://localhost:3000/health"
|
||
|
|
let result = (do { curl -s -f --max-time 2 $endpoint o> /dev/null e> /dev/null } | complete)
|
||
|
|
($result.exit_code == 0)
|
||
|
|
}
|
||
|
|
|
||
|
|
# Check if KMS service is running
|
||
|
|
export def is-kms-running []: nothing -> bool {
|
||
|
|
let endpoint = "http://localhost:3001/health"
|
||
|
|
let result = (do { curl -s -f --max-time 2 $endpoint o> /dev/null e> /dev/null } | complete)
|
||
|
|
($result.exit_code == 0)
|
||
|
|
}
|
||
|
|
|
||
|
|
# Get platform services status
|
||
|
|
export def get-platform-services-status []: nothing -> record {
|
||
|
|
{
|
||
|
|
orchestrator_running: (is-orchestrator-running)
|
||
|
|
orchestrator_endpoint: "http://localhost:9090/health"
|
||
|
|
control_center_running: (is-control-center-running)
|
||
|
|
control_center_endpoint: "http://localhost:3000/health"
|
||
|
|
kms_running: (is-kms-running)
|
||
|
|
kms_endpoint: "http://localhost:3001/health"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
# ============================================================================
|
||
|
|
# ENVIRONMENT ANALYSIS REPORT
|
||
|
|
# ============================================================================
|
||
|
|
|
||
|
|
# Generate comprehensive environment detection report
|
||
|
|
export def generate-detection-report []: nothing -> record {
|
||
|
|
{
|
||
|
|
system: {
|
||
|
|
os: (detect-os)
|
||
|
|
architecture: (detect-architecture)
|
||
|
|
hostname: (get-system-hostname)
|
||
|
|
current_user: (get-current-user)
|
||
|
|
cpu_count: (get-cpu-count)
|
||
|
|
memory_gb: (get-system-memory-gb)
|
||
|
|
disk_gb: (get-system-disk-gb)
|
||
|
|
}
|
||
|
|
capabilities: (get-deployment-capabilities)
|
||
|
|
network: {
|
||
|
|
internet_connected: (has-internet-connectivity)
|
||
|
|
docker_port_available: (is-port-available 2375)
|
||
|
|
orchestrator_port_available: (is-port-available 9090)
|
||
|
|
control_center_port_available: (is-port-available 3000)
|
||
|
|
kms_port_available: (is-port-available 3001)
|
||
|
|
}
|
||
|
|
existing_config: (get-existing-config-summary)
|
||
|
|
platform_services: (get-platform-services-status)
|
||
|
|
timestamp: (date now)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
# Print detection report in readable format
|
||
|
|
export def print-detection-report [
|
||
|
|
report: record
|
||
|
|
]: nothing -> nothing {
|
||
|
|
print ""
|
||
|
|
print "╔═══════════════════════════════════════════════════════════════╗"
|
||
|
|
print "║ ENVIRONMENT DETECTION REPORT ║"
|
||
|
|
print "╚═══════════════════════════════════════════════════════════════╝"
|
||
|
|
print ""
|
||
|
|
|
||
|
|
print "📊 SYSTEM INFORMATION"
|
||
|
|
print "─────────────────────────────────────────────────────────────"
|
||
|
|
print $" OS: ($report.system.os)"
|
||
|
|
print $" Architecture: ($report.system.architecture)"
|
||
|
|
print $" Hostname: ($report.system.hostname)"
|
||
|
|
print $" User: ($report.system.current_user)"
|
||
|
|
print $" CPU Cores: ($report.system.cpu_count)"
|
||
|
|
print $" Memory: ($report.system.memory_gb) GB"
|
||
|
|
print $" Disk Space: ($report.system.disk_gb) GB"
|
||
|
|
print ""
|
||
|
|
|
||
|
|
print "🛠️ AVAILABLE TOOLS"
|
||
|
|
print "─────────────────────────────────────────────────────────────"
|
||
|
|
print $" Docker: (if $report.capabilities.docker_available { '✅' } else { '❌' })"
|
||
|
|
print $" Docker Compose: (if $report.capabilities.docker_compose_available { '✅' } else { '❌' })"
|
||
|
|
print $" Podman: (if $report.capabilities.podman_available { '✅' } else { '❌' })"
|
||
|
|
print $" Kubernetes: (if $report.capabilities.kubectl_available { '✅' } else { '❌' })"
|
||
|
|
print $" Systemd: (if $report.capabilities.systemd_available { '✅' } else { '❌' })"
|
||
|
|
print $" SSH: (if $report.capabilities.ssh_available { '✅' } else { '❌' })"
|
||
|
|
print $" KCL: (if $report.capabilities.kcl_available { '✅' } else { '❌' })"
|
||
|
|
print $" SOPS: (if $report.capabilities.sops_available { '✅' } else { '❌' })"
|
||
|
|
print $" Age: (if $report.capabilities.age_available { '✅' } else { '❌' })"
|
||
|
|
print ""
|
||
|
|
|
||
|
|
print "🌐 NETWORK STATUS"
|
||
|
|
print "─────────────────────────────────────────────────────────────"
|
||
|
|
print $" Internet: (if $report.network.internet_connected { '✅' } else { '❌' })"
|
||
|
|
print $" Docker Port: (if $report.network.docker_port_available { '✅ Available' } else { '❌ In Use' })"
|
||
|
|
print $" Orchestrator: (if $report.network.orchestrator_port_available { '✅ Available' } else { '❌ In Use' })"
|
||
|
|
print $" Control Center: (if $report.network.control_center_port_available { '✅ Available' } else { '❌ In Use' })"
|
||
|
|
print $" KMS Service: (if $report.network.kms_port_available { '✅ Available' } else { '❌ In Use' })"
|
||
|
|
print ""
|
||
|
|
|
||
|
|
print "📁 EXISTING CONFIGURATION"
|
||
|
|
print "─────────────────────────────────────────────────────────────"
|
||
|
|
print $" Config Path: ($report.existing_config.config_path)"
|
||
|
|
print $" Configured: (if $report.existing_config.has_system_config { '✅ Yes' } else { '❌ No' })"
|
||
|
|
print $" Workspaces: (if $report.existing_config.has_workspaces { '✅ Yes' } else { '❌ No' })"
|
||
|
|
print $" Preferences: (if $report.existing_config.has_user_prefs { '✅ Yes' } else { '❌ No' })"
|
||
|
|
print ""
|
||
|
|
|
||
|
|
print "⚙️ PLATFORM SERVICES"
|
||
|
|
print "─────────────────────────────────────────────────────────────"
|
||
|
|
print $" Orchestrator: (if $report.platform_services.orchestrator_running { '✅ Running' } else { '❌ Not Running' })"
|
||
|
|
print $" Control Center: (if $report.platform_services.control_center_running { '✅ Running' } else { '❌ Not Running' })"
|
||
|
|
print $" KMS Service: (if $report.platform_services.kms_running { '✅ Running' } else { '❌ Not Running' })"
|
||
|
|
print ""
|
||
|
|
print "═══════════════════════════════════════════════════════════════"
|
||
|
|
print ""
|
||
|
|
}
|
||
|
|
|
||
|
|
# Recommend deployment mode based on available capabilities
|
||
|
|
export def recommend-deployment-mode [
|
||
|
|
report: record
|
||
|
|
]: nothing -> string {
|
||
|
|
let caps = $report.capabilities
|
||
|
|
|
||
|
|
if ($caps.docker_available and $caps.docker_compose_available) {
|
||
|
|
"docker-compose"
|
||
|
|
} else if ($caps.kubectl_available) {
|
||
|
|
"kubernetes"
|
||
|
|
} else if ($caps.ssh_available) {
|
||
|
|
"remote-ssh"
|
||
|
|
} else if ($caps.systemd_available) {
|
||
|
|
"systemd"
|
||
|
|
} else {
|
||
|
|
"unknown"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
# Get recommended deployment configuration
|
||
|
|
export def get-recommended-config [
|
||
|
|
report: record
|
||
|
|
]: nothing -> record {
|
||
|
|
let deployment_mode = (recommend-deployment-mode $report)
|
||
|
|
let caps = $report.capabilities
|
||
|
|
|
||
|
|
{
|
||
|
|
deployment_mode: $deployment_mode
|
||
|
|
supported_modes: {
|
||
|
|
docker_compose: ($caps.docker_available and $caps.docker_compose_available)
|
||
|
|
kubernetes: ($caps.kubectl_available)
|
||
|
|
remote_ssh: ($caps.ssh_available)
|
||
|
|
systemd: ($caps.systemd_available)
|
||
|
|
}
|
||
|
|
recommended_os_paths: {
|
||
|
|
config_base: (get-config-base-path)
|
||
|
|
workspaces: $"(get-config-base-path)/workspaces"
|
||
|
|
cache: $"(get-config-base-path)/cache"
|
||
|
|
}
|
||
|
|
required_tools_missing: (get-missing-required-tools $report)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
# Get list of missing required tools
|
||
|
|
export def get-missing-required-tools [
|
||
|
|
report: record
|
||
|
|
]: nothing -> list<string> {
|
||
|
|
mut missing = []
|
||
|
|
|
||
|
|
if not $report.capabilities.kcl_available {
|
||
|
|
$missing = ($missing | append "kcl")
|
||
|
|
}
|
||
|
|
|
||
|
|
if not $report.capabilities.sops_available {
|
||
|
|
$missing = ($missing | append "sops")
|
||
|
|
}
|
||
|
|
|
||
|
|
if not $report.capabilities.age_available {
|
||
|
|
$missing = ($missing | append "age")
|
||
|
|
}
|
||
|
|
|
||
|
|
# At least one deployment method is required
|
||
|
|
let has_deployment = (
|
||
|
|
($report.capabilities.docker_available) or
|
||
|
|
($report.capabilities.kubectl_available) or
|
||
|
|
($report.capabilities.ssh_available) or
|
||
|
|
($report.capabilities.systemd_available)
|
||
|
|
)
|
||
|
|
|
||
|
|
if not $has_deployment {
|
||
|
|
$missing = ($missing | append "deployment-method (docker/kubernetes/ssh/systemd)")
|
||
|
|
}
|
||
|
|
|
||
|
|
$missing
|
||
|
|
}
|