# 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 ] List workspace WorkflowDef declarations" print " show [--workspace ] Show workflow definition + FSM state" print " run [--workspace ] Execute a WorkflowDef" print " validate [--workspace ] Cross-validate workflows against components" print " status [--workspace ] 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 }