419 lines
16 KiB
Plaintext
Executable File
419 lines
16 KiB
Plaintext
Executable File
#!/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"
|
||
}
|