422 lines
12 KiB
Plaintext
Raw Permalink Normal View History

# Settings Validation Module
# Validates configuration settings, paths, and user inputs
# Follows Nushell guidelines: explicit types, single purpose, no try-catch
use ./mod.nu *
# ============================================================================
# PATH VALIDATION
# ============================================================================
# Validate configuration base path
export def validate-config-path [
path: string
]: nothing -> record {
let path_exists = ($path | path exists)
let path_is_dir = (if $path_exists { ($path | path type) == "dir" } else { false })
let path_writable = ((do { mkdir $path } | complete) | get exit_code) == 0
let is_valid = ($path_exists and $path_is_dir)
{
path: $path
exists: $path_exists
is_directory: $path_is_dir
writable: $path_writable
valid: $is_valid
}
}
# Validate workspace path
export def validate-workspace-path [
workspace_name: string
workspace_path: string
]: nothing -> record {
let config_base = (get-config-base-path)
let required_dirs = ["config", "infra"]
mut missing_dirs = []
for dir in $required_dirs {
let dir_path = $"($workspace_path)/($dir)"
if not ($dir_path | path exists) {
$missing_dirs = ($missing_dirs | append $dir)
}
}
let workspace_exists = ($workspace_path | path exists)
let is_dir = (if $workspace_exists { ($workspace_path | path type) == "dir" } else { false })
let has_config_file = ($"($workspace_path)/config/provisioning.k" | path exists)
let is_valid = ($workspace_exists and ($missing_dirs | length) == 0)
{
workspace_name: $workspace_name
path: $workspace_path
exists: $workspace_exists
is_directory: $is_dir
has_config: $has_config_file
missing_directories: $missing_dirs
valid: $is_valid
}
}
# ============================================================================
# CONFIGURATION VALUE VALIDATION
# ============================================================================
# Validate OS name
export def validate-os-name [
os_name: string
]: nothing -> record {
let valid_os = ["linux", "macos", "windows"]
let is_valid = ($os_name in $valid_os)
let error_msg = (if not $is_valid { $"Invalid OS: ($os_name)" } else { null })
{
value: $os_name
valid_values: $valid_os
valid: $is_valid
error: $error_msg
}
}
# Validate port number
export def validate-port-number [
port: int
]: nothing -> record {
let is_valid = ($port >= 1 and $port <= 65535)
let error_msg = (if not $is_valid { "Port must be between 1 and 65535" } else { null })
{
port: $port
valid: $is_valid
error: $error_msg
}
}
# Validate port is available
export def validate-port-available [
port: int
]: nothing -> record {
let port_valid = (validate-port-number $port)
if not $port_valid.valid {
return $port_valid
}
let available = (is-port-available $port)
let error_msg = (if not $available { $"Port ($port) is already in use" } else { null })
{
port: $port
valid: $available
available: $available
error: $error_msg
}
}
# Validate provider name
export def validate-provider-name [
provider_name: string
]: nothing -> record {
let valid_providers = ["upcloud", "aws", "hetzner", "local"]
let is_valid = ($provider_name in $valid_providers)
let error_msg = (if not $is_valid { $"Unknown provider: ($provider_name)" } else { null })
{
provider: $provider_name
valid_providers: $valid_providers
valid: $is_valid
error: $error_msg
}
}
# Validate email address format
export def validate-email [
email: string
]: nothing -> record {
let email_pattern = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
let is_valid = ($email | str contains "@")
let error_msg = (if not $is_valid { "Invalid email format" } else { null })
{
email: $email
valid: $is_valid
error: $error_msg
}
}
# ============================================================================
# SYSTEM RESOURCE VALIDATION
# ============================================================================
# Validate CPU count
export def validate-cpu-count [
cpu_count: int
]: nothing -> record {
let is_valid = ($cpu_count >= 1 and $cpu_count <= 1024)
let error_msg = (if not $is_valid { "CPU count must be between 1 and 1024" } else { null })
{
cpu_count: $cpu_count
valid: $is_valid
valid_range: "1-1024"
error: $error_msg
}
}
# Validate memory allocation in GB
export def validate-memory-gb [
memory_gb: int
]: nothing -> record {
let is_valid = ($memory_gb >= 1 and $memory_gb <= 4096)
let error_msg = (if not $is_valid { "Memory must be between 1 and 4096 GB" } else { null })
{
memory_gb: $memory_gb
valid: $is_valid
valid_range: "1-4096 GB"
error: $error_msg
}
}
# Validate disk space in GB
export def validate-disk-gb [
disk_gb: int
]: nothing -> record {
let is_valid = ($disk_gb >= 10 and $disk_gb <= 100000)
let error_msg = (if not $is_valid { "Disk space must be between 10 and 100000 GB" } else { null })
{
disk_gb: $disk_gb
valid: $is_valid
valid_range: "10-100000 GB"
error: $error_msg
}
}
# ============================================================================
# COMPLEX VALIDATION
# ============================================================================
# Validate complete system configuration
export def validate-system-config [
config: record
]: nothing -> record {
mut errors = []
mut warnings = []
# Validate OS name
let os_validation = (validate-os-name ($config.os_name? | default "linux"))
if not $os_validation.valid {
$errors = ($errors | append $os_validation.error)
}
# Validate paths
if ($config.install_path? != null) {
let path_validation = (validate-config-path $config.install_path)
if not $path_validation.valid {
$errors = ($errors | append $"Invalid install_path: ($config.install_path)")
}
}
# Validate CPU count
if ($config.cpu_count? != null) {
let cpu_validation = (validate-cpu-count $config.cpu_count)
if not $cpu_validation.valid {
$errors = ($errors | append $cpu_validation.error)
}
}
# Validate memory
if ($config.memory_gb? != null) {
let mem_validation = (validate-memory-gb $config.memory_gb)
if not $mem_validation.valid {
$errors = ($errors | append $mem_validation.error)
}
}
# Validate disk
if ($config.disk_gb? != null) {
let disk_validation = (validate-disk-gb $config.disk_gb)
if not $disk_validation.valid {
$errors = ($errors | append $disk_validation.error)
}
}
let is_valid = ($errors | length) == 0
let error_count = ($errors | length)
let warning_count = ($warnings | length)
{
valid: $is_valid
errors: $errors
warnings: $warnings
error_count: $error_count
warning_count: $warning_count
}
}
# Validate workspace configuration
export def validate-workspace-config [
workspace_name: string
workspace_path: string
config: record
]: nothing -> record {
mut errors = []
mut warnings = []
# Validate workspace name
if ($workspace_name | str length) == 0 {
$errors = ($errors | append "Workspace name cannot be empty")
}
# Validate workspace path
let path_validation = (validate-workspace-path $workspace_name $workspace_path)
if not $path_validation.valid {
$errors = ($errors | append $"Invalid workspace path: ($workspace_path)")
if ($path_validation.missing_directories | length) > 0 {
$warnings = ($warnings | append $"Missing directories: ($path_validation.missing_directories | str join ', ')")
}
}
# Validate active providers if specified
if ($config.active_providers? != null) {
for provider in $config.active_providers {
let provider_validation = (validate-provider-name $provider)
if not $provider_validation.valid {
$errors = ($errors | append $provider_validation.error)
}
}
}
let is_valid = ($errors | length) == 0
let error_count = ($errors | length)
let warning_count = ($warnings | length)
{
workspace_name: $workspace_name
valid: $is_valid
errors: $errors
warnings: $warnings
error_count: $error_count
warning_count: $warning_count
}
}
# Validate platform services configuration
export def validate-platform-config [
config: record
]: nothing -> record {
mut errors = []
mut warnings = []
# Validate orchestrator port
if ($config.orchestrator_port? != null) {
let port_validation = (validate-port-number $config.orchestrator_port)
if not $port_validation.valid {
$errors = ($errors | append $port_validation.error)
}
}
# Validate control center port
if ($config.control_center_port? != null) {
let port_validation = (validate-port-number $config.control_center_port)
if not $port_validation.valid {
$errors = ($errors | append $port_validation.error)
}
}
# Validate KMS port
if ($config.kms_port? != null) {
let port_validation = (validate-port-number $config.kms_port)
if not $port_validation.valid {
$errors = ($errors | append $port_validation.error)
}
}
# Check for port conflicts
let ports = [
($config.orchestrator_port? | default 9090),
($config.control_center_port? | default 3000),
($config.kms_port? | default 3001)
]
for port in $ports {
if not (is-port-available $port) {
$warnings = ($warnings | append $"Port ($port) is already in use")
}
}
let is_valid = ($errors | length) == 0
let error_count = ($errors | length)
let warning_count = ($warnings | length)
{
valid: $is_valid
errors: $errors
warnings: $warnings
error_count: $error_count
warning_count: $warning_count
}
}
# ============================================================================
# VALIDATION REPORT
# ============================================================================
# Print validation report
export def print-validation-report [
report: record
]: nothing -> nothing {
print ""
print "═══════════════════════════════════════════════════════════════"
print " VALIDATION REPORT"
print "═══════════════════════════════════════════════════════════════"
print ""
if $report.valid {
print "✅ All validation checks passed!"
} else {
print "❌ Validation failed with errors"
}
print ""
if ($report.error_count? | default 0) > 0 {
print "ERRORS:"
for error in ($report.errors? | default []) {
print $" ❌ ($error)"
}
print ""
}
if ($report.warning_count? | default 0) > 0 {
print "WARNINGS:"
for warning in ($report.warnings? | default []) {
print $" ⚠️ ($warning)"
}
print ""
}
print "═══════════════════════════════════════════════════════════════"
print ""
}
# Validate all system requirements are met
export def validate-requirements [
detection_report: record
]: nothing -> record {
let missing_tools = (get-missing-required-tools $detection_report)
let all_requirements_met = ($missing_tools | length) == 0
{
all_requirements_met: $all_requirements_met
missing_tools: $missing_tools
internet_available: $detection_report.network.internet_connected
recommended_tools: [
"kcl",
"sops",
"age",
"docker" # or kubernetes or ssh
]
}
}