#!/usr/bin/env nu # Info: Script to run Provisioning Layer System Management # Author: JesusPerezLorenzo # Release: 1.0.0 # Date: 29-09-2025 use std log use lib_provisioning * use env.nu * # - > Help on Layer export def "main help" [ --src: string = "" --notitles # not titles --out: string # Print Output format: json, yaml, text (default) ]: nothing -> nothing { if $notitles == null or not $notitles { show_titles } ^$"($env.PROVISIONING_NAME)" -mod layer --help if ($out | is-not-empty) { $env.PROVISIONING_NO_TERMINAL = false } print (provisioning_options $src) if not $env.PROVISIONING_DEBUG { end_run "" } } # > Layer System Management def main [ ...args: string # Other options, use help to get info -v # Show version -i # Show Info --version (-V) # Show version with title --info (-I) # Show Info with title --about (-a) # Show About --workspace: string = "" # Workspace/infrastructure name for layer resolution --module: string = "" # Module name to show layer information --provider: string = "" # Provider name for layer testing --debug (-x) # Use Debug mode --xm # Debug with PROVISIONING_METADATA --xld # Log level with DEBUG PROVISIONING_LOG_LEVEL=debug --metadata # Error with metadata (-xm) --notitles # Do not show banner titles --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 } provisioning_init $helpinfo "layer" $args if $version or $v { ^$env.PROVISIONING_NAME -v ; exit } if $info or $i { ^$env.PROVISIONING_NAME -i ; exit } if $about { _print (get_about_info) exit } if $debug { $env.PROVISIONING_DEBUG = true } if $metadata { $env.PROVISIONING_METADATA = true } let task = if ($args | length) > 0 { ($args | get 0) } else { "" } let ops = $"($env.PROVISIONING_ARGS? | default "") " | str replace $" ($task) " "" | str trim let workspace_name = if ($ops | is-not-empty) and not ($ops | str starts-with "-") { ($ops | split row " " | get 0) } else { $workspace } let module_name = if ($ops | split row " " | length) > 1 { ($ops | split row " " | get 1) } else { $module } $env.PROVISIONING_MODULE = "layer" match $task { "h" | "help" => { # Redirect to main categorized help system exec $"($env.PROVISIONING_NAME)" help development --notitles }, "show" => { if ($workspace_name | is-empty) { layer_show_all --out $out } else { layer_show $workspace_name --module $module_name --out $out } }, "test" => { if ($module_name | is-empty) or ($workspace_name | is-empty) { print "❌ Module name and workspace required" print "Usage: provisioning layer test [provider]" exit 1 } let provider_arg = if ($ops | split row " " | length) > 2 { ($ops | split row " " | get 2) } else { $provider } layer_test $module_name $workspace_name $provider_arg }, "explain" => { layer_explain --out $out }, "stats" => { layer_stats }, "validate" => { layer_validate }, _ => { print $"❌ Unknown task: ($task)" print "Use 'provisioning layer help' for available commands" print "" print "Available commands:" print " show [workspace] [--module ] - Show layer information" print " test [provider] - Test layer resolution" print " explain - Explain the layer concept" print " stats - Show layer statistics" print " validate - Validate layer configuration" exit 1 } } } # Show layer information def layer_show [ workspace: string --module: string --out: string ]: nothing -> nothing { let provisioning_root = $env.PROVISIONING? | default $env.PWD if ($module | is-not-empty) { print $"🔍 Layer Information for Module: ($module)" print $" Workspace: ($workspace)" print "" # Show layer resolution chain print "📋 Layer Resolution Chain (Highest to Lowest Priority):" print "" # Layer 3: Infrastructure print " 3️⃣ Infrastructure Layer (Priority 300)" print $" Path: workspace/infra/($workspace)/" let workspace_root = $env.PWD let infra_taskserv = ($workspace_root | path join "workspace" "infra" $workspace "taskservs" $"($module).k") let infra_override = ($workspace_root | path join "workspace" "infra" $workspace "overrides" $"($module).k") if ($infra_override | path exists) { print $" ✅ Override: ($infra_override)" } else if ($infra_taskserv | path exists) { print $" ✅ Taskserv: ($infra_taskserv)" } else { print " ❌ No infrastructure-specific configuration" } print "" # Layer 2: Workspace print " 2️⃣ Workspace Layer (Priority 200)" print " Path: provisioning/workspace/templates/" let workspace_template = ($provisioning_root | path join "workspace" "templates" "taskservs" $module) if ($workspace_template | path exists) { print $" ✅ Template: ($workspace_template)" } else { print " ❌ No shared template" } print "" # Layer 1: Core print " 1️⃣ Core Layer (Priority 100)" print " Path: provisioning/extensions/" # Check if module exists in core by checking directory structure let core_taskserv_path = ($provisioning_root | path join "extensions" "taskservs") let core_provider_path = ($provisioning_root | path join "extensions" "providers" $module) let core_exists = ($core_provider_path | path exists) or ( ($core_taskserv_path | path exists) and (ls $core_taskserv_path | where type == dir | get name | any {|p| ($p | path basename) == $module or ($p | str contains $module)}) ) if $core_exists { print " ✅ Base system extension found" } else { print " ❌ No core extension" } print "" } else { print $"🏗️ Layer System Overview for: ($workspace)" print "" print "📋 Layer Resolution Order:" print " (Higher priority overrides lower priority)" print "" print " 3️⃣ Infrastructure Layer (Priority 300)" print $" Path: workspace/infra/($workspace)/" print " Description: Infrastructure-specific configurations and overrides" print " Purpose: Customize settings for this specific environment" print "" print " 2️⃣ Workspace Layer (Priority 200)" print " Path: provisioning/workspace/templates/" print " Description: Shared templates and reusable configurations" print " Purpose: Share common patterns across infrastructures" print "" print " 1️⃣ Core Layer (Priority 100)" print " Path: provisioning/extensions/" print " Description: Base provisioning system extensions" print " Purpose: Provide default functionality and base components" print "" } } # Show all layer information def layer_show_all [--out: string]: nothing -> nothing { print "🏗️ Layer System Architecture" print "" print "The provisioning system uses a layered architecture for configuration inheritance:" print "" print "📋 Layer Resolution Order (Highest to Lowest Priority):" print "" print " 3️⃣ Infrastructure Layer (Priority 300)" print " • Path: workspace/infra/{name}/" print " • Purpose: Infrastructure-specific configurations and overrides" print " • Use case: Customize settings for specific environments" print "" print " 2️⃣ Workspace Layer (Priority 200)" print " • Path: provisioning/workspace/templates/" print " • Purpose: Shared templates and reusable configurations" print " • Use case: Share common patterns across infrastructures" print "" print " 1️⃣ Core Layer (Priority 100)" print " • Path: provisioning/extensions/" print " • Purpose: Base provisioning system extensions" print " • Use case: Provide default functionality and base components" print "" print "💡 Usage:" print " provisioning layer show [--module ]" print " provisioning layer test [provider]" print " provisioning layer explain" print "" } # Test layer resolution def layer_test [ module_name: string, workspace: string, provider: string = "" ]: nothing -> nothing { let provisioning_root = $env.PROVISIONING? | default $env.PWD let layer_utils = ($provisioning_root | path join "workspace" "tools" "layer-utils.nu") if not ($layer_utils | path exists) { print $"❌ Layer utilities not found: ($layer_utils)" exit 1 } # Call the test function from layer-utils.nu nu -c $"use ($layer_utils) *; test_layer_resolution '($module_name)' '($workspace)' '($provider)'" } # Explain layer concept def layer_explain [--out: string]: nothing -> nothing { if ($out | is-not-empty) { let layers = [ { priority: 300 name: "Infrastructure" path: "workspace/infra/{name}/" description: "Infrastructure-specific configurations and overrides" } { priority: 200 name: "Workspace" path: "provisioning/workspace/templates/" description: "Shared templates and reusable configurations" } { priority: 100 name: "Core" path: "provisioning/extensions/" description: "Base provisioning system extensions" } ] if $out == "json" { print ($layers | to json) } else if $out == "yaml" { print ($layers | to yaml) } else { print ($layers | table) } return } print "🎓 Understanding the Layer System" print "=================================" print "" print "The provisioning system uses a three-layer architecture for configuration" print "inheritance and override management. Each layer has a specific priority:" print "" print "🏗️ LAYER ARCHITECTURE" print "" print "┌─────────────────────────────────────────────────────────────┐" print "│ Layer 3: Infrastructure (Priority 300) │" print "│ ────────────────────────────────────────── │" print "│ Path: workspace/infra/{name}/ │" print "│ Purpose: Environment-specific customizations │" print "│ Example: workspace/infra/production/taskservs/ │" print "│ kubernetes.k (production-specific K8s config) │" print "└─────────────────────────────────────────────────────────────┘" print " ↓ overrides ↓" print "┌─────────────────────────────────────────────────────────────┐" print "│ Layer 2: Workspace (Priority 200) │" print "│ ───────────────────────────────── │" print "│ Path: provisioning/workspace/templates/ │" print "│ Purpose: Shared templates across infrastructures │" print "│ Example: workspace/templates/taskservs/kubernetes/ │" print "│ default.k (common K8s configuration) │" print "└─────────────────────────────────────────────────────────────┘" print " ↓ overrides ↓" print "┌─────────────────────────────────────────────────────────────┐" print "│ Layer 1: Core (Priority 100) │" print "│ ──────────────────────────── │" print "│ Path: provisioning/extensions/ │" print "│ Purpose: Base system functionality │" print "│ Example: extensions/taskservs/kubernetes/ │" print "│ (base kubernetes installation logic) │" print "└─────────────────────────────────────────────────────────────┘" print "" print "📖 HOW IT WORKS" print "" print "1. Resolution Order:" print " When you request a module (e.g., 'kubernetes'), the system searches" print " from highest to lowest priority:" print " Infrastructure (300) → Workspace (200) → Core (100)" print "" print "2. Override Mechanism:" print " • Infrastructure overrides Workspace and Core" print " • Workspace overrides Core" print " • Core provides base defaults" print "" print "3. Configuration Inheritance:" print " Each layer can inherit from lower layers and override specific" print " settings. This allows you to:" print " • Keep common configs in Workspace" print " • Customize per-environment in Infrastructure" print " • Maintain base functionality in Core" print "" print "💡 PRACTICAL EXAMPLE" print "" print "Scenario: Deploying Kubernetes" print "" print "• Core Layer (100):" print " Provides base kubernetes installation scripts" print " Default version: 1.28.0" print " Default CNI: none" print "" print "• Workspace Layer (200):" print " Template with your organization's standards" print " Version: 1.29.0" print " CNI: Cilium" print " Monitoring: Enabled" print "" print "• Infrastructure Layer (300):" print " Production-specific overrides" print " Version: 1.29.0 (inherited from workspace)" print " CNI: Cilium (inherited from workspace)" print " Monitoring: Enabled (inherited from workspace)" print " High Availability: True (production-specific)" print " Backup: Enabled (production-specific)" print "" print "Result: Production gets all workspace defaults plus specific overrides" print "" print "🔧 COMMANDS" print "" print "• Show layers for a workspace:" print " provisioning layer show " print "" print "• Show layers for specific module:" print " provisioning layer show --module " print "" print "• Test layer resolution:" print " provisioning layer test [provider]" print "" print "• Show layer statistics:" print " provisioning layer stats" print "" print "• Validate layer configuration:" print " provisioning layer validate" print "" } # Show layer statistics def layer_stats []: nothing -> nothing { let provisioning_root = $env.PROVISIONING? | default $env.PWD let layer_utils = ($provisioning_root | path join "workspace" "tools" "layer-utils.nu") if not ($layer_utils | path exists) { print $"❌ Layer utilities not found: ($layer_utils)" exit 1 } # Call the stats function from layer-utils.nu nu -c $"use ($layer_utils) *; show_layer_stats" } # Validate layer configuration def layer_validate []: nothing -> nothing { let provisioning_root = $env.PROVISIONING? | default $env.PWD let layer_utils = ($provisioning_root | path join "workspace" "tools" "layer-utils.nu") if not ($layer_utils | path exists) { print $"❌ Layer utilities not found: ($layer_utils)" exit 1 } # Call the validate function from layer-utils.nu nu -c $"use ($layer_utils) *; validate_layer_config" }