295 lines
9.7 KiB
Text
295 lines
9.7 KiB
Text
# Orchestration Command Handlers
|
|
# Handles: job (orchestrator jobs), workflow (WorkflowDef), batch, orchestrator commands
|
|
|
|
use cli/flags.nu *
|
|
# REMOVED: use ../../lib_provisioning * - causes circular import
|
|
use platform/plugins/auth.nu *
|
|
use platform/mod.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
|
|
}
|
|
}
|
|
|
|
# Main orchestration command dispatcher
|
|
export def handle_orchestration_command [
|
|
command: string
|
|
ops: string
|
|
flags: record
|
|
] {
|
|
set_debug_env $flags
|
|
|
|
match $command {
|
|
"job" => { handle_job $ops $flags }
|
|
"workflow" => { handle_workflowdef $ops $flags }
|
|
"batch" => { handle_batch $ops $flags }
|
|
"orchestrator" => { handle_orchestrator $ops $flags }
|
|
_ => {
|
|
print $"❌ Unknown orchestration command: ($command)"
|
|
print ""
|
|
print "Available orchestration commands:"
|
|
print " job - Orchestrator job management (list, status, monitor, submit)"
|
|
print " workflow - Workspace WorkflowDef management (list, show, run, validate, status)"
|
|
print " batch - Batch operations (submit, monitor, rollback, stats)"
|
|
print " orchestrator - Orchestrator lifecycle (start, stop, status, health)"
|
|
print ""
|
|
print "Use 'provisioning help orchestration' for more details"
|
|
exit 1
|
|
}
|
|
}
|
|
}
|
|
|
|
# Job command handler — orchestrator HTTP API jobs
|
|
def handle_job [ops: string, flags: record] {
|
|
# Authentication check for workflow operations (metadata-driven)
|
|
let operation_parts = ($ops | split row " ")
|
|
let action = if ($operation_parts | is-empty) { "" } else { $operation_parts | first }
|
|
|
|
# Determine operation type
|
|
let operation_type = match $action {
|
|
"rollback" | "cancel" => "delete"
|
|
"submit" | "create" => "create"
|
|
"update" | "modify" => "modify"
|
|
_ => "read"
|
|
}
|
|
|
|
# Check authentication using metadata-driven approach
|
|
if not (is-check-mode $flags) and $operation_type != "read" {
|
|
let operation_name = $"job ($action)"
|
|
check-operation-auth $operation_name $operation_type $flags
|
|
}
|
|
|
|
# Call job management commands directly (avoid -mod routing conflict)
|
|
use orchestration/workflows/management.nu *
|
|
|
|
let orchestrator = ($flags.orchestrator? | default "")
|
|
let status_filter = ($flags.status? | default "")
|
|
let days = ($flags.days? | default 7 | into int)
|
|
let dry_run = ($flags.dry_run? | default false)
|
|
|
|
# DEBUG
|
|
if $action == "browse" {
|
|
print $"DEBUG: Handling browse action, ops=($ops)"
|
|
}
|
|
|
|
match $action {
|
|
"list" => {
|
|
let limit_arg = if ($operation_parts | length) > 1 {
|
|
let limit_str = ($operation_parts | get 1 | str trim)
|
|
let result = (do { $limit_str | into int } | complete)
|
|
if $result.exit_code == 0 { ($result.stdout | str trim | into int) } else { null }
|
|
} else {
|
|
null
|
|
}
|
|
|
|
if ($limit_arg | is-not-empty) {
|
|
job list $limit_arg --orchestrator $orchestrator --status $status_filter
|
|
} else {
|
|
job list --orchestrator $orchestrator --status $status_filter
|
|
}
|
|
}
|
|
"status" => {
|
|
if ($operation_parts | length) < 2 {
|
|
print "❌ Error: job status requires a task ID"
|
|
return
|
|
}
|
|
let task_id = ($operation_parts | get 1)
|
|
job status $task_id --orchestrator $orchestrator
|
|
}
|
|
"monitor" => {
|
|
if ($operation_parts | length) < 2 {
|
|
print "❌ Error: job monitor requires a task ID"
|
|
return
|
|
}
|
|
let task_id = ($operation_parts | get 1)
|
|
job monitor $task_id --orchestrator $orchestrator
|
|
}
|
|
"stats" => { job stats --orchestrator $orchestrator }
|
|
"cleanup" => {
|
|
if $dry_run {
|
|
job cleanup --orchestrator $orchestrator --days $days --dry-run
|
|
} else {
|
|
job cleanup --orchestrator $orchestrator --days $days
|
|
}
|
|
}
|
|
"orchestrator" => { job orchestrator --orchestrator $orchestrator }
|
|
"browse" => {
|
|
let limit_arg = if ($operation_parts | length) > 1 {
|
|
let limit_str = ($operation_parts | get 1 | str trim)
|
|
let result = (do { $limit_str | into int } | complete)
|
|
if $result.exit_code == 0 { ($result.stdout | str trim | into int) } else { null }
|
|
} else {
|
|
null
|
|
}
|
|
|
|
if ($limit_arg | is-not-empty) {
|
|
job browse $limit_arg --orchestrator $orchestrator
|
|
} else {
|
|
job browse --orchestrator $orchestrator
|
|
}
|
|
}
|
|
"submit" => {
|
|
if ($operation_parts | length) < 4 {
|
|
print "❌ Error: job submit requires: job_type operation target [infra] [settings]"
|
|
return
|
|
}
|
|
let job_type = ($operation_parts | get 1)
|
|
let operation_name = ($operation_parts | get 2)
|
|
let target = ($operation_parts | get 3)
|
|
let infra = if ($operation_parts | length) > 4 { $operation_parts | get 4 } else { "" }
|
|
let settings = if ($operation_parts | length) > 5 { $operation_parts | get 5 } else { "" }
|
|
let check_mode = (is-check-mode $flags)
|
|
let wait = ($flags.wait? | default false)
|
|
|
|
job submit $job_type $operation_name $target $infra $settings --check=$check_mode --wait=$wait --orchestrator $orchestrator
|
|
}
|
|
"" => {
|
|
print "❌ Error: job subcommand required — use: list, status, monitor, stats, cleanup, browse, submit"
|
|
return
|
|
}
|
|
_ => {
|
|
print $"❌ Error: unknown job subcommand '$action'"
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
# WorkflowDef command handler — workspace workflow declarations (workflows/*.ncl)
|
|
def handle_workflowdef [ops: string, flags: record] {
|
|
let parts = ($ops | split row " ")
|
|
let action = if ($parts | is-empty) { "" } else { $parts | first }
|
|
let workspace = ($flags.workspace? | default ($flags.ws? | default ""))
|
|
let infra = ($flags.infra? | default "")
|
|
let dry_run = ($flags.dry_run? | default false)
|
|
|
|
use ../../cli/workflow.nu *
|
|
|
|
match $action {
|
|
"list" => {
|
|
if ($workspace | is-not-empty) {
|
|
main workflow list --workspace $workspace
|
|
} else {
|
|
main workflow list
|
|
}
|
|
}
|
|
"show" => {
|
|
if ($parts | length) < 2 {
|
|
print "❌ Error: workflow show requires a workflow id"
|
|
return
|
|
}
|
|
let wf_id = ($parts | get 1)
|
|
if ($workspace | is-not-empty) {
|
|
use ../../cli/ontoref_queries.nu *
|
|
main describe workflow $wf_id --workspace $workspace
|
|
} else {
|
|
use ../../cli/ontoref_queries.nu *
|
|
main describe workflow $wf_id
|
|
}
|
|
}
|
|
"run" => {
|
|
if ($parts | length) < 2 {
|
|
print "❌ Error: workflow run requires a workflow id"
|
|
return
|
|
}
|
|
let wf_id = ($parts | get 1)
|
|
if ($workspace | is-not-empty) and $dry_run {
|
|
main workflow run $wf_id --workspace $workspace --dry-run
|
|
} else if ($workspace | is-not-empty) {
|
|
main workflow run $wf_id --workspace $workspace
|
|
} else if $dry_run {
|
|
main workflow run $wf_id --dry-run
|
|
} else {
|
|
main workflow run $wf_id
|
|
}
|
|
}
|
|
"validate" => {
|
|
if ($workspace | is-not-empty) {
|
|
main workflow validate --workspace $workspace
|
|
} else {
|
|
main workflow validate
|
|
}
|
|
}
|
|
"status" => {
|
|
if ($parts | length) < 2 {
|
|
print "❌ Error: workflow status requires a workflow id"
|
|
return
|
|
}
|
|
let wf_id = ($parts | get 1)
|
|
if ($workspace | is-not-empty) {
|
|
main workflow status $wf_id --workspace $workspace
|
|
} else {
|
|
main workflow status $wf_id
|
|
}
|
|
}
|
|
"" => {
|
|
print "❌ Error: workflow subcommand required"
|
|
print ""
|
|
print " list [--workspace <ws>] List workspace WorkflowDef declarations"
|
|
print " show <id> [--workspace <ws>] Show workflow definition + FSM state"
|
|
print " run <id> [--workspace <ws>] Execute a WorkflowDef"
|
|
print " validate [--workspace <ws>] Cross-validate workflows against components"
|
|
print " status <id> [--workspace <ws>] Show FSM dimension state"
|
|
}
|
|
_ => {
|
|
print $"❌ Unknown workflow subcommand: ($action)"
|
|
}
|
|
}
|
|
}
|
|
|
|
# Batch command handler
|
|
def handle_batch [ops: string, flags: record] {
|
|
# Authentication check for batch operations (metadata-driven)
|
|
let operation_parts = ($ops | split row " ")
|
|
let action = if ($operation_parts | is-empty) { "" } else { $operation_parts | first }
|
|
|
|
# Determine operation type
|
|
let operation_type = match $action {
|
|
"submit" | "create" => "create"
|
|
"rollback" | "cancel" => "delete"
|
|
"update" | "modify" => "modify"
|
|
_ => "read"
|
|
}
|
|
|
|
# Check authentication using metadata-driven approach
|
|
if not (is-check-mode $flags) and $operation_type != "read" {
|
|
let operation_name = $"batch ($action)"
|
|
check-operation-auth $operation_name $operation_type $flags
|
|
}
|
|
|
|
let args = build_module_args $flags $ops
|
|
run_module $args "batch" --exec
|
|
}
|
|
|
|
# Orchestrator command handler
|
|
def handle_orchestrator [ops: string, flags: record] {
|
|
# Authentication check for orchestrator operations (metadata-driven)
|
|
let operation_parts = ($ops | split row " ")
|
|
let action = if ($operation_parts | is-empty) { "" } else { $operation_parts | first }
|
|
|
|
# Determine operation type (orchestrator start/stop are modify operations)
|
|
let operation_type = match $action {
|
|
"start" => "modify"
|
|
"stop" => "modify"
|
|
_ => "read"
|
|
}
|
|
|
|
# Check authentication using metadata-driven approach
|
|
if not (is-check-mode $flags) and $operation_type != "read" {
|
|
let operation_name = $"orchestrator ($action)"
|
|
check-operation-auth $operation_name $operation_type $flags
|
|
}
|
|
|
|
# Orchestrator has simpler argument requirements
|
|
run_module $ops "orchestrator" --exec
|
|
}
|