273 lines
7.4 KiB
Plaintext
Raw Normal View History

# Enhanced validation utilities for provisioning tool
export def validate-required [
value: any
name: string
context?: string
] {
if ($value | is-empty) {
print $"🛑 Required parameter '($name)' is missing or empty"
if ($context | is-not-empty) {
print $"Context: ($context)"
}
print $"💡 Please provide a value for '($name)'"
return false
}
true
}
export def validate-path [
path: string
context?: string
--must-exist
] {
if ($path | is-empty) {
print "🛑 Path parameter is empty"
if ($context | is-not-empty) {
print $"Context: ($context)"
}
return false
}
if $must_exist and not ($path | path exists) {
print $"🛑 Path '($path)' does not exist"
if ($context | is-not-empty) {
print $"Context: ($context)"
}
print "💡 Check if the path exists and you have proper permissions"
return false
}
true
}
export def validate-command [
command: string
context?: string
] {
let cmd_exists = (^bash -c $"type -P ($command)" | complete)
if $cmd_exists.exit_code != 0 {
print $"🛑 Command '($command)' not found in PATH"
if ($context | is-not-empty) {
print $"Context: ($context)"
}
print $"💡 Install '($command)' or add it to your PATH"
return false
}
true
}
export def safe-execute [
command: closure
context: string
--fallback: closure
] {
let result = (do $command | complete)
if $result.exit_code != 0 {
print $"⚠️ Warning: Error in ($context): ($result.stderr)"
if $fallback != null {
print "🔄 Executing fallback..."
do $fallback
} else {
print $"🛑 Execution failed in ($context)"
print $"Error: ($result.stderr)"
}
} else {
$result.stdout
}
}
export def validate-settings [
settings: record
required_fields: list
] {
# Guard: Check for missing required fields (no try-catch)
let missing_fields = ($required_fields | where {|field|
not ($field in $settings) or (($settings | get $field) | is-empty)
})
if ($missing_fields | length) > 0 {
print "🛑 Missing required settings fields:"
$missing_fields | each {|field| print $" - ($field)"}
return false
}
true
}
# ============================================================================
# NICKEL VALIDATION (TYPE-SAFE CONFIGS)
# ============================================================================
# Check if Nickel is installed and available
export def check-nickel-available [] {
let nickel_check = (do { which nickel } | complete)
if ($nickel_check.exit_code == 0) {
let version_output = (do { nickel --version } | complete).stdout | str trim
return {
available: true
version: $version_output
}
}
{
available: false
version: null
error: "Nickel is not installed or not found in PATH"
}
}
# Validate Nickel configuration using nickel typecheck
export def validate-nickel-typecheck [
config_path: path
] {
if not ($config_path | path exists) {
print-setup-error $"Config file not found: ($config_path)"
return false
}
# Check if nickel command is available
let nickel_check = (do { which nickel } | complete)
if ($nickel_check.exit_code != 0) {
print-setup-warning "Nickel not installed - typecheck validation skipped"
return true # Don't block if Nickel not available
}
# Run nickel typecheck
let validation = (do { nickel typecheck $config_path } | complete)
if ($validation.exit_code == 0) {
return true
} else {
print-setup-error $"Nickel typecheck failed for ($config_path)"
if ($validation.stderr | is-not-empty) {
print-setup-error $"Error: ($validation.stderr)"
}
return false
}
}
# Validate Nickel configuration against schema
export def validate-nickel-schema [
config_path: path
schema_path: path
] {
if not ($config_path | path exists) {
print-setup-error $"Config file not found: ($config_path)"
return false
}
if not ($schema_path | path exists) {
print-setup-error $"Schema file not found: ($schema_path)"
return false
}
# Check if nickel command is available
let nickel_check = (do { which nickel } | complete)
if ($nickel_check.exit_code != 0) {
print-setup-warning "Nickel not installed - schema validation skipped"
return true
}
# For schema validation, we need to check the import chain
# This is a simplified validation that checks typecheck passes
let validation = (do { nickel typecheck $config_path } | complete)
if ($validation.exit_code == 0) {
return true
} else {
print-setup-error $"Nickel schema validation failed for ($config_path)"
if ($validation.stderr | is-not-empty) {
print-setup-error $"Error: ($validation.stderr)"
}
return false
}
}
# Validate Nickel composition (base + overlay)
export def validate-nickel-composition [
base_path: path
overlay_path: path
] {
if not ($base_path | path exists) {
print-setup-error $"Base config not found: ($base_path)"
return false
}
if not ($overlay_path | path exists) {
print-setup-error $"Overlay config not found: ($overlay_path)"
return false
}
# Check if nickel command is available
let nickel_check = (do { which nickel } | complete)
if ($nickel_check.exit_code != 0) {
print-setup-warning "Nickel not installed - composition validation skipped"
return true
}
# Validate both configs individually first
let base_validation = (do { nickel typecheck $base_path } | complete)
let overlay_validation = (do { nickel typecheck $overlay_path } | complete)
if ($base_validation.exit_code != 0) {
print-setup-error $"Base composition validation failed for ($base_path)"
return false
}
if ($overlay_validation.exit_code != 0) {
print-setup-error $"Overlay composition validation failed for ($overlay_path)"
return false
}
return true
}
# Validate all Nickel configs in a directory
export def validate-all-nickel-configs [
config_dir: path
] {
if not ($config_dir | path exists) {
print-setup-error $"Config directory not found: ($config_dir)"
return {
success: false
validated: 0
failed: 0
errors: ["Config directory not found"]
}
}
# Find all .ncl files in config directory
let ncl_files = (glob $"($config_dir)/**/*.ncl" | default [])
if ($ncl_files | is-empty) {
return {
success: true
validated: 0
failed: 0
errors: []
}
}
mut validated_count = 0
mut failed_count = 0
mut errors = []
for file in $ncl_files {
let validation = (validate-nickel-typecheck $file)
if $validation {
$validated_count = ($validated_count + 1)
} else {
$failed_count = ($failed_count + 1)
$errors = ($errors | append $file)
}
}
{
success: ($failed_count == 0)
validated: $validated_count
failed: $failed_count
errors: $errors
}
}