419 lines
16 KiB
Plaintext
419 lines
16 KiB
Plaintext
|
|
#!/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 <module> <workspace> [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 <name>] - Show layer information"
|
|||
|
|
print " test <module> <workspace> [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 <workspace> [--module <name>]"
|
|||
|
|
print " provisioning layer test <module> <workspace> [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 <workspace>"
|
|||
|
|
print ""
|
|||
|
|
print "• Show layers for specific module:"
|
|||
|
|
print " provisioning layer show <workspace> --module <name>"
|
|||
|
|
print ""
|
|||
|
|
print "• Test layer resolution:"
|
|||
|
|
print " provisioning layer test <module> <workspace> [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"
|
|||
|
|
}
|