prvng_core/nulib/provisioning layer
2025-10-07 10:32:04 +01:00

419 lines
16 KiB
Plaintext
Executable File
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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"
}