# 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 } } }