provisioning/core/nulib/main_provisioning/api.nu
2025-09-22 23:11:41 +01:00

318 lines
9.6 KiB
Plaintext

#!/usr/bin/env nu
# API Server management for Provisioning System
# Provides HTTP REST API endpoints for infrastructure management
use ../api/server.nu *
use ../api/routes.nu *
use ../lib_provisioning/utils/settings.nu *
export def "main api" [
command?: string # Command: start, stop, status, docs
--port (-p): int = 8080 # Port to run the API server on
--host: string = "localhost" # Host to bind the server to
--enable-websocket # Enable WebSocket support for real-time updates
--enable-cors # Enable CORS for cross-origin requests
--debug (-d) # Enable debug mode
--background (-b) # Run server in background
--config-file: string # Custom configuration file path
--ssl # Enable SSL/TLS (requires certificates)
--cert-file: string # SSL certificate file path
--key-file: string # SSL private key file path
--doc-format: string = "markdown" # Documentation format (markdown, json, yaml)
]: nothing -> nothing {
let cmd = $command | default "start"
match $cmd {
"start" => {
print $"🚀 Starting Provisioning API Server..."
# Validate configuration
let config_valid = validate_api_config --port $port --host $host
if not $config_valid.valid {
error make {
msg: $"Invalid configuration: ($config_valid.errors | str join ', ')"
help: "Please check your configuration and try again"
}
}
# Check dependencies
check_api_dependencies
# Start the server
if $background {
start_api_background --port $port --host $host --enable-websocket $enable_websocket --enable-cors $enable_cors --debug $debug
} else {
start_api_server --port $port --host $host --enable-websocket $enable_websocket --enable-cors $enable_cors --debug $debug
}
}
"stop" => {
print "🛑 Stopping API server..."
stop_api_server --port $port --host $host
}
"status" => {
print "🔍 Checking API server status..."
let health = check_api_health --port $port --host $host
print ($health | table)
}
"docs" => {
print "📚 Generating API documentation..."
generate_api_documentation --format $doc_format
}
"routes" => {
print "🗺️ Listing API routes..."
let routes = get_route_definitions
print ($routes | select method path description | table)
}
"validate" => {
print "✅ Validating API configuration..."
let validation = validate_routes
print ($validation | table)
}
"spec" => {
print "📋 Generating OpenAPI specification..."
let spec = generate_api_spec
print ($spec | to json)
}
_ => {
print_api_help
}
}
}
def validate_api_config [
--port: int
--host: string
]: nothing -> record {
mut errors = []
mut valid = true
# Validate port range
if $port < 1024 or $port > 65535 {
$errors = ($errors | append "Port must be between 1024 and 65535")
$valid = false
}
# Validate host format
if ($host | str contains " ") {
$errors = ($errors | append "Host cannot contain spaces")
$valid = false
}
# Check if port is available
if $valid {
let port_available = (do -i {
http listen $port --host $host --timeout 1 | ignore
false
} | default true)
if not $port_available {
$errors = ($errors | append $"Port ($port) is already in use")
$valid = false
}
}
{
valid: $valid
errors: $errors
port: $port
host: $host
}
}
def check_api_dependencies []: nothing -> nothing {
print "🔍 Checking dependencies..."
# Check Python availability
let python_available = (do -i { python3 --version } | complete | get exit_code) == 0
if not $python_available {
error make {
msg: "Python 3 is required for the API server"
help: "Please install Python 3 and ensure it's available in PATH"
}
}
# Check required environment variables
if ($env.PROVISIONING_PATH? | is-empty) {
print "⚠️ Warning: PROVISIONING_PATH not set, using current directory"
$env.PROVISIONING_PATH = (pwd)
}
print "✅ All dependencies satisfied"
}
def start_api_background [
--port: int
--host: string
--enable-websocket
--enable-cors
--debug
]: nothing -> nothing {
print $"🚀 Starting API server in background on ($host):($port)..."
# Create background process
let server_cmd = $"nu -c 'use ($env.PWD)/core/nulib/api/server.nu; start_api_server --port ($port) --host ($host)'"
if $enable_websocket {
$server_cmd = $server_cmd + " --enable-websocket"
}
if $enable_cors {
$server_cmd = $server_cmd + " --enable-cors"
}
if $debug {
$server_cmd = $server_cmd + " --debug"
}
# Save PID for later management
let pid_file = $"/tmp/provisioning-api-($port).pid"
bash -c $"($server_cmd) & echo $! > ($pid_file)"
sleep 2sec
let health = check_api_health --port $port --host $host
if $health.api_server {
print $"✅ API server started successfully in background"
print $"📍 PID file: ($pid_file)"
print $"🌐 URL: http://($host):($port)"
} else {
print "❌ Failed to start API server"
}
}
def stop_api_server [
--port: int
--host: string
]: nothing -> nothing {
let pid_file = $"/tmp/provisioning-api-($port).pid"
if ($pid_file | path exists) {
let pid = (open $pid_file | str trim)
print $"🛑 Stopping API server (PID: ($pid))..."
try {
kill $pid
rm -f $pid_file
print "✅ API server stopped successfully"
} catch {
print "⚠️ Failed to stop server, trying force kill..."
kill -9 $pid
rm -f $pid_file
print "✅ Server force stopped"
}
} else {
print "⚠️ No running API server found on port ($port)"
# Try to find and kill any Python processes running the API
let python_pids = (ps | where name =~ "python3" and command =~ "provisioning_api_server" | get pid)
if ($python_pids | length) > 0 {
print $"🔍 Found ($python_pids | length) related processes, stopping them..."
$python_pids | each { |pid| kill $pid }
print "✅ Related processes stopped"
}
}
}
def generate_api_documentation [
--format: string = "markdown"
]: nothing -> nothing {
let output_file = match $format {
"markdown" => "api_documentation.md"
"json" => "api_spec.json"
"yaml" => "api_spec.yaml"
_ => "api_documentation.md"
}
match $format {
"markdown" => {
let docs = generate_route_docs
$docs | save --force $output_file
print $"📚 Markdown documentation saved to: ($output_file)"
}
"json" => {
let spec = generate_api_spec
$spec | to json | save --force $output_file
print $"📋 OpenAPI JSON spec saved to: ($output_file)"
}
"yaml" => {
let spec = generate_api_spec
$spec | to yaml | save --force $output_file
print $"📋 OpenAPI YAML spec saved to: ($output_file)"
}
_ => {
print $"❌ Unsupported format: ($format)"
print "Supported formats: markdown, json, yaml"
}
}
}
def print_api_help []: nothing -> nothing {
print "
🚀 Provisioning API Server Management
USAGE:
provisioning api [COMMAND] [OPTIONS]
COMMANDS:
start Start the API server (default)
stop Stop the API server
status Check server status
docs Generate API documentation
routes List all available routes
validate Validate API configuration
spec Generate OpenAPI specification
OPTIONS:
-p, --port <PORT> Port to run server on [default: 8080]
--host <HOST> Host to bind to [default: localhost]
--enable-websocket Enable WebSocket support
--enable-cors Enable CORS headers
-d, --debug Enable debug mode
-b, --background Run in background
--doc-format <FORMAT> Documentation format [default: markdown]
EXAMPLES:
# Start server on default port
provisioning api start
# Start on custom port with debugging
provisioning api start --port 9090 --debug
# Start in background with WebSocket support
provisioning api start --background --enable-websocket
# Generate API documentation
provisioning api docs --doc-format json
# Check server status
provisioning api status
# Stop running server
provisioning api stop
ENDPOINTS:
GET /api/v1/health Health check
GET /api/v1/query Query infrastructure
POST /api/v1/query Complex queries
GET /api/v1/metrics System metrics
GET /api/v1/logs System logs
GET /api/v1/dashboard Dashboard data
GET /api/v1/servers List servers
POST /api/v1/servers Create server
GET /api/v1/ai/query AI-powered queries
For more information, visit: https://docs.provisioning.dev/api
"
}