293 lines
8.7 KiB
Plaintext
293 lines
8.7 KiB
Plaintext
# Enhanced Check Mode for Taskservs
|
||
# Provides dry-run capabilities with detailed validation and preview
|
||
|
||
use lib_provisioning *
|
||
use utils.nu *
|
||
use deps_validator.nu *
|
||
use validate.nu *
|
||
use ../lib_provisioning/config/accessor.nu *
|
||
|
||
# Preview taskserv configuration generation
|
||
def preview-config-generation [
|
||
taskserv_name: string
|
||
taskserv_profile: string
|
||
settings: record
|
||
server: record
|
||
--verbose (-v)
|
||
]: nothing -> record {
|
||
let taskservs_path = (get-taskservs-path)
|
||
let profile_path = ($taskservs_path | path join $taskserv_name $taskserv_profile)
|
||
|
||
if not ($profile_path | path exists) {
|
||
return {
|
||
valid: false
|
||
errors: [$"Profile path not found: ($profile_path)"]
|
||
warnings: []
|
||
files: []
|
||
}
|
||
}
|
||
|
||
# Find all template files
|
||
let template_files = try {
|
||
ls ($profile_path | path join "**/*.j2") | get name
|
||
} catch {
|
||
[]
|
||
}
|
||
|
||
# Find shell scripts
|
||
let script_files = try {
|
||
ls ($profile_path | path join "**/*.sh") | get name
|
||
} catch {
|
||
[]
|
||
}
|
||
|
||
# Find other config files
|
||
let config_files = try {
|
||
ls $profile_path
|
||
| where type == "file"
|
||
| where name !~ ".j2$"
|
||
| where name !~ ".sh$"
|
||
| get name
|
||
} catch {
|
||
[]
|
||
}
|
||
|
||
mut preview_files = []
|
||
|
||
# Preview templates
|
||
for tpl in $template_files {
|
||
let dest_name = ($tpl | path basename | str replace ".j2" "")
|
||
$preview_files = ($preview_files | append {
|
||
type: "template"
|
||
source: ($tpl | path relative-to $profile_path)
|
||
destination: $dest_name
|
||
action: "render and upload"
|
||
})
|
||
}
|
||
|
||
# Preview scripts
|
||
for script in $script_files {
|
||
$preview_files = ($preview_files | append {
|
||
type: "script"
|
||
source: ($script | path basename)
|
||
destination: ($script | path basename)
|
||
action: "upload and execute"
|
||
})
|
||
}
|
||
|
||
# Preview config files
|
||
for cfg in $config_files {
|
||
$preview_files = ($preview_files | append {
|
||
type: "config"
|
||
source: ($cfg | path basename)
|
||
destination: ($cfg | path basename)
|
||
action: "upload"
|
||
})
|
||
}
|
||
|
||
return {
|
||
valid: true
|
||
errors: []
|
||
warnings: []
|
||
files: $preview_files
|
||
total_files: ($preview_files | length)
|
||
}
|
||
}
|
||
|
||
# Check prerequisites on target server (without actually connecting in check mode)
|
||
def check-prerequisites [
|
||
taskserv_name: string
|
||
server: record
|
||
settings: record
|
||
check_mode: bool
|
||
]: nothing -> record {
|
||
mut checks = []
|
||
|
||
# Check if server is accessible (in check mode, just validate config)
|
||
if $check_mode {
|
||
$checks = ($checks | append {
|
||
check: "Server accessibility"
|
||
status: "skipped"
|
||
message: "Check mode - SSH not tested"
|
||
})
|
||
} else {
|
||
# In real mode, this would test SSH connection
|
||
$checks = ($checks | append {
|
||
check: "Server accessibility"
|
||
status: "pending"
|
||
message: "Would test SSH connection"
|
||
})
|
||
}
|
||
|
||
# Check if required directories exist (preview only in check mode)
|
||
let required_dirs = ["/tmp", "/etc", "/usr/local/bin"]
|
||
for dir in $required_dirs {
|
||
$checks = ($checks | append {
|
||
check: $"Directory ($dir)"
|
||
status: "info"
|
||
message: $"Would verify directory exists"
|
||
})
|
||
}
|
||
|
||
# Check if required commands are available
|
||
let required_commands = ["bash", "systemctl"]
|
||
for cmd in $required_commands {
|
||
$checks = ($checks | append {
|
||
check: $"Command ($cmd)"
|
||
status: "info"
|
||
message: $"Would verify command is available"
|
||
})
|
||
}
|
||
|
||
return {
|
||
checks: $checks
|
||
total_checks: ($checks | length)
|
||
}
|
||
}
|
||
|
||
# Enhanced check mode handler
|
||
export def run-check-mode [
|
||
taskserv_name: string
|
||
taskserv_profile: string
|
||
settings: record
|
||
server: record
|
||
--verbose (-v)
|
||
]: nothing -> record {
|
||
_print $"\n(_ansi cyan_bold)Check Mode: ($taskserv_name)(_ansi reset) on (_ansi green_bold)($server.hostname)(_ansi reset)"
|
||
|
||
mut results = {
|
||
taskserv: $taskserv_name
|
||
profile: $taskserv_profile
|
||
server: $server.hostname
|
||
validations: []
|
||
overall_valid: true
|
||
}
|
||
|
||
# 1. Static validation
|
||
_print $"\n(_ansi yellow)→ Running static validation...(_ansi reset)"
|
||
let static_validation = {
|
||
kcl: (validate-kcl-schemas $taskserv_name --verbose=$verbose)
|
||
templates: (validate-templates $taskserv_name --verbose=$verbose)
|
||
scripts: (validate-scripts $taskserv_name --verbose=$verbose)
|
||
}
|
||
|
||
let static_valid = (
|
||
$static_validation.kcl.valid and
|
||
$static_validation.templates.valid and
|
||
$static_validation.scripts.valid
|
||
)
|
||
|
||
if $static_valid {
|
||
_print $" (_ansi green)✓ Static validation passed(_ansi reset)"
|
||
} else {
|
||
_print $" (_ansi red)✗ Static validation failed(_ansi reset)"
|
||
$results.overall_valid = false
|
||
}
|
||
|
||
$results.validations = ($results.validations | append {
|
||
level: "static"
|
||
valid: $static_valid
|
||
details: $static_validation
|
||
})
|
||
|
||
# 2. Dependency validation
|
||
_print $"\n(_ansi yellow)→ Checking dependencies...(_ansi reset)"
|
||
let deps_validation = (validate-infra-dependencies $taskserv_name $settings --verbose=$verbose)
|
||
|
||
if $deps_validation.valid {
|
||
_print $" (_ansi green)✓ Dependencies OK(_ansi reset)"
|
||
if ($deps_validation.requires | default [] | length) > 0 {
|
||
_print $" Required: (($deps_validation.requires | str join ', '))"
|
||
}
|
||
} else {
|
||
_print $" (_ansi red)✗ Dependency issues found(_ansi reset)"
|
||
for err in ($deps_validation.errors | default []) {
|
||
_print $" (_ansi red)✗(_ansi reset) ($err)"
|
||
}
|
||
$results.overall_valid = false
|
||
}
|
||
|
||
$results.validations = ($results.validations | append {
|
||
level: "dependencies"
|
||
valid: $deps_validation.valid
|
||
details: $deps_validation
|
||
})
|
||
|
||
# 3. Preview configuration generation
|
||
_print $"\n(_ansi yellow)→ Previewing configuration generation...(_ansi reset)"
|
||
let config_preview = (preview-config-generation $taskserv_name $taskserv_profile $settings $server --verbose=$verbose)
|
||
|
||
if $config_preview.valid {
|
||
_print $" (_ansi green)✓ Configuration preview generated(_ansi reset)"
|
||
_print $" Files to process: ($config_preview.total_files)"
|
||
|
||
if $verbose and ($config_preview.files | length) > 0 {
|
||
_print $"\n Files to be deployed:"
|
||
for file in $config_preview.files {
|
||
_print $" ($file.type): ($file.source) → ($file.destination)"
|
||
}
|
||
}
|
||
} else {
|
||
_print $" (_ansi red)✗ Configuration preview failed(_ansi reset)"
|
||
$results.overall_valid = false
|
||
}
|
||
|
||
$results.validations = ($results.validations | append {
|
||
level: "configuration"
|
||
valid: $config_preview.valid
|
||
details: $config_preview
|
||
})
|
||
|
||
# 4. Prerequisites check
|
||
_print $"\n(_ansi yellow)→ Checking prerequisites...(_ansi reset)"
|
||
let prereq_check = (check-prerequisites $taskserv_name $server $settings true)
|
||
_print $" (_ansi blue)ℹ(_ansi reset) Prerequisite checks (preview mode):"
|
||
for check in $prereq_check.checks {
|
||
let icon = match $check.status {
|
||
"passed" => $"(_ansi green)✓(_ansi reset)"
|
||
"failed" => $"(_ansi red)✗(_ansi reset)"
|
||
"info" => $"(_ansi blue)ℹ(_ansi reset)"
|
||
"skipped" => $"(_ansi yellow)⊘(_ansi reset)"
|
||
_ => "•"
|
||
}
|
||
_print $" ($icon) ($check.check): ($check.message)"
|
||
}
|
||
|
||
$results.validations = ($results.validations | append {
|
||
level: "prerequisites"
|
||
valid: true
|
||
details: $prereq_check
|
||
})
|
||
|
||
# Summary
|
||
_print $"\n(_ansi cyan_bold)Check Mode Summary(_ansi reset)"
|
||
if $results.overall_valid {
|
||
_print $"(_ansi green_bold)✓ All validations passed(_ansi reset)"
|
||
_print $"\n💡 Taskserv can be deployed with: (_ansi cyan)provisioning taskserv create ($taskserv_name)(_ansi reset)"
|
||
} else {
|
||
_print $"(_ansi red_bold)✗ Validation failed(_ansi reset)"
|
||
_print $"\n🛑 Fix the errors above before deploying"
|
||
}
|
||
|
||
return $results
|
||
}
|
||
|
||
# Print detailed check mode report
|
||
export def print-check-report [
|
||
results: record
|
||
--format: string = "text"
|
||
]: nothing -> nothing {
|
||
match $format {
|
||
"json" => {
|
||
$results | to json
|
||
}
|
||
"yaml" => {
|
||
$results | to yaml
|
||
}
|
||
_ => {
|
||
# Text format already printed by run-check-mode
|
||
null
|
||
}
|
||
}
|
||
}
|