Update core components including CLI, Nushell libraries, plugins system, and utility scripts for the provisioning system. CLI Updates: - Command implementations - CLI utilities and dispatching - Help system improvements - Command validation Library Updates: - Configuration management system - Infrastructure validation - Extension system improvements - Secrets management - Workspace operations - Cache management system Plugin System: - Interactive form plugin (inquire) - KCL integration plugin - Performance optimization plugins - Plugin registration system Utilities: - Build and distribution scripts - Installation procedures - Testing utilities - Development tools Documentation: - Library module documentation - Extension API guides - Plugin usage guides - Service management documentation All changes are backward compatible. No breaking changes.
251 lines
8.1 KiB
Plaintext
251 lines
8.1 KiB
Plaintext
use std
|
|
use ../lib_provisioning *
|
|
use ../lib_provisioning/platform *
|
|
use ../servers/utils.nu *
|
|
|
|
# Workflow definition for server creation
|
|
|
|
# Get orchestrator endpoint from platform configuration or use provided default
|
|
def get-orchestrator-url [--orchestrator: string = ""] {
|
|
if ($orchestrator | is-not-empty) {
|
|
$orchestrator
|
|
} else {
|
|
"http://localhost:9090"
|
|
}
|
|
}
|
|
|
|
# Detect if orchestrator URL is local (for plugin usage)
|
|
def use-local-plugin [orchestrator_url: string] {
|
|
# Check if it's a local endpoint
|
|
(detect-platform-mode $orchestrator_url) == "local"
|
|
}
|
|
|
|
export def server_create_workflow [
|
|
infra: string # Infrastructure target
|
|
settings?: string # Settings file path
|
|
servers?: list # Specific servers to create (empty = all)
|
|
--check (-c) # Check mode only
|
|
--wait (-w) # Wait for completion
|
|
--orchestrator: string = "" # Orchestrator URL (optional, uses platform config if not provided)
|
|
] {
|
|
let orch_url = (get-orchestrator-url --orchestrator=$orchestrator)
|
|
let workflow_data = {
|
|
infra: $infra,
|
|
settings: ($settings | default ""),
|
|
servers: ($servers | default []),
|
|
check_mode: $check,
|
|
wait: $wait
|
|
}
|
|
|
|
# Submit to orchestrator
|
|
let response = (http post $"($orch_url)/workflows/servers/create" --content-type "application/json" ($workflow_data | to json))
|
|
|
|
if not ($response | get success) {
|
|
return { status: "error", message: ($response | get error) }
|
|
}
|
|
|
|
let task_id = ($response | get data)
|
|
_print $"Server creation workflow submitted: ($task_id)"
|
|
|
|
if $wait {
|
|
wait_for_workflow_completion $orch_url $task_id
|
|
} else {
|
|
{ status: "submitted", task_id: $task_id }
|
|
}
|
|
}
|
|
|
|
def wait_for_workflow_completion [orchestrator: string, task_id: string]: nothing -> record {
|
|
_print "Waiting for workflow completion..."
|
|
|
|
mut result = { status: "pending" }
|
|
|
|
while true {
|
|
# Use plugin for local orchestrator (<5ms vs ~50ms with HTTP)
|
|
let task = if (use-local-plugin $orchestrator) {
|
|
let all_tasks = (orch tasks)
|
|
let found = ($all_tasks | where id == $task_id | first)
|
|
|
|
if ($found | is-empty) {
|
|
return { status: "error", message: "Task not found" }
|
|
}
|
|
|
|
$found
|
|
} else {
|
|
# Fall back to HTTP for remote orchestrators
|
|
let status_response = (http get $"($orchestrator)/tasks/($task_id)")
|
|
|
|
if not ($status_response | get success) {
|
|
return { status: "error", message: "Failed to get task status" }
|
|
}
|
|
|
|
($status_response | get data)
|
|
}
|
|
|
|
let task_status = ($task | get status)
|
|
|
|
match $task_status {
|
|
"Completed" => {
|
|
_print $"✅ Workflow completed successfully"
|
|
if ($task | get output | is-not-empty) {
|
|
_print "Output:"
|
|
_print ($task | get output)
|
|
}
|
|
$result = { status: "completed", task: $task }
|
|
break
|
|
},
|
|
"Failed" => {
|
|
_print $"❌ Workflow failed"
|
|
if ($task | get error | is-not-empty) {
|
|
_print "Error:"
|
|
_print ($task | get error)
|
|
}
|
|
$result = { status: "failed", task: $task }
|
|
break
|
|
},
|
|
"Running" => {
|
|
_print $"🔄 Workflow is running..."
|
|
},
|
|
_ => {
|
|
_print $"⏳ Workflow status: ($task_status)"
|
|
}
|
|
}
|
|
|
|
sleep 2sec
|
|
}
|
|
|
|
return $result
|
|
}
|
|
|
|
# Bridge function to convert legacy server create calls to workflow
|
|
export def on_create_servers_workflow [
|
|
settings: record # Settings record
|
|
check: bool # Only check mode no servers will be created
|
|
wait: bool # Wait for creation
|
|
outfile?: string # Out file for creation
|
|
hostname?: string # Server hostname in settings
|
|
serverpos?: int # Server position in settings
|
|
--orchestrator: string = "http://localhost:8080" # Orchestrator URL
|
|
]: nothing -> record {
|
|
|
|
# Convert legacy parameters to workflow format
|
|
let servers_list = if $hostname != null {
|
|
[$hostname]
|
|
} else if $serverpos != null {
|
|
let total = ($settings.data.servers | length)
|
|
if $serverpos <= $total and $serverpos > 0 {
|
|
let target_server = ($settings.data.servers | get ($serverpos - 1))
|
|
[$target_server.hostname]
|
|
} else {
|
|
[]
|
|
}
|
|
} else {
|
|
[]
|
|
}
|
|
|
|
# Extract infra and settings paths from settings record
|
|
let infra_path = ($settings | get infra? | default "")
|
|
let settings_path = ($settings | get src? | default "")
|
|
|
|
# Submit workflow to orchestrator
|
|
let workflow_result = (server_create_workflow $infra_path $settings_path $servers_list --check=$check --wait=$wait --orchestrator $orchestrator)
|
|
|
|
match ($workflow_result | get status) {
|
|
"completed" => { status: true, error: "" },
|
|
"submitted" => {
|
|
status: true,
|
|
error: "",
|
|
task_id: ($workflow_result | get task_id)
|
|
},
|
|
"error" | "failed" => {
|
|
status: false,
|
|
error: ($workflow_result | get message? | default "Workflow failed")
|
|
},
|
|
_ => { status: false, error: "Unknown workflow status" }
|
|
}
|
|
}
|
|
|
|
# Workflow status check command
|
|
export def "workflow status" [
|
|
task_id: string # Task ID to check
|
|
--orchestrator: string = "http://localhost:8080" # Orchestrator URL
|
|
]: nothing -> record {
|
|
# Use plugin for local orchestrator (~5ms vs ~50ms with HTTP)
|
|
if (use-local-plugin $orchestrator) {
|
|
let all_tasks = (orch tasks)
|
|
let task = ($all_tasks | where id == $task_id | first)
|
|
|
|
if ($task | is-empty) {
|
|
return { error: $"Task ($task_id) not found" }
|
|
}
|
|
|
|
return {
|
|
id: ($task | get id),
|
|
status: ($task | get status),
|
|
priority: ($task | get priority),
|
|
created_at: ($task | get created_at),
|
|
workflow_id: ($task | get workflow_id)
|
|
}
|
|
}
|
|
|
|
# Fall back to HTTP for remote orchestrators
|
|
let response = (http get $"($orchestrator)/tasks/($task_id)")
|
|
|
|
if not ($response | get success) {
|
|
return { error: ($response | get error) }
|
|
}
|
|
|
|
let task = ($response | get data)
|
|
{
|
|
id: ($task | get id),
|
|
name: ($task | get name),
|
|
status: ($task | get status),
|
|
created_at: ($task | get created_at),
|
|
started_at: ($task | get started_at? | default null),
|
|
completed_at: ($task | get completed_at? | default null),
|
|
output: ($task | get output? | default null),
|
|
error: ($task | get error? | default null)
|
|
}
|
|
}
|
|
|
|
# List all workflows
|
|
export def "workflow list" [
|
|
--orchestrator: string = "http://localhost:8080" # Orchestrator URL
|
|
]: nothing -> list<record> {
|
|
# Use plugin for local orchestrator (<10ms vs ~50ms with HTTP)
|
|
if (use-local-plugin $orchestrator) {
|
|
return (orch tasks)
|
|
}
|
|
|
|
# Fall back to HTTP for remote orchestrators
|
|
let response = (http get $"($orchestrator)/tasks")
|
|
|
|
if not ($response | get success) {
|
|
_print $"Error: (($response | get error))"
|
|
return []
|
|
}
|
|
|
|
($response | get data)
|
|
}
|
|
|
|
# Workflow health check
|
|
export def "workflow health" [
|
|
--orchestrator: string = "http://localhost:8080" # Orchestrator URL
|
|
]: nothing -> record {
|
|
# Use plugin for local orchestrator (<5ms vs ~50ms with HTTP)
|
|
if (use-local-plugin $orchestrator) {
|
|
let status = (orch status)
|
|
return {
|
|
status: (if $status.running { "healthy" } else { "stopped" }),
|
|
message: $"Orchestrator running: ($status.running)",
|
|
plugin_mode: true
|
|
}
|
|
}
|
|
|
|
# Fall back to HTTP for remote orchestrators
|
|
let response = (http get $"($orchestrator)/health")
|
|
if ($response | get success) {
|
|
{ status: "healthy", message: ($response | get data) }
|
|
} else {
|
|
{ status: "unhealthy", message: "Orchestrator returned error" }
|
|
}
|
|
} |