prvng_core/cli/module-loader

981 lines
34 KiB
Plaintext
Raw Permalink Normal View History

2025-10-07 10:32:04 +01:00
#!/usr/bin/env nu
# Enhanced Module Loader CLI
# Unified CLI for discovering and loading taskservs, providers, and clusters
# Includes template and layer support from enhanced version
use ../nulib/taskservs/discover.nu *
use ../nulib/taskservs/load.nu *
use ../nulib/providers/discover.nu *
use ../nulib/providers/load.nu *
use ../nulib/clusters/discover.nu *
use ../nulib/clusters/load.nu *
use ../nulib/lib_provisioning/kcl_module_loader.nu *
use ../nulib/lib_provisioning/config/accessor.nu config-get
# Main module loader command with enhanced features
def main [subcommand?: string] {
if ($subcommand | is-empty) {
print_enhanced_help
return
}
match $subcommand {
"help" => print_enhanced_help
"discover" => print_discover_help
"load" => print_load_help
"list" => print_list_help
"unload" => print_unload_help
"init" => print_init_help
"validate" => print_validate_help
"info" => print_info_help
"template" => print_template_help
"layer" => print_layer_help
"override" => print_override_help
_ => {
print $"Unknown command: ($subcommand)"
print_enhanced_help
}
}
}
# === DISCOVERY COMMANDS ===
# Discover available modules
export def "main discover" [
type: string, # Module type: taskservs, providers, clusters
query?: string, # Search query
--format: string = "table", # Output format: table, yaml, json, names
--category: string = "", # Filter by category (for taskservs)
--group: string = "" # Filter by group (for taskservs)
] {
match $type {
"taskservs" => {
let taskservs = if ($query | is-empty) {
discover-taskservs
} else {
search-taskservs $query
}
let filtered = if ($category | is-empty) and ($group | is-empty) {
$taskservs
} else if not ($category | is-empty) {
$taskservs | where group == $category
} else if not ($group | is-empty) {
$taskservs | where group == $group
} else {
$taskservs
}
format_output $filtered $format
}
"providers" => {
print "Provider discovery not implemented yet"
}
"clusters" => {
print "Cluster discovery not implemented yet"
}
_ => {
print $"Unknown module type: ($type)"
print "Available types: taskservs, providers, clusters"
}
}
}
# Sync KCL dependencies for infrastructure workspace
export def "main sync-kcl" [
infra: string, # Infrastructure name or path
--manifest: string = "providers.manifest.yaml", # Manifest file name
--kcl # Show KCL module info after sync
] {
# Resolve infrastructure path
let infra_path = if ($infra | path exists) {
$infra
} else {
# Try workspace path
let workspace_path = $"workspace/infra/($infra)"
if ($workspace_path | path exists) {
$workspace_path
} else {
print $"❌ Infrastructure not found: ($infra)"
return
}
}
# Sync KCL dependencies using library function
sync-kcl-dependencies $infra_path --manifest $manifest
# Show KCL module info if requested
if $kcl {
print ""
print "📋 KCL Modules:"
let modules_dir = (get-config-value "kcl" "modules_dir")
let modules_path = ($infra_path | path join $modules_dir)
if ($modules_path | path exists) {
ls $modules_path | each {|entry|
print $" • ($entry.name | path basename) → ($entry.name)"
}
}
}
}
# === LOAD/UNLOAD COMMANDS ===
# Load modules into workspace
export def "main load" [
type: string, # Module type: taskservs, providers, clusters
workspace: string, # Workspace path
...modules: string, # Module names to load
--layer: string = "workspace", # Layer to load into: workspace, infra
--validate # Validate after loading
--force (-f) # Force overwrite existing files
] {
if ($modules | is-empty) {
print $"No modules specified for loading"
return
}
print $"Loading ($modules | length) ($type) into ($workspace) at layer ($layer)"
match $type {
"taskservs" | "providers" | "clusters" | "workflows" => {
load_extension_to_workspace $type $workspace $modules $layer $force
}
_ => {
print $"Unknown module type: ($type)"
}
}
if $validate {
main validate $workspace
}
}
# Enhanced load with template support
export def "main load enhanced" [
type: string, # Module type
workspace: string, # Workspace path
infra: string, # Infrastructure name
modules: list<string>, # Module names
--layer: string = "workspace", # Target layer
--template-base # Use template as base
] {
print $"🚀 Enhanced loading ($modules | length) ($type) for infra ($infra)"
for module in $modules {
print $" 📦 Loading ($module)..."
# Check if template exists for this module
let template_path = $"provisioning/workspace/templates/taskservs/*/($module).k"
let has_template = (glob $template_path | length) > 0
if $has_template and $template_base {
print $" ✓ Using template base for ($module)"
# Template-based loading would go here
} else {
print $" ✓ Direct loading for ($module)"
# Direct loading
}
}
print "✅ Enhanced loading completed"
}
# Unload module from workspace
export def "main unload" [
type: string, # Module type
workspace: string, # Workspace path
module: string, # Module name to unload
--layer: string = "workspace" # Layer to unload from
] {
print $"Unloading ($module) from ($workspace) at layer ($layer)"
match $type {
"taskservs" => {
unload_taskserv_from_workspace $workspace $module $layer
}
"providers" => {
print "Provider unloading not implemented yet"
}
"clusters" => {
print "Cluster unloading not implemented yet"
}
_ => {
print $"Unknown module type: ($type)"
}
}
}
# === LIST COMMANDS ===
# List modules in workspace
export def "main list" [
type: string, # Module type
workspace: string, # Workspace path
--layer: string = "all", # Layer to list: workspace, infra, all
--format: string = "table" # Output format
] {
print $"Listing ($type) in ($workspace) for layer ($layer)"
match $type {
"taskservs" => {
list_workspace_taskservs $workspace $layer $format
}
"providers" => {
print "Provider listing not implemented yet"
}
"clusters" => {
print "Cluster listing not implemented yet"
}
_ => {
print $"Unknown module type: ($type)"
}
}
}
# === TEMPLATE COMMANDS ===
# List available templates
export def "main template list" [
--template-type: string = "all", # Template type: taskservs, providers, servers, clusters
--format: string = "table" # Output format
] {
print $"📋 Available templates type: ($template_type)"
let template_base = "provisioning/workspace/templates"
match $template_type {
"taskservs" | "all" => {
let taskserv_templates = if (($template_base | path join "taskservs") | path exists) {
glob ($template_base | path join "taskservs" "*" "*.k")
| each { |path|
let category = ($path | path dirname | path basename)
let name = ($path | path basename | str replace ".k" "")
{ type: "taskserv", category: $category, name: $name, path: $path }
}
} else { [] }
format_output $taskserv_templates $format
}
"providers" => {
print "Provider templates not implemented yet"
}
"servers" => {
let server_templates = if (($template_base | path join "servers") | path exists) {
ls ($template_base | path join "servers") | get name
| each { |path| { type: "server", name: ($path | path basename), path: $path } }
} else { [] }
format_output $server_templates $format
}
_ => {
print $"Unknown template type: ($template_type)"
}
}
}
# Extract template from existing infrastructure
export def "main template extract" [
source_infra: string, # Source infrastructure path
template_name: string, # Name for the new template
--type: string = "taskserv", # Template type
--output: string = "provisioning/workspace/templates" # Output directory
] {
print $"📤 Extracting template ($template_name) from ($source_infra)"
# Implementation would analyze the source infra and create template
print "Template extraction not yet implemented"
}
# Apply template to infrastructure
export def "main template apply" [
template_name: string, # Template to apply
target_infra: string, # Target infrastructure
--override-file: string = "", # Override file path
--dry-run # Show what would be done
] {
if $dry_run {
print $"🔍 [DRY RUN] Would apply template ($template_name) to ($target_infra)"
} else {
print $"📥 Applying template ($template_name) to ($target_infra)"
}
# Implementation would apply template with overrides
print "Template application not yet implemented"
}
# === LAYER COMMANDS ===
# Show layer information
export def "main layer show" [
workspace: string, # Workspace path
--module: string = "", # Specific module to show
--type: string = "taskservs" # Module type
] {
print $"📊 Layer information for ($workspace)"
if not ($module | is-empty) {
# Use existing layer utilities
try {
nu -c $"use provisioning/workspace/tools/layer-utils.nu *; test_layer_resolution ($module) ($workspace) upcloud"
} catch {
print $"Could not test layer resolution for ($module)"
}
} else {
print "Showing overall layer structure..."
try {
nu -c "use provisioning/workspace/tools/layer-utils.nu *; show_layer_stats"
} catch {
print "Could not show layer statistics"
}
}
}
# Test layer resolution
export def "main layer test" [
module: string, # Module to test
workspace: string, # Workspace/infra name
provider: string = "upcloud" # Provider for testing
] {
print $"🧪 Testing layer resolution: ($module) in ($workspace) with ($provider)"
try {
nu -c $"use provisioning/workspace/tools/layer-utils.nu *; test_layer_resolution ($module) ($workspace) ($provider)"
} catch {
print $"❌ Layer resolution test failed for ($module)"
}
}
# === OVERRIDE COMMANDS ===
# Create configuration override
export def "main override create" [
type: string, # Type: taskservs, providers, clusters
infra: string, # Infrastructure name
module: string, # Module name
--from: string = "", # Template to base override on
--layer: string = "infra" # Layer for override
] {
print $"⚙️ Creating override for ($module) in ($infra) at layer ($layer)"
let override_path = match $layer {
"infra" => $"workspace/infra/($infra)/overrides/($module).k"
"workspace" => $"provisioning/workspace/templates/($type)/($module).k"
_ => {
print $"Unknown layer: ($layer)"
return
}
}
print $"📝 Override will be created at: ($override_path)"
if not ($from | is-empty) {
print $"📋 Based on template: ($from)"
}
# Create directory if needed
mkdir ($override_path | path dirname)
# Create basic override file
let content = if not ($from | is-empty) {
$"# Override for ($module) in ($infra)
# Based on template: ($from)
import ($type).*.($module).kcl.($module) as base
import provisioning.workspace.templates.($type).($from) as template
# Infrastructure-specific overrides
($module)_($infra)_override: base.($module | str capitalize) = template.($from)_template {
# Add your overrides here
# Example:
# replicas = 3
# resources.memory = \"1Gi\"
}
"
} else {
$"# Override for ($module) in ($infra)
import ($type).*.($module).kcl.($module) as base
# Infrastructure-specific overrides
($module)_($infra)_override: base.($module | str capitalize) = base.($module)_config {
# Add your overrides here
# Example:
# replicas = 3
# resources.memory = \"1Gi\"
}
"
}
$content | save $override_path
print $"✅ Override created: ($override_path)"
}
# === WORKSPACE MANAGEMENT ===
# Initialize workspace with modules
export def "main init" [
workspace: string, # Workspace path
--modules: list<string> = [], # Initial modules to load
--template: string = "", # Workspace template
--provider: string = "upcloud" # Default provider
] {
print $"🚀 Initializing workspace: ($workspace)"
# Create workspace structure
let workspace_dirs = [
$"($workspace)/config"
$"($workspace)/taskservs"
$"($workspace)/overrides"
$"($workspace)/defs"
$"($workspace)/clusters"
]
for dir in $workspace_dirs {
mkdir $dir
print $" 📁 Created: ($dir)"
}
# Create basic configuration
let config_content = $"# Workspace configuration for ($workspace)
# Provider: ($provider)
# Initialized: (date now)
provider = "($provider)"
workspace = "($workspace)"
"
$config_content | save $"($workspace)/config/workspace.toml"
print $" 📄 Created: ($workspace)/config/workspace.toml"
# Load initial modules
if ($modules | length) > 0 {
print $"📦 Loading initial modules: (($modules | str join ', '))"
main load taskservs $workspace ...$modules
}
print $"✅ Workspace ($workspace) initialized successfully"
}
# Validate workspace integrity
export def "main validate" [workspace: string] {
print $"🔍 Validating workspace: ($workspace)"
let required_dirs = ["config", "taskservs", "overrides", "defs"]
mut validation_errors = []
for dir in $required_dirs {
let full_path = ($workspace | path join $dir)
if not ($full_path | path exists) {
$validation_errors = ($validation_errors | append $"Missing directory: ($full_path)")
}
}
# Check configuration file
let config_file = ($workspace | path join "config" "workspace.toml")
if not ($config_file | path exists) {
$validation_errors = ($validation_errors | append $"Missing configuration: ($config_file)")
}
# Report results
if ($validation_errors | is-empty) {
print "✅ Workspace validation passed"
return true
} else {
print "❌ Workspace validation failed:"
for error in $validation_errors {
print $" • ($error)"
}
return false
}
}
# Show workspace information
export def "main info" [workspace: string] {
print $"📊 Workspace Information: ($workspace)"
if not (($workspace | path join "config" "workspace.toml") | path exists) {
print "❌ Workspace not found or not initialized"
return
}
# Show basic info
let config = try { open ($workspace | path join "config" "workspace.toml") | from toml } catch { {} }
print $" Provider: (($config.provider? | default 'unknown'))"
print $" Path: ($workspace)"
# Count modules
let taskserv_count = try {
ls ($workspace | path join "taskservs") | length
} catch { 0 }
let override_count = try {
ls ($workspace | path join "overrides") | length
} catch { 0 }
print $" Task Services: ($taskserv_count)"
print $" Overrides: ($override_count)"
# Show recent activity
let recent_files = try {
ls $workspace | where type == file | sort-by modified | last 3 | get name
} catch { [] }
if ($recent_files | length) > 0 {
print " Recent activity:"
for file in $recent_files {
print $" • ($file | path basename)"
}
}
}
# === HELPER FUNCTIONS ===
# Generic extension loading function (taskservs, providers, clusters, workflows)
def load_extension_to_workspace [
extension_type: string, # taskservs, providers, clusters, workflows
workspace: string,
modules: list<string>,
layer: string,
force: bool = false
] {
# Get extension-specific info function based on type
let get_info_fn = match $extension_type {
"taskservs" => { |name| get-taskserv-info $name }
"providers" => { |name| get-provider-info $name }
"clusters" => { |name| get-cluster-info $name }
_ => { |name| {name: $name, group: "", type: $extension_type} }
}
# Get source path from config
let source_base_path = (config-get $"paths.($extension_type)" | path expand)
# Get template base path from config
let provisioning_base = (config-get "paths.base" | path expand)
let template_base_path = ($provisioning_base | path join "workspace" "templates" $extension_type)
for module in $modules {
print $" 📦 Loading ($extension_type): ($module)"
# Get module info
let module_info = try {
do $get_info_fn $module
} catch {
print $" ❌ Module not found: ($module)"
continue
}
print $" ✓ Found: ($module_info.name) (($module_info.group? | default ""))"
# Resolve workspace paths
let workspace_abs = ($workspace | path expand)
let workspace_root = if ($workspace_abs | str contains "/infra/") {
let parts = ($workspace_abs | split row "/infra/")
$parts.0
} else {
$workspace_abs
}
# Build source path (handle optional group, "root" means no category)
let group_path = ($module_info.group? | default "")
let group_path = if ($group_path == "root") { "" } else { $group_path }
let source_module_path = if ($group_path | is-not-empty) {
$source_base_path | path join $group_path $module
} else {
$source_base_path | path join $module
}
# STEP 1: Copy schemas to workspace/.{extension_type}
let target_schemas_dir = ($workspace_root | path join $".($extension_type)")
let target_module_path = if ($group_path | is-not-empty) {
$target_schemas_dir | path join $group_path $module
} else {
$target_schemas_dir | path join $module
}
# Config file directory
let config_dir = ($workspace_abs | path join $extension_type)
let config_file_path = ($config_dir | path join $"($module).k")
# Check if already loaded
if ($config_file_path | path exists) and ($target_module_path | path exists) {
if not $force {
print $" ✅ Module already loaded: ($module)"
print $" Config: ($config_file_path)"
print $" Source: ($target_module_path)"
print $" 💡 Use --force to overwrite existing files"
continue
} else {
print $" 🔄 Overwriting existing module: ($module)"
}
}
# Copy schemas from system extensions to workspace
let parent_dir = ($target_module_path | path dirname)
mkdir $parent_dir
if ($source_module_path | path exists) {
print $" 📦 Copying schemas to workspace .($extension_type)..."
print $" From: ($source_module_path)"
print $" To: ($target_module_path)"
if ($target_module_path | path exists) {
rm -rf $target_module_path
}
cp -r $source_module_path $parent_dir
print $" ✓ Schemas copied to workspace .($extension_type)/"
# STEP 2a: Update individual module's kcl.mod with correct workspace paths
# Calculate relative paths based on categorization depth
let provisioning_path = if ($group_path | is-not-empty) {
# Categorized: .{ext}/{category}/{module}/kcl/ -> ../../../../.kcl/packages/provisioning
"../../../../.kcl/packages/provisioning"
} else {
# Non-categorized: .{ext}/{module}/kcl/ -> ../../../.kcl/packages/provisioning
"../../../.kcl/packages/provisioning"
}
let parent_path = if ($group_path | is-not-empty) {
# Categorized: .{ext}/{category}/{module}/kcl/ -> ../../..
"../../.."
} else {
# Non-categorized: .{ext}/{module}/kcl/ -> ../..
"../.."
}
# Update the module's kcl.mod file with workspace-relative paths
let module_kcl_mod_path = ($target_module_path | path join "kcl" "kcl.mod")
if ($module_kcl_mod_path | path exists) {
print $" 🔧 Updating module kcl.mod with workspace paths"
let module_kcl_mod_content = $"[package]
name = \"($module)\"
edition = \"v0.11.3\"
version = \"0.0.1\"
[dependencies]
provisioning = { path = \"($provisioning_path)\", version = \"0.0.1\" }
($extension_type) = { path = \"($parent_path)\", version = \"0.1.0\" }
"
$module_kcl_mod_content | save -f $module_kcl_mod_path
print $" ✓ Updated kcl.mod: ($module_kcl_mod_path)"
}
} else {
print $" ⚠️ Warning: Source not found at ($source_module_path)"
}
# STEP 2b: Create kcl.mod in workspace/.{extension_type}
let extension_kcl_mod = ($target_schemas_dir | path join "kcl.mod")
if not ($extension_kcl_mod | path exists) {
print $" 📦 Creating kcl.mod for .($extension_type) package"
let kcl_mod_content = $"[package]
name = \"($extension_type)\"
edition = \"v0.11.3\"
version = \"0.1.0\"
description = \"Workspace-level ($extension_type) schemas\"
"
$kcl_mod_content | save $extension_kcl_mod
}
# Ensure config directory exists
mkdir $config_dir
# STEP 4: Generate config from template
let template_path = if ($group_path | is-not-empty) {
$template_base_path | path join $group_path $"($module).k"
} else {
$template_base_path | path join $"($module).k"
}
# Build import statement with "as {module}" alias
let import_stmt = if ($group_path | is-not-empty) {
$"import ($extension_type).($group_path).($module).kcl.($module) as ($module)"
} else {
$"import ($extension_type).($module).kcl.($module) as ($module)"
}
# Get relative paths for comments
let workspace_name = ($workspace_root | path basename)
let relative_schema_path = if ($group_path | is-not-empty) {
$"($workspace_name)/.($extension_type)/($group_path)/($module)"
} else {
$"($workspace_name)/.($extension_type)/($module)"
}
let config_content = if ($template_path | path exists) {
print $" 📄 Using template from: ($template_path)"
let template_body = (open $template_path)
$"# Configuration for ($module)
# Workspace: ($workspace_name)
# Schemas from: ($relative_schema_path)
($import_stmt)
($template_body)"
} else {
$"# Configuration for ($module)
# Workspace: ($workspace_name)
# Schemas from: ($relative_schema_path)
($import_stmt)
# TODO: Configure your ($module) instance
# See available schemas at: ($relative_schema_path)/kcl/
"
}
$config_content | save -f $config_file_path
print $" ✓ Config created: ($config_file_path)"
print $" 📝 Edit ($extension_type)/($module).k to configure settings"
# STEP 3: Update infra kcl.mod
if ($workspace_abs | str contains "/infra/") {
let kcl_mod_path = ($workspace_abs | path join "kcl.mod")
if ($kcl_mod_path | path exists) {
let kcl_mod_content = (open $kcl_mod_path)
if not ($kcl_mod_content | str contains $"($extension_type) =") {
print $" 🔧 Updating kcl.mod to include ($extension_type) dependency"
let new_dependency = $"\n# Workspace-level ($extension_type) \(shared across infras\)\n($extension_type) = { path = \"../../.($extension_type)\" }\n"
$"($kcl_mod_content)($new_dependency)" | save -f $kcl_mod_path
}
}
}
}
}
# Unload taskserv from workspace
def unload_taskserv_from_workspace [workspace: string, module: string, layer: string] {
let target_path = match $layer {
"workspace" => ($workspace | path join "taskservs" $"($module).k")
"infra" => ($workspace | path join "overrides" $"($module).k")
_ => ($workspace | path join "taskservs" $"($module).k")
}
if ($target_path | path exists) {
rm $target_path
print $" ✓ Removed: ($target_path)"
} else {
print $" ❌ Not found: ($target_path)"
}
}
# List workspace taskservs
def list_workspace_taskservs [workspace: string, layer: string, format: string] {
let paths = match $layer {
"workspace" => [($workspace | path join "taskservs")]
"infra" => [($workspace | path join "overrides")]
"all" => [($workspace | path join "taskservs"), ($workspace | path join "overrides")]
_ => [($workspace | path join "taskservs")]
}
mut all_taskservs = []
for path in $paths {
if ($path | path exists) {
let taskservs = ls $path
| where type == file
| where name =~ '\\.k$'
| each { |file|
{
name: ($file.name | path basename | str replace ".k" "")
layer: ($path | path basename)
path: $file.name
modified: $file.modified
}
}
$all_taskservs = ($all_taskservs | append $taskservs)
}
}
format_output $all_taskservs $format
}
# Format output based on requested format
def format_output [data: any, format: string] {
match $format {
"json" => ($data | to json)
"yaml" => ($data | to yaml)
"names" => ($data | get name | str join "\n")
"table" | _ => ($data | table)
}
}
# === HELP FUNCTIONS ===
def print_enhanced_help [] {
print "Enhanced Module Loader CLI - Discovery and loading with template support"
print ""
print "Usage: module-loader <command> [options]"
print ""
print "CORE COMMANDS:"
print " discover <type> [query] [--format <fmt>] [--category <cat>] - Discover available modules"
print " sync-kcl <infra> [--manifest <file>] [--kcl] - Sync KCL dependencies for infrastructure"
print " load <type> <workspace> <modules...> [--layer <layer>] - Load modules into workspace"
print " list <type> <workspace> [--layer <layer>] - List loaded modules"
print " unload <type> <workspace> <module> [--layer <layer>] - Unload module from workspace"
print ""
print "WORKSPACE COMMANDS:"
print " init <workspace> [--modules <list>] [--template <name>] - Initialize workspace"
print " validate <workspace> - Validate workspace integrity"
print " info <workspace> - Show workspace information"
print ""
print "TEMPLATE COMMANDS:"
print " template list [--type <type>] [--format <fmt>] - List available templates"
print " template extract <source> <name> [--type <type>] - Extract template from infra"
print " template apply <template> <target> [--dry-run] - Apply template to infra"
print ""
print "LAYER COMMANDS:"
print " layer show <workspace> [--module <name>] - Show layer information"
print " layer test <module> <workspace> [provider] - Test layer resolution"
print ""
print "OVERRIDE COMMANDS:"
print " override create <type> <infra> <module> [--from <template>] - Create configuration override"
print ""
print "ENHANCED COMMANDS:"
print " load enhanced <type> <workspace> <infra> <modules> [--layer <layer>] - Enhanced template loading"
print ""
print "Types: taskservs, providers, clusters"
print "Layers: workspace, infra, all"
print "Formats: table, json, yaml, names"
print ""
print "Examples:"
print " module-loader discover taskservs --category databases"
print " module-loader load taskservs ./workspace [redis, postgres]"
print " module-loader template list --type taskservs"
print " module-loader layer test redis wuji upcloud"
print " module-loader override create taskservs wuji kubernetes --from ha-cluster"
}
def print_discover_help [] {
print "Discover available modules"
print ""
print "Usage: module-loader discover <type> [query] [options]"
print ""
print "Options:"
print " --format <fmt> Output format: table, json, yaml, names (default: table)"
print " --category <cat> Filter by category (taskservs only)"
print " --group <group> Filter by group (taskservs only)"
print ""
print "Examples:"
print " module-loader discover taskservs"
print " module-loader discover taskservs redis"
print " module-loader discover taskservs --category databases"
print " module-loader discover taskservs --format json"
}
def print_load_help [] {
print "Load modules into workspace"
print ""
print "Usage: module-loader load <type> <workspace> <modules...> [options]"
print ""
print "Options:"
print " --layer <layer> Target layer: workspace, infra (default: workspace)"
print " --validate Validate workspace after loading"
print ""
print "Examples:"
print " module-loader load taskservs ./workspace [kubernetes, cilium]"
print " module-loader load taskservs ./workspace [redis] --layer infra"
}
def print_list_help [] {
print "List modules in workspace"
print ""
print "Usage: module-loader list <type> <workspace> [options]"
print ""
print "Options:"
print " --layer <layer> Layer to list: workspace, infra, all (default: all)"
print " --format <fmt> Output format: table, json, yaml, names"
print ""
print "Examples:"
print " module-loader list taskservs ./workspace"
print " module-loader list taskservs ./workspace --layer workspace"
}
def print_unload_help [] {
print "Unload module from workspace"
print ""
print "Usage: module-loader unload <type> <workspace> <module> [options]"
print ""
print "Options:"
print " --layer <layer> Layer to unload from: workspace, infra (default: workspace)"
print ""
print "Examples:"
print " module-loader unload taskservs ./workspace kubernetes"
print " module-loader unload taskservs ./workspace redis --layer infra"
}
def print_init_help [] {
print "Initialize workspace with modules"
print ""
print "Usage: module-loader init <workspace> [options]"
print ""
print "Options:"
print " --modules <list> Initial modules to load"
print " --template <name> Workspace template to use"
print " --provider <name> Default provider (default: upcloud)"
print ""
print "Examples:"
print " module-loader init ./my-workspace"
print " module-loader init ./k8s-workspace --modules [kubernetes, cilium]"
}
def print_validate_help [] {
print "Validate workspace integrity"
print ""
print "Usage: module-loader validate <workspace>"
print ""
print "Examples:"
print " module-loader validate ./workspace"
}
def print_info_help [] {
print "Show workspace information"
print ""
print "Usage: module-loader info <workspace>"
print ""
print "Examples:"
print " module-loader info ./workspace"
}
def print_template_help [] {
print "Template management commands"
print ""
print "Usage: module-loader template <subcommand> [options]"
print ""
print "Subcommands:"
print " list List available templates"
print " extract Extract template from existing infrastructure"
print " apply Apply template to infrastructure"
print ""
print "Examples:"
print " module-loader template list --type taskservs"
print " module-loader template extract ./wuji wuji-production"
print " module-loader template apply wuji-production ./new-infra"
}
def print_layer_help [] {
print "Layer resolution commands"
print ""
print "Usage: module-loader layer <subcommand> [options]"
print ""
print "Subcommands:"
print " show Show layer information for workspace"
print " test Test layer resolution for specific module"
print ""
print "Examples:"
print " module-loader layer show ./workspace"
print " module-loader layer test kubernetes wuji upcloud"
}
def print_override_help [] {
print "Configuration override commands"
print ""
print "Usage: module-loader override create <type> <infra> <module> [options]"
print ""
print "Options:"
print " --from <template> Base override on template"
print " --layer <layer> Target layer: infra, workspace (default: infra)"
print ""
print "Examples:"
print " module-loader override create taskservs wuji kubernetes"
print " module-loader override create taskservs wuji redis --from databases/redis"
}