chore: add current provisioning state before migration

This commit is contained in:
Jesús Pérez 2025-09-22 23:11:41 +01:00
parent a9703b4748
commit 50745b0f22
660 changed files with 88126 additions and 0 deletions

View file

@ -0,0 +1,431 @@
# AI Module for Provisioning CLI
# Enhanced natural language interface with intelligent agents
use std
use ../lib_provisioning/ai/lib.nu *
use ../lib_provisioning/utils/settings.nu load_settings
use ../lib_provisioning/plugins_defs.nu render_template
use ../ai/query_processor.nu *
# Main AI command dispatcher
export def main [
action: string
...args: string
--prompt: string
--template-type: string = "server"
--context: string
--provider: string
--model: string
--max-tokens: int
--temperature: float
--test
--config
--enable
--disable
]: nothing -> any {
match $action {
"template" => { ai_template_command $args $prompt $template_type }
"query" => {
if ($prompt | is-not-empty) {
enhanced_query_command $prompt $context
} else {
ai_query_command $args $prompt $context
}
}
"chat" => { start_interactive_chat }
"capabilities" => { show_ai_capabilities }
"examples" => { show_query_examples }
"batch" => {
if ($args | length) > 0 {
process_batch_file $args.0
} else {
print "❌ Batch processing requires a file path"
}
}
"performance" => { run_ai_benchmark }
"webhook" => { ai_webhook_command $args $prompt }
"test" => { ai_test_command }
"config" => { ai_config_command }
"enable" => { ai_enable_command }
"disable" => { ai_disable_command }
"help" => { enhanced_ai_help_command }
_ => {
print $"Unknown AI action: ($action)"
enhanced_ai_help_command
}
}
}
# Generate infrastructure templates using AI
def ai_template_command [
args: list<string>
prompt: string
template_type: string
] {
if ($prompt | is-empty) {
error make {msg: "AI template generation requires --prompt"}
}
let result = (ai_generate_template $prompt $template_type)
print $"# AI Generated ($template_type) Template"
print $"# Prompt: ($prompt)"
print ""
print $result
}
# Process natural language queries about infrastructure
def ai_query_command [
args: list<string>
prompt: string
context: string
] {
if ($prompt | is-empty) {
error make {msg: "AI query requires --prompt"}
}
let context_data = if ($context | is-empty) {
{}
} else {
if ($context | str starts-with "{") {
($context | from json)
} else {
{raw_context: $context}
}
}
let result = (ai_process_query $prompt $context_data)
print $result
}
# Process webhook/chat messages
def ai_webhook_command [
args: list<string>
prompt: string
] {
if ($prompt | is-empty) {
error make {msg: "AI webhook processing requires --prompt"}
}
let user_id = if ($args | length) > 0 { $args.0 } else { "cli" }
let channel = if ($args | length) > 1 { $args.1 } else { "direct" }
let result = (ai_process_webhook $prompt $user_id $channel)
print $result
}
# Test AI connectivity and configuration
def ai_test_command [] {
print "Testing AI configuration..."
let validation = (validate_ai_config)
if not $validation.valid {
print "❌ AI configuration issues found:"
for issue in $validation.issues {
print $" - ($issue)"
}
return
}
print "✅ AI configuration is valid"
let test_result = (test_ai_connection)
if $test_result.success {
print $"✅ ($test_result.message)"
if "response" in $test_result {
print $" Response: ($test_result.response)"
}
} else {
print $"❌ ($test_result.message)"
}
}
# Show AI configuration
def ai_config_command [] {
let config = (get_ai_config)
print "🤖 AI Configuration:"
print $" Enabled: ($config.enabled)"
print $" Provider: ($config.provider)"
print $" Model: ($config.model? // 'default')"
print $" Max Tokens: ($config.max_tokens)"
print $" Temperature: ($config.temperature)"
print $" Timeout: ($config.timeout)s"
print ""
print "Feature Flags:"
print $" Template AI: ($config.enable_template_ai)"
print $" Query AI: ($config.enable_query_ai)"
print $" Webhook AI: ($config.enable_webhook_ai)"
if $config.enabled and ($config.api_key? == null) {
print ""
print "⚠️ API key not configured"
print " Set environment variable based on provider:"
print " - OpenAI: OPENAI_API_KEY"
print " - Claude: ANTHROPIC_API_KEY"
print " - Generic: LLM_API_KEY"
}
}
# Enable AI functionality
def ai_enable_command [] {
print "AI functionality can be enabled by setting ai.enabled = true in your KCL settings"
print "Example configuration:"
print ""
print "ai: AIProvider {"
print " enabled: true"
print " provider: \"openai\" # or \"claude\" or \"generic\""
print " api_key: env(\"OPENAI_API_KEY\")"
print " model: \"gpt-4\""
print " max_tokens: 2048"
print " temperature: 0.3"
print " enable_template_ai: true"
print " enable_query_ai: true"
print " enable_webhook_ai: false"
print "}"
}
# Disable AI functionality
def ai_disable_command [] {
print "AI functionality can be disabled by setting ai.enabled = false in your KCL settings"
print "This will disable all AI features while preserving configuration."
}
# Show AI help
def ai_help_command [] {
print "🤖 AI-Powered Provisioning Commands"
print ""
print "USAGE:"
print " ./core/nulib/provisioning ai <ACTION> [OPTIONS]"
print ""
print "ACTIONS:"
print " template Generate infrastructure templates from natural language"
print " query Process natural language queries about infrastructure"
print " webhook Process webhook/chat messages"
print " test Test AI connectivity and configuration"
print " config Show current AI configuration"
print " enable Show how to enable AI functionality"
print " disable Show how to disable AI functionality"
print " help Show this help message"
print ""
print "TEMPLATE OPTIONS:"
print " --prompt <text> Natural language description"
print " --template-type <type> Type of template (server, cluster, taskserv)"
print ""
print "QUERY OPTIONS:"
print " --prompt <text> Natural language query"
print " --context <json> Additional context as JSON"
print ""
print "WEBHOOK OPTIONS:"
print " --prompt <text> Message to process"
print " <user_id> User ID for context"
print " <channel> Channel for context"
print ""
print "EXAMPLES:"
print " # Generate a Kubernetes cluster template"
print " ./core/nulib/provisioning ai template --prompt \"3-node Kubernetes cluster with Ceph storage\""
print ""
print " # Query infrastructure status"
print " ./core/nulib/provisioning ai query --prompt \"show all running servers with high CPU\""
print ""
print " # Process chat message"
print " ./core/nulib/provisioning ai webhook --prompt \"deploy redis cluster\" user123 slack"
print ""
print " # Test AI configuration"
print " ./core/nulib/provisioning ai test"
}
# AI-enhanced generate command
export def ai_generate [
type: string
--prompt: string
--template-type: string = "server"
--output: string
]: nothing -> any {
if ($prompt | is-empty) {
error make {msg: "AI generation requires --prompt"}
}
let result = (ai_generate_template $prompt $template_type)
if ($output | is-empty) {
print $result
} else {
$result | save $output
print $"AI generated ($template_type) saved to: ($output)"
}
}
# AI-enhanced query with provisioning context
export def ai_query_infra [
query: string
--infra: string
--provider: string
--output-format: string = "human"
]: nothing -> any {
let context = {
infra: ($infra | default "")
provider: ($provider | default "")
output_format: $output_format
}
let result = (ai_process_query $query $context)
match $output_format {
"json" => { {query: $query, response: $result} | to json }
"yaml" => { {query: $query, response: $result} | to yaml }
_ => { print $result }
}
}
# Enhanced AI query command with intelligent agents
def enhanced_query_command [
prompt: string
context: string
] {
print $"🤖 Enhanced AI Query: ($prompt)"
let result = process_query $prompt --format "summary"
print $result
}
# Show AI system capabilities
def show_ai_capabilities [] {
let caps = get_query_capabilities
print "🤖 Enhanced AI System Capabilities"
print ""
print "📋 Supported Query Types:"
$caps.supported_types | each { |type| print $" • ($type)" }
print ""
print "🤖 Available AI Agents:"
$caps.agents | each { |agent| print $" • ($agent)" }
print ""
print "📊 Output Formats:"
$caps.output_formats | each { |format| print $" • ($format)" }
print ""
print "🚀 Features:"
$caps.features | each { |feature| print $" • ($feature)" }
}
# Show query examples
def show_query_examples [] {
print "💡 Enhanced AI Query Examples"
print ""
print "🏗️ Infrastructure Status:"
print " • \"What servers are currently running?\""
print " • \"Show me the health status of all services\""
print " • \"Which containers are consuming the most resources?\""
print ""
print "⚡ Performance Analysis:"
print " • \"Which services have high CPU usage?\""
print " • \"What's causing slow response times?\""
print " • \"Show me memory usage trends over the last hour\""
print ""
print "💰 Cost Optimization:"
print " • \"How can I reduce my AWS costs?\""
print " • \"Which instances are underutilized?\""
print " • \"Show me the most expensive resources\""
print ""
print "🛡️ Security Analysis:"
print " • \"Are there any security threats detected?\""
print " • \"Show me recent failed login attempts\""
print " • \"What vulnerabilities exist in the system?\""
print ""
print "🔮 Predictive Analysis:"
print " • \"When will I need to scale the database?\""
print " • \"Predict disk space usage for next month\""
print " • \"What failures are likely to occur soon?\""
}
# Process batch queries from file
def process_batch_file [file_path: string] {
if not ($file_path | path exists) {
print $"❌ File not found: ($file_path)"
return
}
let queries = (open $file_path | lines | where { |line| not ($line | is-empty) and not ($line | str starts-with "#") })
print $"📋 Processing ($queries | length) queries from: ($file_path)"
let results = process_batch_queries $queries --format "summary"
$results | enumerate | each { |item|
print $"--- Query ($item.index + 1) ---"
print $item.item
print ""
}
}
# Run AI performance benchmark
def run_ai_benchmark [] {
let benchmark_queries = [
"What's the current CPU usage?"
"Show me error logs from the last hour"
"Which services are consuming high memory?"
"Are there any security alerts?"
"Predict when we'll need more storage"
]
let results = analyze_query_performance $benchmark_queries
print "📊 AI Query Performance Benchmark"
print $"Total Queries: ($results.total_queries)"
print $"Average Duration: ($results.average_duration_ms) ms"
print $"Queries per Second: ($results.queries_per_second | math round -p 2)"
}
# Enhanced AI help command
def enhanced_ai_help_command [] {
print "🤖 Enhanced AI-Powered Provisioning Commands"
print ""
print "USAGE:"
print " ./core/nulib/provisioning ai <ACTION> [OPTIONS]"
print ""
print "ENHANCED ACTIONS:"
print " query Process natural language queries with intelligent agents"
print " chat Interactive AI chat mode"
print " capabilities Show AI system capabilities"
print " examples Show example queries"
print " batch Process batch queries from file"
print " performance Run performance benchmarks"
print ""
print "LEGACY ACTIONS:"
print " template Generate infrastructure templates"
print " webhook Process webhook/chat messages"
print " test Test AI connectivity"
print " config Show AI configuration"
print " enable Enable AI functionality"
print " disable Disable AI functionality"
print ""
print "ENHANCED QUERY EXAMPLES:"
print " # Natural language infrastructure queries"
print " ./core/nulib/provisioning ai query --prompt \"What servers are using high CPU?\""
print " ./core/nulib/provisioning ai query --prompt \"How can I reduce AWS costs?\""
print " ./core/nulib/provisioning ai query --prompt \"Are there any security threats?\""
print ""
print " # Interactive chat mode"
print " ./core/nulib/provisioning ai chat"
print ""
print " # Batch processing"
print " ./core/nulib/provisioning ai batch queries.txt"
print ""
print " # Performance analysis"
print " ./core/nulib/provisioning ai performance"
print ""
print "🚀 New Features:"
print " • Intelligent agent selection"
print " • Natural language processing"
print " • Real-time data integration"
print " • Predictive analytics"
print " • Interactive chat mode"
print " • Batch query processing"
}

View file

@ -0,0 +1,318 @@
#!/usr/bin/env nu
# API Server management for Provisioning System
# Provides HTTP REST API endpoints for infrastructure management
use ../api/server.nu *
use ../api/routes.nu *
use ../lib_provisioning/utils/settings.nu *
export def "main api" [
command?: string # Command: start, stop, status, docs
--port (-p): int = 8080 # Port to run the API server on
--host: string = "localhost" # Host to bind the server to
--enable-websocket # Enable WebSocket support for real-time updates
--enable-cors # Enable CORS for cross-origin requests
--debug (-d) # Enable debug mode
--background (-b) # Run server in background
--config-file: string # Custom configuration file path
--ssl # Enable SSL/TLS (requires certificates)
--cert-file: string # SSL certificate file path
--key-file: string # SSL private key file path
--doc-format: string = "markdown" # Documentation format (markdown, json, yaml)
]: nothing -> nothing {
let cmd = $command | default "start"
match $cmd {
"start" => {
print $"🚀 Starting Provisioning API Server..."
# Validate configuration
let config_valid = validate_api_config --port $port --host $host
if not $config_valid.valid {
error make {
msg: $"Invalid configuration: ($config_valid.errors | str join ', ')"
help: "Please check your configuration and try again"
}
}
# Check dependencies
check_api_dependencies
# Start the server
if $background {
start_api_background --port $port --host $host --enable-websocket $enable_websocket --enable-cors $enable_cors --debug $debug
} else {
start_api_server --port $port --host $host --enable-websocket $enable_websocket --enable-cors $enable_cors --debug $debug
}
}
"stop" => {
print "🛑 Stopping API server..."
stop_api_server --port $port --host $host
}
"status" => {
print "🔍 Checking API server status..."
let health = check_api_health --port $port --host $host
print ($health | table)
}
"docs" => {
print "📚 Generating API documentation..."
generate_api_documentation --format $doc_format
}
"routes" => {
print "🗺️ Listing API routes..."
let routes = get_route_definitions
print ($routes | select method path description | table)
}
"validate" => {
print "✅ Validating API configuration..."
let validation = validate_routes
print ($validation | table)
}
"spec" => {
print "📋 Generating OpenAPI specification..."
let spec = generate_api_spec
print ($spec | to json)
}
_ => {
print_api_help
}
}
}
def validate_api_config [
--port: int
--host: string
]: nothing -> record {
mut errors = []
mut valid = true
# Validate port range
if $port < 1024 or $port > 65535 {
$errors = ($errors | append "Port must be between 1024 and 65535")
$valid = false
}
# Validate host format
if ($host | str contains " ") {
$errors = ($errors | append "Host cannot contain spaces")
$valid = false
}
# Check if port is available
if $valid {
let port_available = (do -i {
http listen $port --host $host --timeout 1 | ignore
false
} | default true)
if not $port_available {
$errors = ($errors | append $"Port ($port) is already in use")
$valid = false
}
}
{
valid: $valid
errors: $errors
port: $port
host: $host
}
}
def check_api_dependencies []: nothing -> nothing {
print "🔍 Checking dependencies..."
# Check Python availability
let python_available = (do -i { python3 --version } | complete | get exit_code) == 0
if not $python_available {
error make {
msg: "Python 3 is required for the API server"
help: "Please install Python 3 and ensure it's available in PATH"
}
}
# Check required environment variables
if ($env.PROVISIONING_PATH? | is-empty) {
print "⚠️ Warning: PROVISIONING_PATH not set, using current directory"
$env.PROVISIONING_PATH = (pwd)
}
print "✅ All dependencies satisfied"
}
def start_api_background [
--port: int
--host: string
--enable-websocket
--enable-cors
--debug
]: nothing -> nothing {
print $"🚀 Starting API server in background on ($host):($port)..."
# Create background process
let server_cmd = $"nu -c 'use ($env.PWD)/core/nulib/api/server.nu; start_api_server --port ($port) --host ($host)'"
if $enable_websocket {
$server_cmd = $server_cmd + " --enable-websocket"
}
if $enable_cors {
$server_cmd = $server_cmd + " --enable-cors"
}
if $debug {
$server_cmd = $server_cmd + " --debug"
}
# Save PID for later management
let pid_file = $"/tmp/provisioning-api-($port).pid"
bash -c $"($server_cmd) & echo $! > ($pid_file)"
sleep 2sec
let health = check_api_health --port $port --host $host
if $health.api_server {
print $"✅ API server started successfully in background"
print $"📍 PID file: ($pid_file)"
print $"🌐 URL: http://($host):($port)"
} else {
print "❌ Failed to start API server"
}
}
def stop_api_server [
--port: int
--host: string
]: nothing -> nothing {
let pid_file = $"/tmp/provisioning-api-($port).pid"
if ($pid_file | path exists) {
let pid = (open $pid_file | str trim)
print $"🛑 Stopping API server (PID: ($pid))..."
try {
kill $pid
rm -f $pid_file
print "✅ API server stopped successfully"
} catch {
print "⚠️ Failed to stop server, trying force kill..."
kill -9 $pid
rm -f $pid_file
print "✅ Server force stopped"
}
} else {
print "⚠️ No running API server found on port ($port)"
# Try to find and kill any Python processes running the API
let python_pids = (ps | where name =~ "python3" and command =~ "provisioning_api_server" | get pid)
if ($python_pids | length) > 0 {
print $"🔍 Found ($python_pids | length) related processes, stopping them..."
$python_pids | each { |pid| kill $pid }
print "✅ Related processes stopped"
}
}
}
def generate_api_documentation [
--format: string = "markdown"
]: nothing -> nothing {
let output_file = match $format {
"markdown" => "api_documentation.md"
"json" => "api_spec.json"
"yaml" => "api_spec.yaml"
_ => "api_documentation.md"
}
match $format {
"markdown" => {
let docs = generate_route_docs
$docs | save --force $output_file
print $"📚 Markdown documentation saved to: ($output_file)"
}
"json" => {
let spec = generate_api_spec
$spec | to json | save --force $output_file
print $"📋 OpenAPI JSON spec saved to: ($output_file)"
}
"yaml" => {
let spec = generate_api_spec
$spec | to yaml | save --force $output_file
print $"📋 OpenAPI YAML spec saved to: ($output_file)"
}
_ => {
print $"❌ Unsupported format: ($format)"
print "Supported formats: markdown, json, yaml"
}
}
}
def print_api_help []: nothing -> nothing {
print "
🚀 Provisioning API Server Management
USAGE:
provisioning api [COMMAND] [OPTIONS]
COMMANDS:
start Start the API server (default)
stop Stop the API server
status Check server status
docs Generate API documentation
routes List all available routes
validate Validate API configuration
spec Generate OpenAPI specification
OPTIONS:
-p, --port <PORT> Port to run server on [default: 8080]
--host <HOST> Host to bind to [default: localhost]
--enable-websocket Enable WebSocket support
--enable-cors Enable CORS headers
-d, --debug Enable debug mode
-b, --background Run in background
--doc-format <FORMAT> Documentation format [default: markdown]
EXAMPLES:
# Start server on default port
provisioning api start
# Start on custom port with debugging
provisioning api start --port 9090 --debug
# Start in background with WebSocket support
provisioning api start --background --enable-websocket
# Generate API documentation
provisioning api docs --doc-format json
# Check server status
provisioning api status
# Stop running server
provisioning api stop
ENDPOINTS:
GET /api/v1/health Health check
GET /api/v1/query Query infrastructure
POST /api/v1/query Complex queries
GET /api/v1/metrics System metrics
GET /api/v1/logs System logs
GET /api/v1/dashboard Dashboard data
GET /api/v1/servers List servers
POST /api/v1/servers Create server
GET /api/v1/ai/query AI-powered queries
For more information, visit: https://docs.provisioning.dev/api
"
}

View file

@ -0,0 +1,120 @@
use ops.nu provisioning_context_options
use ../lib_provisioning/setup *
#> Manage contexts settings
export def "main context" [
task?: string # server (s) | task (t) | service (sv)
name?: string # server (s) | task (t) | service (sv)
--key (-k): string
--value (-v): string
...args # Args for create command
--reset (-r) # Restore defaults
--serverpos (-p): int # Server position in settings
--wait (-w) # Wait servers to be created
--settings (-s): string # Settings path
--outfile (-o): string # Output file
--debug (-x) # Use Debug mode
--xm # Debug with PROVISIONING_METADATA
--xc # Debuc for task and services locally PROVISIONING_DEBUG_CHECK
--xr # Debug for remote servers PROVISIONING_DEBUG_REMOTE
--xld # Log level with DEBUG PROVISIONING_LOG_LEVEL=debug
--metadata # Error with metadata (-xm)
--notitles # not tittles
] {
parse_help_command "context" --task {provisioning_context_options} --end
if $debug { $env.PROVISIONING_DEBUG = true }
let config_path = (setup_config_path)
let default_context_path = ($config_path | path join "default_context.yaml")
let name_context_path = ($config_path | path join $"($name).yaml")
let context_path = ($config_path | path join "context.yaml")
let set_as_default = {
rm -f $context_path
^ln -s $name_context_path $context_path
_print (
$"(_ansi blue_bold)($name)(_ansi reset) set as (_ansi green)default context(_ansi reset)" +
$" in (_ansi default_dimmed)($config_path)(_ansi reset)"
)
}
match $task {
"h" => {
^$"($env.PROVISIONING_NAME)" context --help
_print (provisioning_context_options)
}
"create" | "c" | "new" => {
if $name == null or $name == "" {
_print $"🛑 No (_ansi red)name(_ansi reset) value "
}
if ($name_context_path |path exists) {
_print $"(_ansi blue_bold)($name)(_ansi reset) already in (_ansi default_dimmed)($config_path)(_ansi reset)"
} else {
^cp $default_context_path $name_context_path
open -r $name_context_path | str replace "infra: " $"infra: ($name)" | save -f $name_context_path
_print $"(_ansi blue_bold)($name)(_ansi reset) created in (_ansi default_dimmed)($config_path)(_ansi reset)"
}
do $set_as_default
},
"default" | "d" => {
if $name == null or $name == "" {
_print $"🛑 No (_ansi red)name(_ansi reset) value "
exit 1
}
if not ($name_context_path | path exists) {
_print $"🛑 No (_ansi red)($name)(_ansi reset) found in (_ansi default_dimmed)($config_path)(_ansi reset) "
exit 1
}
do $set_as_default
},
"remove" | "r" => {
if $name == null {
_print $"🛑 No (_ansi red)name(_ansi reset) value "
exit 1
}
if $name == "" or not ( $name_context_path | path exists) {
_print $"🛑 context path (_ansi blue_bold)($name)(_ansi reset) not found "
exit 1
}
let context = (setup_user_context $name)
let curr_infra = ($context | get -o "infra")
if $curr_infra == $name {
_print (
$"(_ansi blue_bold)($name)(_ansi reset) removed as (_ansi green)default context(_ansi reset) " +
$" in (_ansi default_dimmed)($config_path)(_ansi reset)"
)
}
rm -f $name_context_path $context_path
_print $"(_ansi blue_bold)($name)(_ansi reset) context removed "
},
"edit" | "e" => {
let editor = ($env | get -o EDITOR | default "vi")
let config_path = (setup_user_context_path $name)
^$editor $config_path
},
"view" | "v" => {
_print ((setup_user_context $name) | table -e)
},
"set" | "s" => {
let context = (setup_user_context $name)
let curr_value = ($context | get -o $key)
if $curr_value == null {
_print $"🛑 invalid ($key) in setup "
exit 1
}
if $curr_value == $value {
_print $"🛑 ($key) ($value) already set "
exit 1
}
# if $context != null and ( $context.infra | path exists) { return $context.infra }
let new_context = ($context | update $key $value)
setup_save_context $new_context
},
"i" | "install" => {
install_config $reset --context
},
_ => {
invalid_task "context" ($task | default "") --end
},
}
end_run $" create ($task) "
}

View file

@ -0,0 +1,47 @@
# -> Create infrastructure and services (see TARGETS)
export def "main create" [
target?: string # server (s) | taskserv (t) | cluster (c)
name?: string # Target name in settings
...args # Args for create command
--serverpos (-p): int # Server position in settings
--check (-c) # Only check mode no servers will be created
--wait (-w) # Wait servers to be created
--infra (-i): string # Infra path
--settings (-s): string # Settings path
--outfile (-o): string # Output file
--debug (-x) # Use Debug mode
--xm # Debug with PROVISIONING_METADATA
--xc # Debuc for task and services locally PROVISIONING_DEBUG_CHECK
--xr # Debug for remote servers PROVISIONING_DEBUG_REMOTE
--xld # Log level with DEBUG PROVISIONING_LOG_LEVEL=debug
--metadata # Error with metadata (-xm)
--notitles # not tittles
--out: string # Print Output format: json, yaml, text (default)
]: nothing -> nothing {
if ($out | is-not-empty) {
$env.PROVISIONING_OUT = $out
$env.PROVISIONING_NO_TERMINAL = true
}
parse_help_command "create" --end
if $debug { $env.PROVISIONING_DEBUG = true }
let use_debug = if $debug or $env.PROVISIONING_DEBUG { "-x" } else { "" }
match $target {
"server"| "servers" | "s" => {
^$"($env.PROVISIONING_NAME)" $use_debug -mod "server" ($env.PROVISIONING_ARGS | str replace $target '') --notitles
},
"taskserv" | "taskservs" | "task" | "tasks" | "t" => {
let ops = ($env.PROVISIONING_ARGS | split row " ")
let task = ($ops | get -o 0 | default "")
^$"($env.PROVISIONING_NAME)" $use_debug -mod "taskserv" $task ($env.PROVISIONING_ARGS | str replace $"($task) ($target)" '') --notitles
},
"clusters"| "clusters" | "cl" => {
^$"($env.PROVISIONING_NAME)" $use_debug -mod "cluster" ($env.PROVISIONING_ARGS | str replace $target '') --notitles
},
_ => {
invalid_task "create" ($target | default "") --end
exit
},
}
}

View file

@ -0,0 +1,152 @@
# Enhanced create command with better validation and logging
export def "main create enhanced" [
target?: string # server (s) | taskserv (t) | cluster (c)
name?: string # Target name in settings
...args # Args for create command
--serverpos (-p): int # Server position in settings
--check (-c) # Only check mode no servers will be created
--wait (-w) # Wait servers to be created
--infra (-i): string # Infra path
--settings (-s): string # Settings path
--outfile (-o): string # Output file
--debug (-x) # Use Debug mode
--dry-run # Show what would be done without executing
--verbose (-v) # Verbose output
]: nothing -> nothing {
# Set debug mode
if $debug {
$env.PROVISIONING_DEBUG = true
print $"🐛 Debug mode enabled"
}
# Set output format
if ($outfile | is-not-empty) {
$env.PROVISIONING_OUT = $outfile
$env.PROVISIONING_NO_TERMINAL = true
}
# Validate target parameter
if ($target | is-empty) {
print $"🛑 Target parameter is required"
print "💡 Valid targets: server(s), taskserv(t), cluster(cl)"
print "💡 Example: provisioning create enhanced server my-server"
exit 1
}
# Validate target value
let valid_targets = ["server", "servers", "s", "taskserv", "taskservs", "task", "tasks", "t", "clusters", "cl"]
let is_valid_target = ($valid_targets | where {|t| $t == $target} | length) > 0
if not $is_valid_target {
print $"🛑 Invalid target: ($target)"
print $"💡 Valid targets: ($valid_targets | str join ', ')"
exit 1
}
# Log operation start
print $""
print $"📋 Creating ($target)"
print $"─────────────────────────────────────────────────────────────"
print $" Target: ($target)"
print $" Name: ($name | default 'default')"
if $dry_run {
print $"⚠️ DRY RUN MODE - No actual changes will be made"
}
# Validate settings path if provided
if ($settings | is-not-empty) {
if not ($settings | path exists) {
print $"🛑 Settings file not found: ($settings)"
exit 1
}
print $" Using settings: ($settings)"
}
# Validate infra path if provided
if ($infra | is-not-empty) {
if not ($infra | path exists) {
print $"🛑 Infra path not found: ($infra)"
exit 1
}
print $" Using infra: ($infra)"
}
# Execute the appropriate creation command
let use_debug = if $debug { "-x" } else { "" }
try {
match $target {
"server"| "servers" | "s" => {
print $" 📌 Creating server"
if $dry_run {
print $" Would execute: server creation command"
} else {
^$"($env.PROVISIONING_NAME)" $use_debug -mod "server" ($env.PROVISIONING_ARGS | str replace $target '') --notitles
}
},
"taskserv" | "taskservs" | "task" | "tasks" | "t" => {
print $" 📌 Creating taskserv"
let ops = ($env.PROVISIONING_ARGS | split row " ")
let task = ($ops | get -o 0 | default "")
if $dry_run {
print $" Would execute: taskserv creation for task ($task)"
} else {
^$"($env.PROVISIONING_NAME)" $use_debug -mod "taskserv" $task ($env.PROVISIONING_ARGS | str replace $"($task) ($target)" '') --notitles
}
},
"clusters"| "clusters" | "cl" => {
print $" 📌 Creating cluster"
if $dry_run {
print $" Would execute: cluster creation command"
} else {
^$"($env.PROVISIONING_NAME)" $use_debug -mod "cluster" ($env.PROVISIONING_ARGS | str replace $target '') --notitles
}
}
}
if not $dry_run {
print $"✅ Successfully created ($target)"
} else {
print $"✅ Dry run completed successfully"
}
} catch {|err|
print $"🛑 Failed to create ($target)"
print $" Details: ($err.msg)"
exit 1
}
}
# Helper function to validate server configuration
export def validate-server-config [
server_config: record
]: bool {
let required_fields = ["hostname", "ip", "provider"]
let missing_fields = ($required_fields | where {|field|
($server_config | get -o $field | is-empty)
})
if ($missing_fields | length) > 0 {
print $"🛑 Missing required server configuration fields"
$missing_fields | each {|field|
print $" - ($field)"
}
return false
}
print $"✅ Server configuration is valid"
true
}
# Helper function to show creation progress
export def show-creation-progress [
current: int
total: int
operation: string
] {
let percent = (($current * 100) / $total)
print $"📊 ($operation) ($percent)%"
}

View file

@ -0,0 +1,157 @@
#!/usr/bin/env nu
# Dashboard Management Commands
# Interactive dashboards and data visualization
use ../dashboard/marimo_integration.nu *
# Main dashboard command
export def main [
subcommand?: string
...args: string
]: [string, ...string] -> nothing {
if ($subcommand | is-empty) {
print "📊 Systems Provisioning Dashboard"
print ""
print "Interactive dashboards for infrastructure monitoring and analytics"
print ""
print "Usage: provisioning dashboard <subcommand> [args...]"
print ""
print "Subcommands:"
print " create [template] [name] - Create interactive dashboard"
print " start <name> [port] - Start dashboard server"
print " list - List available dashboards"
print " export <name> [output] - Export dashboard to HTML"
print " demo - Create and start demo dashboard"
print " status - Show dashboard system status"
print ""
print "Templates:"
print " monitoring - Real-time logs and metrics"
print " infrastructure - Server and cluster overview"
print " full - Complete observability dashboard"
print " ai-insights - AI-powered analytics and predictions"
print ""
print "Examples:"
print " provisioning dashboard demo"
print " provisioning dashboard create monitoring my-dashboard"
print " provisioning dashboard start my-dashboard 8080"
print ""
return
}
match $subcommand {
"create" => {
marimo_integration create ...$args
}
"start" => {
marimo_integration start ...$args
}
"list" => {
marimo_integration list
}
"export" => {
marimo_integration export ...$args
}
"demo" => {
create_demo_dashboard
}
"status" => {
show_dashboard_status
}
_ => {
print $"❌ Unknown subcommand: ($subcommand)"
print "Run 'provisioning dashboard' for help"
}
}
}
# Create and start a demo dashboard
def create_demo_dashboard []: nothing -> nothing {
print "🚀 Creating demo dashboard with live data..."
# Check if API server is running
let api_status = check_api_server_status
if not $api_status {
print "⚠️ API server not running. Starting API server..."
start_api_server --port 3000 --background
sleep 3sec
}
# Create AI insights dashboard
marimo_integration create ai-insights demo-dashboard
print ""
print "🎉 Demo dashboard created and started!"
print "📊 Open your browser to: http://localhost:8080"
print ""
print "Features available:"
print " 🔍 Real-time log analysis"
print " 📈 System metrics visualization"
print " 🏗️ Infrastructure topology"
print " 🤖 AI-powered insights and predictions"
print " 📊 Interactive charts and tables"
print ""
}
# Check API server status
def check_api_server_status []: nothing -> bool {
try {
http get "http://localhost:3000/health" | get status == "healthy"
} catch {
false
}
}
# Start API server in background
def start_api_server [--port: int = 3000, --background = false]: nothing -> nothing {
if $background {
nu -c "use ../api/server.nu *; start_api_server --port $port" &
} else {
use ../api/server.nu *
start_api_server --port $port
}
}
# Show dashboard system status
def show_dashboard_status []: nothing -> nothing {
print "📊 Dashboard System Status"
print ""
# Check Marimo installation
let marimo_available = check_marimo_available
let marimo_status = if $marimo_available { "✅ Installed" } else { "❌ Not installed" }
print $"Marimo: ($marimo_status)"
# Check API server
let api_status = check_api_server_status
let api_display = if $api_status { "✅ Running" } else { "❌ Stopped" }
print $"API Server: ($api_display)"
# List dashboards
let dashboards = list_dashboards
print $"Dashboards: ($dashboards | length) available"
if ($dashboards | length) > 0 {
print ""
print "Available dashboards:"
$dashboards | select name modified | table
}
# System resources
print ""
print "System Resources:"
let mem_info = (sys mem)
print $"Memory: ($mem_info.used | into string) / ($mem_info.total | into string) used"
print ""
print "Quick start:"
if not $marimo_available {
print "1. Install Marimo: provisioning dashboard create install"
}
if not $api_status {
print "2. Start API: provisioning api start"
}
print "3. Create dashboard: provisioning dashboard demo"
}

View file

@ -0,0 +1,79 @@
def prompt_delete [
target: string
target_name: string
yes: bool
name?: string
]: nothing -> string {
match $name {
"h" | "help" => {
^($env.PROVISIONING_NAME) "-mod" $target "--help"
exit 0
}
}
if not $yes or not (($env.PROVISIONING_ARGS? | default "") | str contains "--yes") {
_print ( $"To (_ansi red_bold)delete ($target_name) (_ansi reset) " +
$" (_ansi green_bold)($name)(_ansi reset) type (_ansi green_bold)yes(_ansi reset) ? "
)
let user_input = (input --numchar 3)
if $user_input != "yes" and $user_input != "YES" {
exit 1
}
$name
} else {
$env.PROVISIONING_ARGS = ($env.PROVISIONING_ARGS? | find -v "yes")
($name | default "" | str replace "yes" "")
}
}
# -> Delete infrastructure and services
export def "main delete" [
target?: string # server (s) | task (t) | service (sv)
name?: string # target name in settings
...args # Args for create command
--serverpos (-p): int # Server position in settings
--keepstorage # Keep storage
--yes (-y) # confirm delete
--wait (-w) # Wait servers to be created
--infra (-i): string # Infra path
--settings (-s): string # Settings path
--outfile (-o): string # Output file
--debug (-x) # Use Debug mode
--xm # Debug with PROVISIONING_METADATA
--xc # Debuc for task and services locally PROVISIONING_DEBUG_CHECK
--xr # Debug for remote servers PROVISIONING_DEBUG_REMOTE
--xld # Log level with DEBUG PROVISIONING_LOG_LEVEL=debug
--metadata # Error with metadata (-xm)
--notitles # not tittles
--out: string # Print Output format: json, yaml, text (default)
]: nothing -> nothing {
if ($out | is-not-empty) {
$env.PROVISIONING_OUT = $out
$env.PROVISIONING_NO_TERMINAL = true
}
parse_help_command "delete" --end
if $debug { $env.PROVISIONING_DEBUG = true }
let use_debug = if $debug or $env.PROVISIONING_DEBUG { "-x" } else { "" }
match $target {
"server"| "servers" | "s" => {
prompt_delete "server" "servers" $yes $name
^$"($env.PROVISIONING_NAME)" $use_debug -mod "server" ($env.PROVISIONING_ARGS | str replace $target '') --yes --notitles
},
"storage" => {
prompt_delete "server" "storage" $yes $name
^$"($env.PROVISIONING_NAME)" $use_debug -mod "server" $env.PROVISIONING_ARGS --yes --notitles
},
"taskserv" | "taskservs" | "t" => {
prompt_delete "taskserv" "tasks/services" $yes $name
^$"($env.PROVISIONING_NAME)" $use_debug -mod "tasksrv" ($env.PROVISIONING_ARGS | str replace $target '') --yes --notitles
},
"clusters"| "clusters" | "cl" => {
prompt_delete "cluster" "cluster" $yes $name
^$"($env.PROVISIONING_NAME)" $use_debug -mod "cluster" ($env.PROVISIONING_ARGS | str replace $target '') --yes --notitles
},
_ => {
invalid_task "delete" ($target | default "") --end
exit
},
}
}

View file

@ -0,0 +1,94 @@
# Extensions Management Commands
use ../lib_provisioning/extensions *
# List available extensions
export def "main extensions list" [
--type: string = "" # Filter by type: provider, taskserv, or all
--helpinfo (-h) # Show help
]: nothing -> nothing {
if $helpinfo {
print "List available extensions"
return
}
match $type {
"provider" => {
print "Available Provider Extensions:"
list-providers
}
"taskserv" => {
print "Available TaskServ Extensions:"
list-taskservs
}
_ => {
print "Available Extensions:"
print "\nProviders:"
list-providers
print "\nTaskServs:"
list-taskservs
}
}
}
# Show extension details
export def "main extensions show" [
name: string # Extension name
--helpinfo (-h) # Show help
]: nothing -> nothing {
if $helpinfo {
print "Show details for a specific extension"
return
}
let provider = (get-provider $name)
let taskserv = (get-taskserv $name)
if ($provider | is-not-empty) {
print $"Provider Extension: ($name)"
$provider
} else if ($taskserv | is-not-empty) {
print $"TaskServ Extension: ($name)"
$taskserv
} else {
print $"Extension '($name)' not found"
}
}
# Initialize extensions
export def "main extensions init" [
--helpinfo (-h) # Show help
]: nothing -> nothing {
if $helpinfo {
print "Initialize extension registry"
return
}
init-registry
print "Extension registry initialized"
}
# Show current profile
export def "main profile show" [
--helpinfo (-h) # Show help
]: nothing -> nothing {
if $helpinfo {
print "Show current access profile"
return
}
show-profile | table
}
# Create example profiles
export def "main profile create-examples" [
--helpinfo (-h) # Show help
]: nothing -> nothing {
if $helpinfo {
print "Create example profile files"
return
}
create-example-profiles
}

View file

@ -0,0 +1,209 @@
#use utils *
#use defs *
use lib_provisioning *
# - > Query infrastructure and services
export def "main generate" [
#hostname?: string # Server hostname in settings
...args # Args for create command
--infra (-i): string # Infra path
--settings (-s): string # Settings path
--serverpos (-p): int # Server position in settings
--check (-c) # Only check mode no servers will be created
--wait (-w) # Wait servers to be created
--outfile: string # Optional output format: json | yaml | csv | text | md | nuon
--find (-f): string # Optional generate find a value (empty if no value found)
--cols (-l): string # Optional generate columns list separated with comma
--template(-t): string # Template path or name in PROVISION_KLOUDS_PATH
--ips # Optional generate get IPS only for target "servers-info"
--prov: string # Optional provider name to filter generate
--debug (-x) # Use Debug mode
--xm # Debug with PROVISIONING_METADATA
--xc # Debuc for task and services locally PROVISIONING_DEBUG_CHECK
--xr # Debug for remote servers PROVISIONING_DEBUG_REMOTE
--xld # Log level with DEBUG PROVISIONING_LOG_LEVEL=debug
--metadata # Error with metadata (-xm)
--notitles # not tittles
--helpinfo (-h) # For more details use options "help" (no dashes)
--out: string # Print Output format: json, yaml, text (default)
]: nothing -> nothing {
if ($out | is-not-empty) {
$env.PROVISIONING_OUT = $out
$env.PROVISIONING_NO_TERMINAL = true
}
if $helpinfo {
_print (provisioning_generate_options)
if not $env.PROVISIONING_DEBUG { end_run "" }
exit
}
parse_help_command "generate" --end
if $debug { $env.PROVISIONING_DEBUG = true }
#use defs [ load_settings ]
let curr_settings = if $infra != null {
if $settings != null {
(load_settings --infra $infra --settings $settings)
} else {
(load_settings --infra $infra)
}
} else {
if $settings != null {
(load_settings --settings $settings)
} else {
(load_settings false true)
}
}
#let cmd_template = if ($template | is-empty ) {
# ($args | get -o 0 | default "")
#} else { $template }
#let str_out = if $outfile == null { "none" } else { $outfile }
let str_out = if $out == null { "" } else { $out }
let str_cols = if $cols == null { "" } else { $cols }
let str_find = if $find == null { "" } else { $find }
let str_template = if $template == null { "" } else { $template }
let cmd_target = if ($args | length) > 0 { ($args| get 0) } else { "" }
$env.PROVISIONING_MODULE = "generate"
let ops = $"($env.PROVISIONING_ARGS? | default "") " | str replace $env.PROVISIONING_MODULE "" | str replace $" ($cmd_target) " "" | str trim
#generate_provision $args $curr_settings $str_template
match $cmd_target {
"new" | "n" => {
let args_list = if ($args | length) > 0 {
($args| skip 1)
} else { [] }
generate_provision $args_list $curr_settings $str_template
},
"server" | "servers" => {
#use utils/format.nu datalist_to_format
_print (datalist_to_format $str_out
(mw_generate_servers $curr_settings $str_find $cols --prov $prov --serverpos $serverpos)
)
},
"server-status" | "servers-status" | "server-info" | "servers-info" => {
let list_cols = if ($cmd_target | str contains "status") {
if ($str_cols | str contains "state") { $str_cols } else { $str_cols + ",state" }
} else {
$str_cols
}
# not use $str_cols to filter previous $ips selection
(out_data_generate_info
$curr_settings
(mw_servers_info $curr_settings $str_find --prov $prov --serverpos $serverpos)
#(mw_servers_info $curr_settings $find $cols --prov $prov --serverpos $serverpos)
$list_cols
$str_out
$ips
)
},
"servers-def" | "server-def" => {
let data = if $str_find != "" { ($curr_settings.data.servers | find $find) } else { $curr_settings.data.servers}
(out_data_generate_info
$curr_settings
$data
$str_cols
$str_out
false
)
},
"def" | "defs" => {
let data = if $str_find != "" { ($curr_settings.data | find $find) } else { $curr_settings.data}
(out_data_generate_info
$curr_settings
[ $data ]
$str_cols
$str_out
false
)
}
_ => {
(throw-error $"🛑 ($env.PROVISIONING_NAME) generate " $"Invalid option (_ansi red)($cmd_target)(_ansi reset)"
$"($env.PROVISIONING_NAME) generate --target ($cmd_target)" --span (metadata $cmd_target).span
)
}
}
cleanup ($curr_settings | get -o wk_path | default "")
if $outfile == null { end_run "generate" }
}
export def generate_new_infra [
args: list
template: string
]: nothing -> record {
let infra_path = ($args | get -o 0 | default "")
let infra_name = ($infra_path | path basename)
let target_path = if ($infra_path | str contains "/") {
$infra_path
} else if ($env.PROVISIONING_INFRA_PATH | path exists) and not ($env.PROVISIONING_INFRA_PATH | path join $infra_path | path exists) {
($env.PROVISIONING_INFRA_PATH | path join $infra_path)
} else {
$infra_path
}
if ($target_path | path exists) {
_print $"🛑 Path (_ansi yellow_bold)($target_path)(_ansi reset) already exits"
return
}
^mkdir -p $target_path
_print $"(_ansi green)($infra_name)(_ansi reset) created in (_ansi green)($target_path | path dirname)(_ansi reset)"
_print $"(_ansi green)($infra_name)(_ansi reset) ... "
let template_path = if ($template | is-empty) {
($env.PROVISIONING | path join $env.PROVISIONING_GENERATE_DIRPATH | path join "default")
} else if ($template | str contains "/") and ($template | path exists) {
$template
} else if ($env.PROVISIONING_INFRA_PATH | path join $template | path exists) {
($env.PROVISIONING_INFRA_PATH | path join $template)
}
let new_created = if not ($target_path | path join "settings.k" | path exists) {
^cp -pr ...(glob ($template_path | path join "*")) ($target_path)
_print $"copy (_ansi green)($template)(_ansi reset) to (_ansi green)($infra_name)(_ansi reset)"
true
} else {
false
}
{ path: $target_path, name: $infra_name, created: $new_created }
}
export def generate_provision [
args: list
settings: record
template: string
]: nothing -> nothing {
let generated_infra = if ($settings | is-empty) {
if ($args | is-empty) {
(throw-error $"🛑 ($env.PROVISIONING_NAME) generate " $"Invalid option (_ansi red)no settings and path found(_ansi reset)"
$"($env.PROVISIONING_NAME) generate " --span (metadata $settings).span
)
} else {
generate_new_infra $args $template
}
}
if ($generated_infra | is-empty) {
(throw-error $"🛑 ($env.PROVISIONING_NAME) generate " $"Invalid option (_ansi red)no settings and path found(_ansi reset)"
$"($env.PROVISIONING_NAME) generate " --span (metadata $settings).span
)
}
generate_data_def $env.PROVISIONING $generated_infra.name $generated_infra.path $generated_infra.created
}
def out_data_generate_info [
settings: record
data: list
cols: string
outfile: string
ips: bool
]: nothing -> nothing {
if ($data | get -o 0 | is-empty) {
if $env.PROVISIONING_DEBUG { print $"🛑 ($env.PROVISIONING_NAME) generate (_ansi red)no data found(_ansi reset)" }
_print ""
return
}
let sel_data = if ($cols | is-not-empty) {
$data | select -o ($cols | split row ",")
} else {
$data
}
#use ../../../providers/prov_lib/middleware.nu mw_servers_ips
#use utils/format.nu datalist_to_format
print (datalist_to_format $outfile $sel_data)
# let data_ips = (($data).ip_addresses? | flatten | find "public")
if $ips {
let ips_result = (mw_servers_ips $settings $data)
print $ips_result
}
}

View file

@ -0,0 +1,24 @@
export use ops.nu *
export use query.nu *
export use create.nu *
export use delete.nu *
export use status.nu *
export use update.nu *
export use generate.nu *
export use tools.nu *
export use sops.nu *
export use secrets.nu *
export use ai.nu *
export use contexts.nu *
export use extensions.nu *
#export use main.nu *
# export use server.nu *
#export use task.nu *
#export use server/server_delete.nu *
#export module instances.nu

View file

@ -0,0 +1,207 @@
export def provisioning_options [
]: nothing -> string {
let target_items = $"(_ansi blue)server(_ansi reset) | (_ansi yellow)tasks(_ansi reset) | (_ansi purple)cluster(_ansi reset)"
(
$"(_ansi green_bold)Options(_ansi reset):\n" +
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) sed - to edit content from a SOPS file \n" +
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) ssh - to config and get SSH settings for servers\n" +
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) list [items] - to list items: " +
$"[ (_ansi green)providers(_ansi reset) p | (_ansi green)tasks(_ansi reset) t | (_ansi green)nfra(_ansi reset) k ]\n" +
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) nu - to run a nushell in ($env.PROVISIONING) path\n" +
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) qr - to get ($env.PROVISIONING_URL) QR code\n" +
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) context - to change (_ansi blue)context(_ansi reset) settings. " +
$"(_ansi default_dimmed)use context -h for help(_ansi reset)\n" +
$"\n(_ansi green_bold)Targets(_ansi reset):\n" +
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) generate - to generate (_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) use one option: (_ansi green)provision(_ansi reset) " +
$"| ($target_items)\n" +
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) create - to create use one option: ($target_items)\n" +
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) delete - to delete use one option: ($target_items)\n" +
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) cst - to create (_ansi blue)Servers(_ansi reset) and (_ansi yellow)Tasks(_ansi reset). " +
$"Alias from (_ansi blue_bold)create-servers-tasks(_ansi reset)\n" +
$"\n(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) deploy-sel - to sel (_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) " +
$"(_ansi cyan_bold)deployments info(_ansi reset) --onsel [ (_ansi yellow_bold)e(_ansi reset)dit | " +
$"(_ansi yellow_bold)v(_ansi reset)iew | (_ansi yellow_bold)l(_ansi reset)ist | (_ansi yellow_bold)t(_ansi reset)ree " +
$"(_ansi yellow_bold)c(_ansi reset)ode | (_ansi yellow_bold)s(_ansi reset)hell | (_ansi yellow_bold)n(_ansi reset)u ]\n" +
$"\n(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) deploy-rm - to remove (_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) " +
$"(_ansi cyan_bold)deployments infos(_ansi reset)\n" +
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) destroy - to remove (_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) " +
$"(_ansi cyan_bold)deployments infos(_ansi reset) and (_ansi green_bold)servers(_ansi reset) with confirmation or add '--yes'\n" +
$"\n(_ansi green_bold)Targets(_ansi reset):\n" +
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) server - On Servers or instances \n" +
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) taskserv - On Task Services for servers: settings, services\n" +
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) cluster - On Cluster for provisioning\n" +
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) infra - On Infrastructures for provisioning\n" +
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) validate - Infrastructure validation and review tool\n" +
$"\n(_ansi green_bold)Others(_ansi reset):\n" +
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) show - To show (_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) settings and data \n" +
$"(_ansi default_dimmed)Options:(_ansi reset) (_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) show [ settings | defsettings | servers | serverdefs | costs | alldata | data ] \n" +
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) new - To create a new (_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) Infrastructure \n" +
$"\n(_ansi default_dimmed)To get help on Targets use:(_ansi reset) (_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) [target-name] help\n" +
$"\n(_ansi default_dimmed)NOTICE: Most of Options and Targets have a shortcut by using a single dash and a letter(_ansi reset)\n" +
$"(_ansi default_dimmed)example(_ansi reset) -h (_ansi default_dimmed)for(_ansi reset)" +
$" --helpinfo (_ansi default_dimmed)or(_ansi reset) help" +
$" (_ansi default_dimmed)even it can simply be used as(_ansi reset) h \n"
)
}
export def provisioning_context_options [
]: nothing -> string {
(
$"(_ansi green_bold)Context options(_ansi reset):\n" +
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) install - to install (_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) (_ansi yellow)context(_ansi reset) \n" +
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) view - to view (_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) (_ansi yellow)context(_ansi reset)\n" +
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) default [name] - to set default as [name] \n" +
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) remove [name] - to remove [name] from (_ansi yellow)context(_ansi reset)\n" +
$"\n(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) set [name] -k [key] -v [value] - to set (_ansi green)[key] = [value](_ansi reset) in [name] (_ansi yellow)context(_ansi reset)"
)
}
export def provisioning_setup_options [
]: nothing -> string {
(
$"(_ansi green_bold)Setup options(_ansi reset):\n" +
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) providers - to view (_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) (_ansi yellow)context(_ansi reset) use 'check' or 'help'\n" +
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) tools - to install (_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) (_ansi yellow)tools(_ansi reset) use 'check' or 'help'\n" +
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) versions - to generate (_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) (_ansi yellow)tools versions file (_ansi reset)\n" +
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) midddleware - to generate (_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) (_ansi yellow)providers middleware library(_ansi reset)\n" +
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) context - to create (_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) (_ansi yellow)context file(_ansi reset)\n" +
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) defaults - to create (_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) (_ansi yellow)defaults file(_ansi reset)"
)
}
export def provisioning_infra_options [
]: nothing -> string {
(
$"(_ansi green_bold)Cloud options(_ansi reset):\n" +
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) view - to view (_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) (_ansi yellow)context(_ansi reset)"
)
}
export def provisioning_tools_options [
]: nothing -> string {
(
$"(_ansi green_bold)Tools options(_ansi reset):\n" +
$"(_ansi blue)($env.PROVISIONING_NAME) tools(_ansi reset) - to check (_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) (_ansi yellow)tools(_ansi reset) and versions\n" +
$"(_ansi blue)($env.PROVISIONING_NAME) tools(_ansi reset) check - to check (_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) (_ansi yellow)tools(_ansi reset) and versions\n" +
$"(_ansi blue)($env.PROVISIONING_NAME) tools(_ansi reset) install - to install(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) (_ansi yellow)tools(_ansi reset)\n" +
$"(_ansi blue)($env.PROVISIONING_NAME) tools(_ansi reset) show - to show (_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) (_ansi yellow)tools(_ansi reset) info \n" +
$"(_ansi blue)($env.PROVISIONING_NAME) tools(_ansi reset) show providers - to show (_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) (_ansi yellow)providers (_ansi reset) info \n" +
$"(_ansi blue)($env.PROVISIONING_NAME) tools(_ansi reset) show all - to show (_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) (_ansi yellow)tools and providers (_ansi reset) info \n" +
$"(_ansi blue)($env.PROVISIONING_NAME) tools(_ansi reset) info - alias (_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) (_ansi cyan)tools show(_ansi reset) \n" +
$"\n(_ansi blue)($env.PROVISIONING_NAME) tools(_ansi reset) (_ansi cyan)[install | check | show](_ansi reset) commmands support to add specifict (_ansi green)'tool-name'(_ansi reset) at the end, " +
$"\n(_ansi blue)($env.PROVISIONING_NAME) tools(_ansi reset) (_ansi cyan)show or info(_ansi reset) commmands support to add specifict (_ansi green)'provider-name'(_ansi reset) at the end, " +
$"by default uses (_ansi green)'all'(_ansi reset)" +
$"\n(_ansi blue)($env.PROVISIONING_NAME) tools(_ansi reset) (_ansi green)'tool-name'(_ansi reset) to check tool installation and version"
)
}
export def provisioning_generate_options [
]: nothing -> string {
(
$"(_ansi green_bold)Generate options(_ansi reset):\n" +
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) (_ansi yellow)generate new [name-or-path](_ansi reset) - to create a new (_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) (_ansi yellow)directory(_ansi reset)" +
$"\nif '[name-or-path]' is not relative or full path it will be created in (_ansi blue)($env.PROVISIONING_INFRA_PATH | default "")(_ansi reset) " +
$"\nadd (_ansi blue)--template [name](_ansi reset) to (_ansi cyan)copy(_ansi reset) from existing (_ansi green)template 'name'(_ansi reset) " +
$"\ndefault (_ansi blue)template(_ansi reset) to use (_ansi cyan)($env.PROVISIONING | path join $env.PROVISIONING_GENERATE_DIRPATH | path join "default")(_ansi reset)"
)
}
export def provisioning_show_options [
]: nothing -> string {
(
$"(_ansi green_bold)Show options(_ansi reset):\n" +
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) (_ansi yellow)show [options](_ansi reset) - To show (_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) settings and data (_ansi yellow)(_ansi reset)" +
$"\n(_ansi blue)settings (_ansi reset) to (_ansi cyan)get(_ansi reset) (_ansi green)settings(_ansi reset) " +
$"\n(_ansi blue)defsettings (_ansi reset) to (_ansi cyan)get(_ansi reset) (_ansi green)def settings content (_ansi reset) " +
$"\n(_ansi blue)servers (_ansi reset) to (_ansi cyan)get(_ansi reset) (_ansi green)servers(_ansi reset) " +
$"\n(_ansi blue)defservers (_ansi reset) to (_ansi cyan)get(_ansi reset) (_ansi green)def servers content (_ansi reset) " +
$"\n(_ansi blue)costs (_ansi reset) to (_ansi cyan)get(_ansi reset) (_ansi green) prices or costs (_ansi reset) " +
$"\n(_ansi blue)alldata (_ansi reset) to (_ansi cyan)get(_ansi reset) (_ansi green) all data settings and prices or costs (_ansi reset) " +
$"\n(_ansi blue)data (_ansi reset) to (_ansi cyan)get(_ansi reset) (_ansi green) data settings (_ansi reset) " +
$"\nby adding (_ansi blue)--out(_ansi reset) (_ansi cyan)[ json | yaml | toml ](_ansi reset) it can be used ad a kind of API source" +
$"\nby adding (_ansi blue)--view(_ansi reset) with (_ansi blue)--out(_ansi reset) option, content is formated with highlight"
)
}
export def provisioning_validate_options [
]: nothing -> string {
print "Infrastructure Validation & Review Tool"
print "========================================"
print ""
print "Validates KCL/YAML configurations, checks best practices, and generates reports"
print ""
print "USAGE:"
print $" ($env.PROVISIONING_NAME) validate [SUBCOMMAND] [INFRA_PATH] [OPTIONS]"
print ""
print "SUBCOMMANDS:"
print " (none) Full validation with customizable options"
print " quick Quick validation focusing on errors and critical issues"
print " ci CI/CD optimized validation with structured output"
print " full Comprehensive validation including info-level checks"
print " agent Agent/automation interface with JSON output"
print " rules List all available validation rules"
print " test Run validation system self-tests"
print " help Show detailed help information"
print ""
print "ARGUMENTS:"
print " INFRA_PATH Path to infrastructure configuration (default: current directory)"
print ""
print "OPTIONS:"
print " -f, --fix Auto-fix issues where possible"
print " -r, --report FORMAT Report format: md, yaml, json, all (default: md)"
print " -o, --output DIR Output directory (default: ./validation_results)"
print " -s, --severity LEVEL Minimum severity: info, warning, error, critical (default: warning)"
print " --ci CI/CD mode (exit codes, no colors, minimal output)"
print " -d, --dry-run Show what would be fixed without actually fixing"
print " --rules RULES Comma-separated list of specific rules to run"
print " --exclude RULES Comma-separated list of rules to exclude"
print " -v, --verbose Verbose output (show all details)"
print " -h, --help Show detailed help"
print ""
print "EXIT CODES:"
print " 0 All validations passed"
print " 1 Critical errors found (blocks deployment)"
print " 2 Errors found (should be fixed)"
print " 3 Only warnings found"
print " 4 Validation system error"
print ""
print "VALIDATION RULES:"
print " VAL001 YAML Syntax Validation (critical)"
print " VAL002 KCL Compilation Check (critical)"
print " VAL003 Unquoted Variable References (error, auto-fixable)"
print " VAL004 Required Fields Validation (error)"
print " VAL005 Resource Naming Conventions (warning, auto-fixable)"
print " VAL006 Basic Security Checks (error)"
print " VAL007 Version Compatibility Check (warning)"
print " VAL008 Network Configuration Validation (error)"
print ""
print "Legend: Auto-fixable rules can be automatically corrected with --fix"
print ""
print "EXAMPLES:"
print ""
print " # Validate current directory"
print $" ($env.PROVISIONING_NAME) validate"
print ""
print " # Quick validation with auto-fix"
print $" ($env.PROVISIONING_NAME) validate quick klab/sgoyol --fix"
print ""
print " # CI/CD validation"
print $" ($env.PROVISIONING_NAME) validate ci klab/sgoyol --report yaml"
print ""
print " # Dry run to see what would be fixed"
print $" ($env.PROVISIONING_NAME) validate klab/sgoyol --fix --dry-run"
print ""
print " # Generate all report formats"
print $" ($env.PROVISIONING_NAME) validate klab/sgoyol --report all --output ./reports"
print ""
print " # List available rules"
print $" ($env.PROVISIONING_NAME) validate rules"
print ""
print " # Test the validation system"
print $" ($env.PROVISIONING_NAME) validate test"
print ""
""
}

View file

@ -0,0 +1,171 @@
#use utils *
#use defs *
use lib_provisioning *
# - > Query infrastructure and services
export def "main query" [
#hostname?: string # Server hostname in settings
...args # Args for create command
--infra (-i): string # Infra path
--settings (-s): string # Settings path
--serverpos (-p): int # Server position in settings
--check (-c) # Only check mode no servers will be created
--wait (-w) # Wait servers to be created
--outfile: string # Optional output format: json | yaml | csv | text | md | nuon
--find (-f): string # Optional query find a value (empty if no value found)
--cols (-l): string # Optional query columns list separated with comma
--target(-t): string # Target element for query: servers-status | servers | servers-info | servers-def | defs
--ips # Optional query get IPS only for target "servers-info"
--prov: string # Optional provider name to filter query
--ai_query: string # Natural language query using AI
--debug (-x) # Use Debug mode
--xm # Debug with PROVISIONING_METADATA
--xc # Debuc for task and services locally PROVISIONING_DEBUG_CHECK
--xr # Debug for remote servers PROVISIONING_DEBUG_REMOTE
--xld # Log level with DEBUG PROVISIONING_LOG_LEVEL=debug
--metadata # Error with metadata (-xm)
--notitles # not tittles
--out: string # Print Output format: json, yaml, text (default)
]: nothing -> nothing {
if ($out | is-not-empty) {
$env.PROVISIONING_OUT = $out
$env.PROVISIONING_NO_TERMINAL = true
}
# Handle AI query first if provided
if ($ai_query | is-not-empty) {
use ../lib_provisioning/ai/lib.nu *
if (is_ai_enabled) and (get_ai_config).enable_query_ai {
# Get current infrastructure context for AI
let curr_settings = if $infra != null {
if $settings != null {
(load_settings --infra $infra --settings $settings)
} else {
(load_settings --infra $infra)
}
} else {
if $settings != null {
(load_settings --settings $settings)
} else {
(load_settings)
}
}
let context = {
infra: ($infra | default "")
provider: ($prov | default "")
available_targets: ["servers", "servers-status", "servers-info", "servers-def", "defs"]
output_format: ($out | default "text")
}
let ai_response = (ai_process_query $ai_query $context)
print $ai_response
return
} else {
print "AI query processing is disabled or not configured"
return
}
}
parse_help_command "query" --end
if $debug { $env.PROVISIONING_DEBUG = true }
#use defs [ load_settings ]
let curr_settings = if $infra != null {
if $settings != null {
(load_settings --infra $infra --settings $settings)
} else {
(load_settings --infra $infra)
}
} else {
if $settings != null {
(load_settings --settings $settings)
} else {
(load_settings)
}
}
let cmd_target = if ($target | is-empty ) {
($args | get -o 0 | default "")
} else { $target }
#let str_out = if $outfile == null { "none" } else { $outfile }
let str_out = if $out == null { "" } else { $out }
let str_cols = if $cols == null { "" } else { $cols }
let str_find = if $find == null { "" } else { $find }
#use lib_provisioning *
match $cmd_target {
"server" | "servers" => {
#use utils/format.nu datalist_to_format
_print (datalist_to_format $str_out
(mw_query_servers $curr_settings $str_find $cols --prov $prov --serverpos $serverpos)
)
},
"server-status" | "servers-status" | "server-info" | "servers-info" => {
let list_cols = if ($cmd_target | str contains "status") {
if ($str_cols | str contains "state") { $str_cols } else { $str_cols + ",state" }
} else {
$str_cols
}
# not use $str_cols to filter previous $ips selection
(out_data_query_info
$curr_settings
(mw_servers_info $curr_settings $str_find --prov $prov --serverpos $serverpos)
#(mw_servers_info $curr_settings $find $cols --prov $prov --serverpos $serverpos)
$list_cols
$str_out
$ips
)
},
"servers-def" | "server-def" => {
let data = if $str_find != "" { ($curr_settings.data.servers | find $find) } else { $curr_settings.data.servers}
(out_data_query_info
$curr_settings
$data
$str_cols
$str_out
false
)
},
"def" | "defs" => {
let data = if $str_find != "" { ($curr_settings.data | find $find) } else { $curr_settings.data}
(out_data_query_info
$curr_settings
[ $data ]
$str_cols
$str_out
false
)
}
_ => {
(throw-error $"🛑 ($env.PROVISIONING_NAME) query " $"Invalid option (_ansi red)($cmd_target)(_ansi reset)"
$"($env.PROVISIONING_NAME) query --target ($cmd_target)" --span (metadata $cmd_target).span
)
}
}
cleanup $curr_settings.wk_path
if $outfile == null { end_run "query" }
}
def out_data_query_info [
settings: record
data: list
cols: string
outfile: string
ips: bool
]: nothing -> nothing {
if ($data | get -o 0 | is-empty) {
if $env.PROVISIONING_DEBUG { print $"🛑 ($env.PROVISIONING_NAME) query (_ansi red)no data found(_ansi reset)" }
_print ""
return
}
let sel_data = if ($cols | is-not-empty) {
$data | select -o ($cols | split row ",")
} else {
$data
}
#use (prov-middleware) mw_servers_ips
#use utils/format.nu datalist_to_format
print (datalist_to_format $outfile $sel_data)
# let data_ips = (($data).ip_addresses? | flatten | find "public")
if $ips {
let ips_result = (mw_servers_ips $settings $data)
print $ips_result
}
}

View file

@ -0,0 +1,82 @@
# Import will be handled by parent context
# - > Secrets management with infrastructure and services (SOPS or KMS)
export def "main secrets" [
sourcefile?: string # source file for secrets command
targetfile?: string # target file for secrets command
--provider (-p): string # secret provider: sops or kms
--encrypt (-e) # Encrypt file
--decrypt (-d) # Decrypt file
--gen (-g) # Generate encrypted files
--sed # Edit encrypted file
--debug (-x) # Use Debug mode
--xm # Debug with PROVISIONING_METADATA
--xc # Debug for task and services locally PROVISIONING_DEBUG_CHECK
--xr # Debug for remote servers PROVISIONING_DEBUG_REMOTE
--xld # Log level with DEBUG PROVISIONING_LOG_LEVEL=debug
--metadata # Error with metadata (-xm)
--notitles # not tittles
--out: string # Print Output format: json, yaml, text (default)
]: nothing -> nothing {
if ($out | is-not-empty) {
$env.PROVISIONING_OUT = $out
$env.PROVISIONING_NO_TERMINAL = true
}
# Set secret provider if specified
if ($provider | is-not-empty) {
$env.PROVISIONING_SECRET_PROVIDER = $provider
}
parse_help_command "secrets" --end
if $debug { $env.PROVISIONING_DEBUG = true }
if $sourcefile == "sed" or $sourcefile == "ed" {
on_secrets "sed" $targetfile
end_run "secrets"
return true
}
if $sed and $sourcefile != null and ($sourcefile | path exists) {
on_secrets sed $sourcefile
exit
}
if $encrypt {
if $sourcefile == null or not ($sourcefile | path exists) {
print $"🛑 Error on_secrets encrypt 'sourcefile' ($sourcefile) not found "
exit 1
}
if ($targetfile | is-not-empty) {
print $"on_secrets encrypt ($sourcefile) ($targetfile)"
on_secrets "encrypt" $sourcefile $targetfile
exit
} else {
print $"on_secrets encrypt ($sourcefile) "
print (on_secrets "encrypt" $sourcefile)
exit
}
}
if $decrypt {
if $sourcefile == null or not ($sourcefile | path exists) {
print $"🛑 Error on_secrets decrypt 'sourcefile' ($sourcefile) not found "
return false
}
if ($targetfile | is-not-empty) {
on_secrets decrypt $sourcefile $targetfile
exit
} else {
print (on_secrets decrypt $sourcefile)
exit
}
}
if $gen and $sourcefile != null {
on_secrets generate $sourcefile $targetfile
exit
}
option_undefined "secrets" ""
end_run "secrets"
}

View file

@ -0,0 +1,70 @@
#use sops/lib.nu on_sops
# - > SOPS with infrastructure and services
export def "main sops" [
sourcefile?: string # source file for sops command
targetfile?: string # target file for sops command
--encrypt (-e) # SOPS encrypt file
--decrypt (-d) # SOPS decrypt file
--gen (-g) # SOPS generate encrypted files
--sed # Edit sops encrypted file
--debug (-x) # Use Debug mode
--xm # Debug with PROVISIONING_METADATA
--xc # Debuc for task and services locally PROVISIONING_DEBUG_CHECK
--xr # Debug for remote servers PROVISIONING_DEBUG_REMOTE
--xld # Log level with DEBUG PROVISIONING_LOG_LEVEL=debug
--metadata # Error with metadata (-xm)
--notitles # not tittles
--out: string # Print Output format: json, yaml, text (default)
]: nothing -> nothing {
if ($out | is-not-empty) {
$env.PROVISIONING_OUT = $out
$env.PROVISIONING_NO_TERMINAL = true
}
parse_help_command "sops" --end
if $debug { $env.PROVISIONING_DEBUG = true }
if $sourcefile == "sed" or $sourcefile == "ed" {
on_sops "sed" $targetfile
end_run "sops"
return true
}
if $sed and $sourcefile != null and ($sourcefile | path exists) {
on_sops sed $sourcefile
exit
}
if $encrypt {
if $sourcefile == null or not ($sourcefile | path exists) {
print $"🛑 Error on_sops encrypt 'sourcefile' ($sourcefile) not found "
exit 1
}
if ($targetfile | is-not-empty) {
print $"on_sops encrypt ($sourcefile) ($targetfile)"
on_sops "encrypt" $sourcefile $targetfile
exit
} else {
print $"on_sops encrypt ($sourcefile) "
print (on_sops "encrypt" $sourcefile)
exit
}
}
if $decrypt {
if $sourcefile == null or not ($sourcefile | path exists) {
print $"🛑 Error on_sops decrypt 'sourcefile' ($sourcefile) not found "
return false
}
if ($targetfile | is-not-empty) {
on_sops decrypt $sourcefile $targetfile
exit
} else {
print (on_sops decrypt $sourcefile)
exit
}
}
if $gen and $sourcefile != null {
on_sops generate $sourcefile $targetfile
exit
}
option_undefined "sops" ""
#cleanup $settings.wk_path
end_run "sops"
}

View file

@ -0,0 +1,48 @@
# -> Manage provisioning Servers or instances
export def "main status" [
target?: string # server (s) | taskserv (t) | cluster (c)
name?: string # Target name in settings
...args # Args for create command
--serverpos (-p): int # Server position in settings
--check (-c) # Only check mode no servers will be created
--wait (-w) # Wait servers to be created
--infra (-i): string # Infra path
--settings (-s): string # Settings path
--outfile (-o): string # Output file
--debug (-x) # Use Debug mode
--xm # Debug with PROVISIONING_METADATA
--xc # Debuc for task and services locally PROVISIONING_DEBUG_CHECK
--xr # Debug for remote servers PROVISIONING_DEBUG_REMOTE
--xld # Log level with DEBUG PROVISIONING_LOG_LEVEL=debug
--metadata # Error with metadata (-xm)
--notitles # not tittles
--out: string # Print Output format: json, yaml, text (default)
]: nothing -> nothing {
let str_out = if ($out | is-not-empty) {
$env.PROVISIONING_OUT = $out
$env.PROVISIONING_NO_TERMINAL = true
$"--out ($out)"
} else {
""
}
parse_help_command "status" --end
if $debug { $env.PROVISIONING_DEBUG = true }
let use_debug = if $debug or $env.PROVISIONING_DEBUG { "-x" } else { "" }
match ($target | default "") {
"server"| "servers" | "s" => {
^$"($env.PROVISIONING_NAME)" $use_debug -mod "server" ($env.PROVISIONING_ARGS | str replace $target '') $str_out --yes --notitles
},
"taskserv" | "taskservs" | "t" => {
^$"($env.PROVISIONING_NAME)" $use_debug -mod "tasksrv" ($env.PROVISIONING_ARGS | str replace $target '') _out --yes --notitles
},
"clusters"| "clusters" | "c" => {
^$"($env.PROVISIONING_NAME)" $use_debug -mod "cluster" ($env.PROVISIONING_ARGS | str replace $target '') $str_out --yes --notitles
},
"" => {
^$"($env.PROVISIONING_NAME)" $use_debug -mod "server" ($env.PROVISIONING_ARGS) $str_out
},
_ => {
invalid_task "status" ($target | default "") --end
},
}
}

View file

@ -0,0 +1,272 @@
#!/usr/bin/env nu
# Info: Script to run Provisioning
# Author: JesusPerezLorenzo
# Release: 1.0.4
# Date: 30-4-2024
use std log
#use lib_provisioning *
use ../env.nu *
use ../lib_provisioning/utils/interface.nu *
use ../lib_provisioning/utils/init.nu *
use ../lib_provisioning/utils/error.nu *
use ../lib_provisioning/utils/version_manager.nu *
use ../lib_provisioning/utils/version_formatter.nu *
use ../lib_provisioning/utils/version_loader.nu *
use ../lib_provisioning/utils/version_registry.nu *
use ../lib_provisioning/utils/version_taskserv.nu *
# - > Tools management
export def "main tools" [
task?: string # tools tasks for tools command
...args # tools options
--update (-u) # Update tools
--debug (-x) # Use Debug mode
--xm # Debug with PROVISIONING_METADATA
--xc # Debuc for task and services locally PROVISIONING_DEBUG_CHECK
--xr # Debug for remote servers PROVISIONING_DEBUG_REMOTE
--xld # Log level with DEBUG PROVISIONING_LOG_LEVEL=debug
--metadata # Error with metadata (-xm)
--notitles # not tittles
--helpinfo (-h) # For more details use options "help" (no dashes)
--out: string # Print Output format: json, yaml, text (default)
--dry-run (-n) # Dry run mode for update operations
--force (-f) # Force updates even if fixed
]: nothing -> nothing {
if ($out | is-not-empty) {
$env.PROVISIONING_OUT = $out
$env.PROVISIONING_NO_TERMINAL = true
}
if (use_titles) { show_titles }
if $helpinfo {
_print (provisioning_tools_options)
# if not $env.PROVISIONING_DEBUG { end_run "" }
exit
}
let tools_task = if $task == null { "" } else { $task }
let tools_args = if ($args | length) == 0 { ["all"] } else { $args }
let core_bin = ($env.PROVISIONING | path join "core" | path join "bin")
match $tools_task {
"install" => {
let update_tools = if $update { "--update" } else { "" }
_print $"(_ansi blue_bold)($env.PROVISIONING_NAME)(_ansi reset) tools_install (_ansi green_bold)($tools_args | str join ' ') ($update_tools)(_ansi reset) "
^$"($core_bin)/tools-install" ...$tools_args $update_tools
},
"show" | "s" | "info" => {
_print $"(_ansi blue_bold)($env.PROVISIONING_NAME)(_ansi reset) tools (_ansi green_bold)($tools_args | str join ' ')(_ansi reset) "
let target = ($args | get -o 0 | default "")
let match = ($args | get -o 1 | default "")
match $target {
"a" | "all" => {
(show_tools_info $target)
(show_provs_info $match)
},
"p" | "prov" | "provider" | "providers" => (show_provs_info $match),
_ => (show_tools_info $target),
}
},
"" | "check" | "c" => {
_print $"(_ansi blue_bold)($env.PROVISIONING_NAME)(_ansi reset) tools check (_ansi green_bold)($tools_args | str join ' ')(_ansi reset) "
# Get all results first
let all_results = (check-versions --fetch-latest=false)
let all_configs = (discover-configurations)
# Filter based on arguments
let filtered_results = if ($args | length) == 0 {
# No args - show all
$all_results
} else if ($args | length) == 1 {
let arg = ($args | get 0)
# Handle special cases for providers
if $arg == "providers" {
# Show all provider components
$all_results | where type == "provider"
} else {
# Check if it's a type or component ID
let by_type = ($all_results | where type == $arg)
let by_id = ($all_results | where id == $arg)
if ($by_type | length) > 0 { $by_type } else { $by_id }
}
} else {
# Multiple args - "provider upcloud" format
let type_filter = ($args | get 0)
let category_filter = ($args | get 1)
if $type_filter == "provider" {
# Filter by provider category
let configs_by_category = ($all_configs | where type == "provider" and category == $category_filter)
let ids_by_category = ($configs_by_category | get id)
$all_results | where id in $ids_by_category
} else {
# Fallback to ID filtering
let id_filter = $category_filter
$all_results | where type == $type_filter and id == $id_filter
}
}
_print ($filtered_results | select id type configured status | table)
},
"versions" | "v" => {
_print $"(_ansi blue_bold)($env.PROVISIONING_NAME)(_ansi reset) tools versions (_ansi green_bold)($tools_args | str join ' ')(_ansi reset) "
# Get all results first
let all_results = (check-versions --fetch-latest=false)
let all_configs = (discover-configurations)
# Filter based on arguments (same logic as check command)
let filtered_results = if ($args | length) == 0 {
# No args - show all
$all_results
} else if ($args | length) == 1 {
let arg = ($args | get 0)
# Handle special cases for providers
if $arg == "providers" {
# Show all provider components
$all_results | where type == "provider"
} else {
# Check if it's a type or component ID
let by_type = ($all_results | where type == $arg)
let by_id = ($all_results | where id == $arg)
if ($by_type | length) > 0 { $by_type } else { $by_id }
}
} else {
# Multiple args - "provider upcloud" format
let type_filter = ($args | get 0)
let category_filter = ($args | get 1)
if $type_filter == "provider" {
# Filter by provider category
let configs_by_category = ($all_configs | where type == "provider" and category == $category_filter)
let ids_by_category = ($configs_by_category | get id)
$all_results | where id in $ids_by_category
} else {
# Fallback to ID filtering
let id_filter = $category_filter
$all_results | where type == $type_filter and id == $id_filter
}
}
_print ($filtered_results | select id type configured status | table)
_print "\nNote: Run 'tools check-updates' to fetch latest versions from remote sources"
return
},
"check-updates" | "cu" => {
_print $"(_ansi blue_bold)($env.PROVISIONING_NAME)(_ansi reset) tools check-updates (_ansi green_bold)($tools_args | str join ' ')(_ansi reset) "
let types = if ($args | length) > 0 { $args } else { [] }
check-available-updates --types=$types
return
},
"apply-updates" | "au" => {
_print $"(_ansi blue_bold)($env.PROVISIONING_NAME)(_ansi reset) tools apply-updates (_ansi green_bold)($tools_args | str join ' ')(_ansi reset) "
let types = if ($args | length) > 0 { $args } else { [] }
apply-config-updates --types=$types --dry-run=$dry_run --force=$force
return
},
"pin" => {
let component = ($args | get -o 0)
if ($component | is-empty) {
_print "❌ Please specify a component ID"
return
}
_print $"(_ansi blue_bold)($env.PROVISIONING_NAME)(_ansi reset) tools pin (_ansi green_bold)($component)(_ansi reset) "
set-fixed $component true
return
},
"unpin" => {
let component = ($args | get -o 0)
if ($component | is-empty) {
_print "❌ Please specify a component ID"
return
}
_print $"(_ansi blue_bold)($env.PROVISIONING_NAME)(_ansi reset) tools unpin (_ansi green_bold)($component)(_ansi reset) "
set-fixed $component false
return
},
"taskserv-versions" | "tv" => {
_print $"(_ansi blue_bold)($env.PROVISIONING_NAME)(_ansi reset) taskserv versions (_ansi green_bold)($tools_args | str join ' ')(_ansi reset) "
let format = ($args | get -o 0 | default "table")
let taskservs_path = if ($args | length) > 1 { ($args | get 1) } else { "" }
show-version-status --taskservs-path=$taskservs_path --format=$format
return
},
"taskserv-check" | "tc" => {
_print $"(_ansi blue_bold)($env.PROVISIONING_NAME)(_ansi reset) taskserv check (_ansi green_bold)($tools_args | str join ' ')(_ansi reset) "
let taskservs_path = if ($args | length) > 0 { ($args | get 0) } else { "" }
let configs = (discover-taskserv-configurations --base-path=$taskservs_path)
_print ($configs | select id version kcl_file | table)
return
},
"taskserv-update" | "tu" => {
_print $"(_ansi blue_bold)($env.PROVISIONING_NAME)(_ansi reset) taskserv update (_ansi green_bold)($tools_args | str join ' ')(_ansi reset) "
let components = if ($args | length) > 0 { $args } else { [] }
update-registry-versions --components=$components --dry-run=$dry_run
return
},
"taskserv-sync" | "ts" => {
_print $"(_ansi blue_bold)($env.PROVISIONING_NAME)(_ansi reset) taskserv sync (_ansi green_bold)($tools_args | str join ' ')(_ansi reset) "
let taskservs_path = if ($args | length) > 0 { ($args | get 0) } else { "" }
let component = if ($args | length) > 1 { ($args | get 1) } else { "" }
taskserv-sync-versions --taskservs-path=$taskservs_path --component=$component --dry-run=$dry_run
return
},
"help" | "helpinfo" | "h" => {
provisioning_tools_options
},
_ => {
on_tools_task $core_bin $tools_task
let text = $"expected to be one of [install, show, info, check, versions, check-updates, update-versions, pin, unpin], got ($tools_task)"
(throw-error
"🛑 invalid_option"
$text
#--span (metadata $pkg_dir | get span)
)
},
}
if not $env.PROVISIONING_DEBUG { end_run "" }
}
export def show_tools_info [
match: string
]: nothing -> nothing {
let tools_data = (open $env.PROVISIONING_REQ_VERSIONS)
if ($match | is-empty) {
_print ($tools_data | table -e)
} else {
_print ($tools_data | get -o $match | table -e)
}
}
export def show_provs_info [
match: string
]: nothing -> nothing {
if not ($env.PROVISIONING_PROVIDERS_PATH| path exists) {
_print $"❗Error providers path (_ansi red)($env.PROVISIONING_PROVIDERS_PATH)(_ansi reset) not found"
return
}
^ls $env.PROVISIONING_PROVIDERS_PATH | each {|prv|
if ($match | is-empty) or $match == ($prv | str trim) {
let prv_path = ($env.PROVISIONING_PROVIDERS_PATH | path join ($prv | str trim) | path join "provisioning.yaml")
if ($prv_path | path exists) {
_print $"(_ansi magenta_bold)($prv | str trim | str upcase)(_ansi reset)"
_print (open $prv_path | table -e)
}
}
}
}
export def on_tools_task [
core_bin: string
tools_task: string
]: nothing -> nothing {
if not ($env.PROVISIONING_REQ_VERSIONS | path exists) {
_print $"❗Error tools path (_ansi red)($env.PROVISIONING_REQ_VERSIONS)(_ansi reset) not found"
return
}
let tools_data = (open $env.PROVISIONING_REQ_VERSIONS)
let tool_name = ($tools_data | get -o $tools_task)
if ($tool_name | is-not-empty) {
_print $"(_ansi blue_bold)($env.PROVISIONING_NAME)(_ansi reset) tools check (_ansi green_bold)($tools_task)(_ansi reset) "
^$"($core_bin)/tools-install" check $tools_task
# if not $env.PROVISIONING_DEBUG { end_run "" }
exit
}
}

View file

@ -0,0 +1,75 @@
def prompt_update [
target: string
target_name: string
yes: bool
name?: string
]: nothing -> string {
match $name {
"h" | "help" => {
^($env.PROVISIONING_NAME) "-mod" $target "--help"
exit 0
}
}
if not $yes or not (($env.PROVISIONING_ARGS? | default "") | str contains "--yes") {
_print ( $"To (_ansi red_bold)update ($target_name) (_ansi reset) " +
$" (_ansi green_bold)($name)(_ansi reset) type (_ansi green_bold)yes(_ansi reset) ? "
)
let user_input = (input --numchar 3)
if $user_input != "yes" and $user_input != "YES" {
exit 1
}
$name
} else {
$env.PROVISIONING_ARGS = ($env.PROVISIONING_ARGS? | find -v "yes")
($name | default "" | str replace "yes" "")
}
}
# -> Update infrastructure and services
export def "main update" [
target?: string # server (s) | task (t) | service (sv)
name?: string # target name in settings
...args # Args for create command
--serverpos (-p): int # Server position in settings
--keepstorage # Keep storage
--yes (-y) # confirm update
--wait (-w) # Wait servers to be created
--infra (-i): string # Infra path
--settings (-s): string # Settings path
--outfile (-o): string # Output file
--debug (-x) # Use Debug mode
--xm # Debug with PROVISIONING_METADATA
--xc # Debuc for task and services locally PROVISIONING_DEBUG_CHECK
--xr # Debug for remote servers PROVISIONING_DEBUG_REMOTE
--xld # Log level with DEBUG PROVISIONING_LOG_LEVEL=debug
--metadata # Error with metadata (-xm)
--notitles # not tittles
--out: string # Print Output format: json, yaml, text (default)
]: nothing -> nothing {
if ($out | is-not-empty) {
$env.PROVISIONING_OUT = $out
$env.PROVISIONING_NO_TERMINAL = true
}
parse_help_command "update" --end
if $debug { $env.PROVISIONING_DEBUG = true }
let use_debug = if $debug or $env.PROVISIONING_DEBUG { "-x" } else { "" }
match $target {
"server"| "servers" | "s" => {
let use_keepstorage = if $keepstorage { "--keepstorage "} else { "" }
prompt_update "server" "servers" $yes $name
^$"($env.PROVISIONING_NAME)" $use_debug -mod "server" ($env.PROVISIONING_ARGS | str replace $target '') --yes --notitles $use_keepstorage
},
"taskserv" | "taskservs" | "t" => {
prompt_update "taskserv" "tasks/services" $yes $name
^$"($env.PROVISIONING_NAME)" $use_debug -mod "tasksrv" ($env.PROVISIONING_ARGS | str replace $target '') --yes --notitles
},
"clusters"| "clusters" | "cl" => {
prompt_update "cluster" "cluster" $yes $name
^$"($env.PROVISIONING_NAME)" $use_debug -mod "cluster" ($env.PROVISIONING_ARGS | str replace $target '') --yes --notitles
},
_ => {
invalid_task "update" ($target | default "") --end
exit
},
}
}

View file

@ -0,0 +1,343 @@
# Infrastructure Validation Commands
# Integrates validation system into the main provisioning CLI
# Import validation functions
use ../lib_provisioning/infra_validator/validator.nu *
use ../lib_provisioning/infra_validator/agent_interface.nu *
# Main validation command
export def "main validate" [
infra_path?: string # Path to infrastructure configuration (default: current directory)
...args # Additional arguments
--fix (-f) # Auto-fix issues where possible
--report (-r): string = "md" # Report format (md|yaml|json|all)
--output (-o): string = "./validation_results" # Output directory
--severity (-s): string = "warning" # Minimum severity (info|warning|error|critical)
--ci # CI/CD mode (exit codes, no colors, minimal output)
--dry-run (-d) # Show what would be fixed without actually fixing
--rules: string # Comma-separated list of specific rules to run
--exclude: string # Comma-separated list of rules to exclude
--verbose (-v) # Verbose output (show all details)
--help (-h) # Show detailed help
]: nothing -> nothing {
if $help {
show_validation_help
return
}
let target_path = if ($infra_path | is-empty) {
"."
} else {
$infra_path
}
if not ($target_path | path exists) {
if not $ci {
print $"🛑 Infrastructure path not found: ($target_path)"
print "Use --help for usage information"
}
exit 1
}
if not $ci {
print_validation_banner
print $"🔍 Validating infrastructure: ($target_path | path expand)"
print ""
}
# Validate input parameters
let valid_severities = ["info", "warning", "error", "critical"]
if ($severity not-in $valid_severities) {
if not $ci {
print $"🛑 Invalid severity level: ($severity)"
print $"Valid options: ($valid_severities | str join ', ')"
}
exit 1
}
let valid_formats = ["md", "markdown", "yaml", "yml", "json", "all"]
if ($report not-in $valid_formats) {
if not $ci {
print $"🛑 Invalid report format: ($report)"
print $"Valid options: ($valid_formats | str join ', ')"
}
exit 1
}
# Set up environment
setup_validation_environment $verbose
# Run validation using the validator engine
try {
let result = (main $target_path
--fix=$fix
--report=$report
--output=$output
--severity=$severity
--ci=$ci
--dry-run=$dry_run
)
if not $ci {
print ""
print $"📊 Reports generated in: ($output)"
show_validation_next_steps $result
}
} catch {|error|
if not $ci {
print $"🛑 Validation failed: ($error.msg)"
}
exit 4
}
}
# Quick validation subcommand
export def "main validate quick" [
infra_path?: string
--fix (-f)
]: nothing -> nothing {
let target = if ($infra_path | is-empty) { "." } else { $infra_path }
print "🚀 Quick Infrastructure Validation"
print "=================================="
print ""
main validate $target --severity="error" --report="md" --output="./quick_validation" --fix=$fix
}
# CI validation subcommand
export def "main validate ci" [
infra_path: string
--format (-f): string = "yaml"
--fix
]: nothing -> nothing {
main validate $infra_path --ci --report=$format --output="./ci_validation" --fix=$fix
}
# Full validation subcommand
export def "main validate full" [
infra_path?: string
--output (-o): string = "./full_validation"
]: nothing -> nothing {
let target = if ($infra_path | is-empty) { "." } else { $infra_path }
print "🔍 Full Infrastructure Validation"
print "================================="
print ""
main validate $target --severity="info" --report="all" --output=$output --verbose
}
# Agent interface for automation
export def "main validate agent" [
infra_path: string
--auto_fix: bool = false
--severity_threshold: string = "warning"
--format: string = "json"
]: nothing -> nothing {
print "🤖 Agent Validation Mode"
print "========================"
print ""
let result = (validate_for_agent $infra_path --auto_fix=$auto_fix --severity_threshold=$severity_threshold)
match $format {
"json" => { $result | to json },
"yaml" => { $result | to yaml },
_ => { $result }
}
}
# List available rules
export def "main validate rules" []: nothing -> nothing {
print "📋 Available Validation Rules"
print "============================"
print ""
let rules = [
{id: "VAL001", category: "syntax", severity: "critical", name: "YAML Syntax Validation", auto_fix: false}
{id: "VAL002", category: "compilation", severity: "critical", name: "KCL Compilation Check", auto_fix: false}
{id: "VAL003", category: "syntax", severity: "error", name: "Unquoted Variable References", auto_fix: true}
{id: "VAL004", category: "schema", severity: "error", name: "Required Fields Validation", auto_fix: false}
{id: "VAL005", category: "best_practices", severity: "warning", name: "Resource Naming Conventions", auto_fix: true}
{id: "VAL006", category: "security", severity: "error", name: "Basic Security Checks", auto_fix: false}
{id: "VAL007", category: "compatibility", severity: "warning", name: "Version Compatibility Check", auto_fix: false}
{id: "VAL008", category: "networking", severity: "error", name: "Network Configuration Validation", auto_fix: false}
]
for rule in $rules {
let auto_fix_indicator = if $rule.auto_fix { "🔧" } else { "👁️" }
let severity_color = match $rule.severity {
"critical" => "🚨"
"error" => "❌"
"warning" => "⚠️"
_ => ""
}
print $"($auto_fix_indicator) ($severity_color) ($rule.id): ($rule.name)"
print $" Category: ($rule.category) | Severity: ($rule.severity) | Auto-fix: ($rule.auto_fix)"
print ""
}
print "Legend:"
print "🔧 = Auto-fixable | 👁️ = Manual fix required"
print "🚨 = Critical | ❌ = Error | ⚠️ = Warning | = Info"
}
# Test validation system
export def "main validate test" []: nothing -> nothing {
print "🧪 Testing Validation System"
print "============================="
print ""
# Run the test script
try {
^nu test_validation.nu
} catch {|error|
print $"❌ Test failed: ($error.msg)"
exit 1
}
}
def print_validation_banner []: nothing -> nothing {
print "╔══════════════════════════════════════════════════════════════╗"
print "║ Infrastructure Validation & Review Tool ║"
print "║ Cloud Native Provisioning ║"
print "╚══════════════════════════════════════════════════════════════╝"
print ""
}
def show_validation_help []: nothing -> nothing {
print "Infrastructure Validation & Review Tool"
print "========================================"
print ""
print "USAGE:"
print " ./core/nulib/provisioning validate [SUBCOMMAND] [INFRA_PATH] [OPTIONS]"
print ""
print "SUBCOMMANDS:"
print " (none) Full validation with customizable options"
print " quick Quick validation focusing on errors and critical issues"
print " ci CI/CD optimized validation with structured output"
print " full Comprehensive validation including info-level checks"
print " agent Agent/automation interface with JSON output"
print " rules List all available validation rules"
print " test Run validation system self-tests"
print ""
print "ARGUMENTS:"
print " INFRA_PATH Path to infrastructure configuration (default: current directory)"
print ""
print "OPTIONS:"
print " -f, --fix Auto-fix issues where possible"
print " -r, --report FORMAT Report format: md, yaml, json, all (default: md)"
print " -o, --output DIR Output directory (default: ./validation_results)"
print " -s, --severity LEVEL Minimum severity: info, warning, error, critical (default: warning)"
print " --ci CI/CD mode (exit codes, no colors, minimal output)"
print " -d, --dry-run Show what would be fixed without actually fixing"
print " --rules RULES Comma-separated list of specific rules to run"
print " --exclude RULES Comma-separated list of rules to exclude"
print " -v, --verbose Verbose output"
print " -h, --help Show this help"
print ""
print "EXIT CODES:"
print " 0 All validations passed"
print " 1 Critical errors found (blocks deployment)"
print " 2 Errors found (should be fixed)"
print " 3 Only warnings found"
print " 4 Validation system error"
print ""
print "EXAMPLES:"
print ""
print " # Validate current directory"
print " ./core/nulib/provisioning validate"
print ""
print " # Quick validation with auto-fix"
print " ./core/nulib/provisioning validate quick klab/sgoyol --fix"
print ""
print " # CI/CD validation"
print " ./core/nulib/provisioning validate ci klab/sgoyol --format yaml"
print ""
print " # Full validation with all reports"
print " ./core/nulib/provisioning validate full klab/sgoyol --output ./reports"
print ""
print " # Agent mode for automation"
print " ./core/nulib/provisioning validate agent klab/sgoyol --auto_fix"
print ""
print " # List available rules"
print " ./core/nulib/provisioning validate rules"
print ""
print " # Test the validation system"
print " ./core/nulib/provisioning validate test"
print ""
}
def setup_validation_environment [verbose: bool]: nothing -> nothing {
# Check required dependencies
let dependencies = ["kcl"] # Add other required tools
for dep in $dependencies {
let check = (^bash -c $"type -P ($dep)" | complete)
if $check.exit_code != 0 {
if $verbose {
print $"⚠️ Warning: ($dep) not found in PATH"
print " Some validation rules may be skipped"
}
} else if $verbose {
print $"✅ ($dep) found"
}
}
}
def show_validation_next_steps [result: record]: nothing -> nothing {
let exit_code = $result.exit_code
print "🎯 Next Steps:"
print "=============="
match $exit_code {
0 => {
print "✅ All validations passed! Your infrastructure is ready for deployment."
print ""
print "Recommended actions:"
print "• Review the validation report for any enhancement suggestions"
print "• Consider setting up automated validation in your CI/CD pipeline"
print "• Share the report with your team for documentation"
}
1 => {
print "🚨 Critical issues found that block deployment:"
print ""
print "Required actions:"
print "• Fix all critical issues before deployment"
print "• Review the validation report for specific fixes needed"
print "• Re-run validation after fixes: ./core/nulib/provisioning validate --fix"
print "• Consider using --dry-run first to preview fixes"
}
2 => {
print "❌ Errors found that should be resolved:"
print ""
print "Recommended actions:"
print "• Review and fix the errors in the validation report"
print "• Use --fix flag to auto-resolve fixable issues"
print "• Test your infrastructure after fixes"
print "• Consider the impact of proceeding with these errors"
}
3 => {
print "⚠️ Warnings found - review recommended:"
print ""
print "Suggested actions:"
print "• Review warnings for potential improvements"
print "• Consider addressing warnings for better practices"
print "• Documentation and monitoring suggestions may be included"
print "• Safe to proceed with deployment"
}
_ => {
print "❓ Unexpected validation result - please review the output"
}
}
print ""
print "For detailed information, check the generated reports in the output directory."
print "Use --help for more usage examples and CI/CD integration guidance."
}