2025-10-07 10:32:04 +01:00

324 lines
11 KiB
Plaintext

# Command Dispatcher
# Central routing logic for all provisioning commands
use flags.nu *
use commands/infrastructure.nu *
use commands/orchestration.nu *
use commands/development.nu *
use commands/workspace.nu *
use commands/generation.nu *
use commands/utilities.nu *
use commands/configuration.nu *
use commands/guides.nu *
use ../lib_provisioning *
use ../lib_provisioning/workspace/enforcement.nu *
# Helper to run module commands
def run_module [
args: string
module: string
option?: string
--exec
] {
let use_debug = if ($env.PROVISIONING_DEBUG? | default false) { "-x" } else { "" }
if $exec {
exec $"($env.PROVISIONING_NAME)" $use_debug -mod $module ($option | default "") $args
} else {
^$"($env.PROVISIONING_NAME)" $use_debug -mod $module ($option | default "") $args
}
}
# Command registry with shortcuts and aliases
# Maps short forms and aliases to their canonical command domain
export def get_command_registry []: nothing -> record {
{
# Infrastructure commands (server, taskserv, cluster, infra)
"s": "infrastructure server"
"server": "infrastructure server"
"t": "infrastructure taskserv"
"task": "infrastructure taskserv"
"taskserv": "infrastructure taskserv"
"cl": "infrastructure cluster"
"cluster": "infrastructure cluster"
"i": "infrastructure infra"
"infra": "infrastructure infra"
"infras": "infrastructure infra"
# Orchestration commands (workflow, batch, orchestrator)
"wf": "orchestration workflow"
"flow": "orchestration workflow"
"workflow": "orchestration workflow"
"bat": "orchestration batch"
"batch": "orchestration batch"
"orch": "orchestration orchestrator"
"orchestrator": "orchestration orchestrator"
# Development commands (module, layer, version, pack)
"mod": "development module"
"module": "development module"
"lyr": "development layer"
"layer": "development layer"
"version": "development version"
"pack": "development pack"
# Module discover shortcuts
"discover": "development module discover"
"disc": "development module discover"
"discover-taskservs": "development module discover taskservs"
"disc-t": "development module discover taskservs"
"dt": "development module discover taskservs"
"discover-providers": "development module discover providers"
"disc-p": "development module discover providers"
"dp": "development module discover providers"
"discover-clusters": "development module discover clusters"
"disc-c": "development module discover clusters"
"dc": "development module discover clusters"
# Workspace commands (workspace, template)
"ws": "workspace workspace"
"workspace": "workspace workspace"
"tpl": "workspace template"
"tmpl": "workspace template"
"template": "workspace template"
# Configuration commands (env, allenv, show, init, validate)
"e": "config env"
"env": "config env"
"allenv": "config allenv"
"show": "config show"
"init": "config init"
"validate": "config validate"
"val": "config validate"
"config-template": "config config-template"
# Utility commands (ssh, sed, sops, cache, providers, etc.)
"ssh": "utils ssh"
"sed": "utils sed"
"sops": "utils sops"
"cache": "utils cache"
"providers": "utils providers"
"nu": "utils nu"
# Test environment commands
"test": "test"
"tst": "test"
"list": "utils list"
"l": "utils list"
"ls": "utils list"
"qr": "utils qr"
"nuinfo": "utils nuinfo"
"plugin": "utils plugin"
"plugins": "utils plugins"
# Generation commands
"g": "generation generate"
"gen": "generation generate"
"generate": "generation generate"
# Guide commands
"guide": "guides guide"
"guides": "guides guide"
"sc": "guides sc"
"shortcuts": "guides sc"
"howto": "guides guide list"
# Special commands (handled separately)
"h": "help"
"c": "create"
"create": "create"
"d": "delete"
"delete": "delete"
"u": "update"
"update": "update"
"price": "price"
"prices": "price"
"cost": "price"
"costs": "price"
"cst": "create-server-task"
"create-server-task": "create-server-task"
"csts": "create-server-task"
"create-servers-tasks": "create-server-task"
"deploy-rm": "deploy"
"deploy-del": "deploy"
"dp-rm": "deploy"
"d-r": "deploy"
"destroy": "deploy"
"deploy-sel": "deploy-sel"
"deploy-list": "deploy-sel"
"dp-sel": "deploy-sel"
"d-s": "deploy-sel"
"deploy-sel-tree": "deploy-sel-tree"
"deploy-list-tree": "deploy-sel-tree"
"dp-sel-t": "deploy-sel-tree"
"d-st": "deploy-sel-tree"
"new": "new"
"ai": "ai"
"context": "context"
"ctx": "context"
"setup": "setup"
"st": "setup"
"config": "setup"
"control-center": "control-center"
"mcp-server": "mcp-server"
}
}
# Main command dispatcher
# Routes commands to appropriate domain handlers
export def dispatch_command [
args: list
flags: record
] {
let task = if ($args | length) > 0 { ($args | get 0) } else { "" }
let ops_list = ($args | skip 1)
let ops_str = ($ops_list | str join " ")
# Handle empty command
if ($task | is-empty) {
print "Use 'provisioning help' for available commands"
exit
}
# Intercept bi-directional help: "provisioning <cmd> help" → "provisioning help <cmd>"
# This ensures shortcuts like "provisioning ws help" work correctly
let first_op = if ($ops_list | length) > 0 { ($ops_list | get 0) } else { "" }
if $first_op in ["help" "h"] {
# Redirect to categorized help system
exec $"($env.PROVISIONING_NAME)" help $task --notitles
}
# Resolve command through registry
let registry = get_command_registry
let resolved = ($registry | get -o $task | default $task)
# Split into domain, command, and optional subcommand args
let parts = ($resolved | split row " ")
let domain = if ($parts | length) > 1 { ($parts | get 0) } else { "special" }
let command = if ($parts | length) > 1 { ($parts | get 1) } else { $task }
# Extract any additional parts as pre-filled ops (for compound shortcuts like "dt" → "discover taskservs")
let extra_ops = if ($parts | length) > 2 {
($parts | skip 2 | str join " ")
} else {
""
}
# Combine extra_ops with user-provided ops
let final_ops = if ($extra_ops | is-not-empty) and ($ops_str | is-not-empty) {
$"($extra_ops) ($ops_str)"
} else if ($extra_ops | is-not-empty) {
$extra_ops
} else {
$ops_str
}
# WORKSPACE ENFORCEMENT - Check workspace requirement before processing
# This enforces that most commands require an active workspace
let enforcement_allowed = (check-and-enforce $task $args)
if not $enforcement_allowed {
# Enforcement failed - error already displayed by check-and-enforce
exit 1
}
# Set environment based on flags
set_debug_env $flags
# Dispatch to domain handler
match $domain {
"infrastructure" => { handle_infrastructure_command $command $final_ops $flags }
"orchestration" => { handle_orchestration_command $command $final_ops $flags }
"development" => { handle_development_command $command $final_ops $flags }
"workspace" => { handle_workspace_command $command $final_ops $flags }
"config" => { handle_config_command $command $final_ops $flags }
"utils" => { handle_utility_command $command $final_ops $flags }
"generation" => { handle_generation_command $command $final_ops $flags }
"guides" => { handle_guide_command $command $final_ops $flags }
"special" => { handle_special_command $command $final_ops $flags }
"test" => { handle_test_command $command $final_ops $flags }
"help" => { exec $"($env.PROVISIONING_NAME)" help $command --notitles }
_ => {
invalid_task "" $task --end
exit 1
}
}
}
# Test command handler
def handle_test_command [command: string, ops: string, flags: record] {
let args = if ($ops | is-not-empty) { $ops } else { "" }
run_module $args "test" --exec
}
# Special command handler (create, delete, update, deploy, etc.)
def handle_special_command [command: string, ops: string, flags: record] {
match $command {
"create" | "c" => {
let use_debug = if $flags.debug_mode or ($env.PROVISIONING_DEBUG? | default false) { "-x" } else { "" }
let use_check = if $flags.check_mode { "--check " } else { "" }
let str_infra = if ($flags.infra | is-not-empty) { $"--infra ($flags.infra) " } else { "" }
let str_out = if ($flags.outfile | is-not-empty) { $"--outfile ($flags.outfile) " } else { "" }
exec $"($env.PROVISIONING_NAME)" $use_debug "create" $ops $use_check $str_infra $str_out --notitles
}
"delete" | "d" => {
let use_debug = if $flags.debug_mode { "-x" } else { "" }
let use_check = if $flags.check_mode { "--check " } else { "" }
let use_yes = if $flags.auto_confirm { "--yes " } else { "" }
let use_keepstorage = if $flags.keep_storage { "--keepstorage " } else { "" }
let str_infra = if ($flags.infra | is-not-empty) { $"--infra ($flags.infra) " } else { "" }
exec $"($env.PROVISIONING_NAME)" "delete" $ops $use_check $use_yes $use_keepstorage $str_infra --notitles
}
"update" | "u" => {
let use_debug = if $flags.debug_mode { "-x" } else { "" }
let use_check = if $flags.check_mode { "--check " } else { "" }
let str_infra = if ($flags.infra | is-not-empty) { $"--infra ($flags.infra) " } else { "" }
exec $"($env.PROVISIONING_NAME)" "update" $ops $use_check $str_infra --notitles
}
"price" | "prices" | "cost" | "costs" => {
handle_price_command $ops $flags
}
"create-server-task" | "cst" | "csts" | "create-servers-tasks" => {
handle_create_server_task $ops $flags
}
"new" => {
let str_new = ($flags.new_infra | default "")
print $"\n (_ansi yellow)New Infra ($str_new)(_ansi reset)"
}
"ai" => {
let str_infra = if ($flags.infra | is-not-empty) { $"--infra ($flags.infra) " } else { "" }
let str_settings = if ($flags.settings | is-not-empty) { $"--settings ($flags.settings) " } else { "" }
let str_out = if ($flags.output_format | is-not-empty) { $"--out ($flags.output_format) " } else { "" }
run_module $"($ops) ($str_infra) ($str_settings) ($str_out)" "ai" --exec
}
"context" | "ctx" => {
^$"($env.PROVISIONING_NAME)" "context" $ops --notitles
run_module $ops "" --exec
}
"setup" | "st" | "config" => {
run_module $ops "setup" --exec
}
"control-center" => {
run_module $ops "control-center" --exec
}
"mcp-server" => {
run_module $ops "mcp-server" --exec
}
_ => {
print $"❌ Unknown command: ($command)"
print "Use 'provisioning help' for available commands"
exit 1
}
}
}