# Provider Creation Tool # Quickly create a new provider with proper structure and templates use ../core/nulib/lib_provisioning/utils/logging.nu * use ../core/nulib/lib_provisioning/providers/registry.nu * # Create a new provider export def main [ provider_name: string # Name of the new provider (e.g., "digitalocean") --description: string = "" # Description of the provider --api-base: string = "" # Base API URL for the provider --auth-type: string = "token" # Authentication type (token, key, oauth) --template: string = "cloud" # Template type (cloud, container, baremetal) --dry-run # Show what would be created without executing ] { log-section "Creating new provider: $provider_name" "create-provider" # Validate provider name if ($provider_name | str contains " ") { log-error "Provider name cannot contain spaces" "validation" return } if ($provider_name | str length) < 2 { log-error "Provider name must be at least 2 characters" "validation" return } # Check if provider already exists let provider_path = $"../extensions/providers/($provider_name)" if ($provider_path | path exists) { log-error $"Provider ($provider_name) already exists at ($provider_path)" "validation" return } # Create directory structure let directories = [ $"../extensions/providers/($provider_name)" $"../extensions/providers/($provider_name)/nulib" $"../extensions/providers/($provider_name)/nulib/($provider_name)" ] if $dry_run { log-info "DRY RUN MODE - No files will be created" "create-provider" print "Directories to create:" for dir in $directories { print $" 📁 ($dir)" } } else { for dir in $directories { mkdir $dir log-success $"Created directory: ($dir)" "create-provider" } } # Generate provider metadata let metadata = generate_provider_metadata $provider_name $description $template # Generate provider adapter let adapter_content = generate_provider_adapter $provider_name $template $auth_type # Generate provider implementation let implementation_content = generate_provider_implementation $provider_name $template $api_base $auth_type # Create files let files = [ { path: $"../extensions/providers/($provider_name)/provider.nu" content: $adapter_content description: "Provider adapter implementing standard interface" } { path: $"../extensions/providers/($provider_name)/nulib/($provider_name)/servers.nu" content: $implementation_content description: "Provider-specific implementation functions" } { path: $"../extensions/providers/($provider_name)/README.md" content: (generate_provider_readme $provider_name $description $auth_type) description: "Provider documentation" } ] if $dry_run { print "\nFiles to create:" for file in $files { print $" 📄 ($file.path) - ($file.description)" } } else { for file in $files { $file.content | save $file.path log-success $"Created file: ($file.path)" "create-provider" } } # Generate usage examples let usage_examples = generate_usage_examples $provider_name if not $dry_run { $usage_examples | save $"../extensions/providers/($provider_name)/USAGE.md" log-success "Created usage examples" "create-provider" } # Show next steps log-section "Next Steps" "create-provider" let next_steps = [ $"1. Edit authentication in: ../extensions/providers/($provider_name)/nulib/($provider_name)/servers.nu" $"2. Implement provider-specific API calls" $"3. Test provider: nu -c \"use provisioning/core/nulib/lib_provisioning/providers/loader.nu *; load-provider '($provider_name)'\"" $"4. Validate interface: nu -c \"use provisioning/core/nulib/lib_provisioning/providers/interface.nu *; validate-provider-interface '($provider_name)'\"" $"5. Add provider to infrastructure configs" $"6. Run tests: ./provisioning/tools/test-provider-agnostic.nu" ] for step in $next_steps { print $step } if not $dry_run { log-success $"Provider ($provider_name) created successfully!" "create-provider" } else { log-info "Use --dry-run=false to create the provider" "create-provider" } } # Generate provider metadata def generate_provider_metadata [name: string, description: string, template: string]: nothing -> record { let desc = if ($description | is-empty) { match $template { "cloud" => $"($name | str title-case) cloud provider" "container" => $"($name | str title-case) container platform" "baremetal" => $"($name | str title-case) bare metal provider" _ => $"($name | str title-case) infrastructure provider" } } else { $description } let capabilities = match $template { "cloud" => { server_management: true network_management: true storage_management: true load_balancer: true dns_management: false cdn: false backup_service: true monitoring: false logging: false auto_scaling: true spot_instances: false containers: false serverless: false multi_region: true encryption_at_rest: true encryption_in_transit: true compliance_certifications: [] } "container" => { server_management: false network_management: true storage_management: true load_balancer: false dns_management: false cdn: false backup_service: false monitoring: false logging: false auto_scaling: true spot_instances: false containers: true serverless: false multi_region: false encryption_at_rest: false encryption_in_transit: true compliance_certifications: [] } "baremetal" => { server_management: true network_management: false storage_management: true load_balancer: false dns_management: false cdn: false backup_service: false monitoring: false logging: false auto_scaling: false spot_instances: false containers: true serverless: false multi_region: false encryption_at_rest: false encryption_in_transit: false compliance_certifications: [] } _ => { server_management: true network_management: false storage_management: false load_balancer: false dns_management: false cdn: false backup_service: false monitoring: false logging: false auto_scaling: false spot_instances: false containers: false serverless: false multi_region: false encryption_at_rest: false encryption_in_transit: false compliance_certifications: [] } } { name: $name description: $desc capabilities: $capabilities } } # Generate provider adapter content def generate_provider_adapter [name: string, template: string, auth_type: string]: nothing -> string { let name_title = ($name | str title-case) let metadata = generate_provider_metadata $name "" $template $"# ($name_title) Provider Adapter # Implements the standard provider interface for ($name_title) use nulib/($name)/servers.nu * # Provider metadata export def get-provider-metadata []: nothing -> record { { name: \"($name)\" version: \"1.0.0\" description: \"($metadata.description)\" capabilities: ($metadata.capabilities | to nuon) } } # Server query operations export def query_servers [ find?: string cols?: string ]: nothing -> list { let str_find = if \\$find != null { \\$find } else { \"\" } let str_cols = if \\$cols != null { \\$cols } else { \"\" } ($name)_query_servers \\$str_find \\$str_cols } # Server information operations export def server_info [ server: record check: bool find?: string cols?: string ]: nothing -> record { ($name)_server_info \\$server \\$check } # Server existence and status operations export def server_exists [ server: record error_exit: bool ]: nothing -> bool { ($name)_server_exists \\$server \\$error_exit } export def server_is_running [ server: record error_exit: bool ]: nothing -> bool { ($name)_server_is_running \\$server \\$error_exit } # Server lifecycle operations export def check_server_requirements [ settings: record server: record check: bool ]: nothing -> bool { ($name)_check_server_requirements \\$settings \\$server \\$check } export def create_server [ settings: record server: record check: bool wait: bool ]: nothing -> bool { ($name)_create_server \\$settings \\$server \\$check \\$wait } export def delete_server [ settings: record server: record keep_storage: bool error_exit: bool ]: nothing -> bool { ($name)_delete_server \\$settings \\$server \\$keep_storage \\$error_exit } export def delete_server_storage [ settings: record server: record error_exit: bool ]: nothing -> bool { ($name)_delete_server_storage \\$settings \\$server \\$error_exit } export def post_create_server [ settings: record server: record check: bool ]: nothing -> bool { ($name)_post_create_server \\$settings \\$server \\$check } export def modify_server [ settings: record server: record new_values: list error_exit: bool ]: nothing -> bool { ($name)_modify_server \\$settings \\$server \\$new_values \\$error_exit } # Server state management export def server_state [ server: record new_state: string error_exit: bool wait: bool settings: record ]: nothing -> bool { ($name)_server_state \\$server \\$new_state \\$error_exit \\$wait \\$settings } # Network operations export def get_ip [ settings: record server: record ip_type: string error_exit: bool ]: nothing -> string { let use_type = match \\$ip_type { \"\\$network_public_ip\" => \"public\" \"\\$network_private_ip\" => \"private\" _ => \\$ip_type } let result = (($name)_get_ip \\$settings \\$server \\$use_type \\$error_exit) \\$result | str trim } export def servers_ips [ settings: record data: list prov?: string serverpos?: int ]: nothing -> list { ($name)_servers_ips \\$settings \\$data \\$prov \\$serverpos } # Infrastructure operations export def load_infra_servers_info [ settings: record server: record error_exit: bool ]: nothing -> record { ($name)_load_infra_servers_info \\$settings \\$server \\$error_exit } export def load_infra_storages_info [ settings: record server: record error_exit: bool ]: nothing -> record { ($name)_load_infra_storages_info \\$settings \\$server \\$error_exit } export def get_infra_storage [ server: record settings: record cloud_data: record error_exit: bool ]: nothing -> list { ($name)_get_infra_storage \\$server \\$settings \\$cloud_data \\$error_exit } export def get_infra_item [ server: record settings: record cloud_data: record error_exit: bool ]: nothing -> record { ($name)_get_infra_item \\$server \\$settings \\$cloud_data \\$error_exit } export def get_infra_price [ server: record data: record key: string error_exit: bool price_col?: string ]: nothing -> float { ($name)_get_infra_price \\$server \\$data \\$key \\$error_exit \\$price_col } # Cache operations export def start_cache_info [ settings: record server: record ]: nothing -> nothing { ($name)_start_cache_info \\$settings \\$server } export def create_cache [ settings: record server: record error_exit: bool ]: nothing -> nothing { ($name)_create_cache \\$settings \\$server \\$error_exit } export def read_cache [ settings: record server: record error_exit: bool ]: nothing -> nothing { ($name)_read_cache \\$settings \\$server \\$error_exit } export def clean_cache [ settings: record server: record error_exit: bool ]: nothing -> nothing { ($name)_clean_cache \\$settings \\$server \\$error_exit } export def ip_from_cache [ settings: record server: record error_exit: bool ]: nothing -> string { ($name)_ip_from_cache \\$settings \\$server \\$error_exit } # Provider metadata operations export def on_prov_server [ server: record ]: nothing -> string { ($name)_on_prov_server \\$server } # Provider validation export def validate_provider []: nothing -> record { { provider: \"($name)\" valid: true interface_version: \"1.0.0\" capabilities: (get-provider-metadata).capabilities last_validated: (date now) } } " } # Generate provider implementation content def generate_provider_implementation [name: string, template: string, api_base: string, auth_type: string]: nothing -> string { let name_title = ($name | str title-case) let auth_var = match $auth_type { "token" => $"($name | str upcase)_TOKEN" "key" => $"($name | str upcase)_API_KEY" "oauth" => $"($name | str upcase)_CLIENT_ID" _ => $"($name | str upcase)_TOKEN" } let api_url = if ($api_base | is-empty) { $"https://api.($name).com" } else { $api_base } let implementation = match $template { "cloud" => generate_cloud_implementation $name $auth_var $api_url "container" => generate_container_implementation $name "baremetal" => generate_baremetal_implementation $name _ => generate_generic_implementation $name $auth_var $api_url } $"# ($name_title) Provider Implementation # Provider-specific functions for ($name_title) use ../../core/nulib/lib_provisioning/utils/logging.nu * # Authentication check def check_auth []: nothing -> bool { if (\\$env | get -o ($auth_var)) == null { log-error \"($auth_var) environment variable required\" \"auth\" return false } true } ($implementation) " } # Generate cloud provider implementation def generate_cloud_implementation [name: string, auth_var: string, api_url: string]: nothing -> string { $"# Cloud provider implementation for ($name) export def ($name)_query_servers [find?: string, cols?: string]: nothing -> list { if not (check_auth) { return [] } let auth_header = { Authorization: \\$\"Bearer (\\$env.($auth_var))\" } try { let servers = (http get \\$\"($api_url)/servers\" --headers \\$auth_header) # Filter results if find parameter provided let filtered = if (\\$find != null) and (\\$find != \"\") { \\$servers | where {|server| \\$server.name =~ \\$find} } else { \\$servers } # Select columns if specified if (\\$cols != null) and (\\$cols != \"\") { let field_list = (\\$cols | split row \",\") \\$filtered | select ...(\\$field_list) } else { \\$filtered | select name status region instance_type public_ip } } catch {|err| log-error \\$\"Failed to query servers: (\\$err.msg)\" \"($name)\" [] } } export def ($name)_create_server [settings: record, server: record, check: bool, wait: bool]: nothing -> bool { if not (check_auth) { return false } let payload = { name: \\$server.hostname region: (\\$server.zone? | default \"us-east-1\") instance_type: (\\$server.plan? | default \"t3.micro\") image: (\\$server.image? | default \"ubuntu-20.04\") } if \\$check { log-info \\$\"Would create ($name) server: (\\$payload)\" \"($name)\" return true } try { let auth_header = { Authorization: \\$\"Bearer (\\$env.($auth_var))\" } let result = (http post \\$\"($api_url)/servers\" --headers \\$auth_header --content-type application/json \\$payload) if \\$wait { # Poll for server to be ready mut attempts = 0 while \\$attempts < 60 { # 5 minutes max let status = (($name)_server_exists \\$server false) if \\$status { log-success \\$\"Server (\\$server.hostname) is ready\" \"($name)\" break } sleep 5sec \\$attempts += 1 } } log-success \\$\"Created server: (\\$server.hostname)\" \"($name)\" true } catch {|err| log-error \\$\"Failed to create server: (\\$err.msg)\" \"($name)\" false } } export def ($name)_server_exists [server: record, error_exit: bool]: nothing -> bool { if not (check_auth) { return false } try { let auth_header = { Authorization: \\$\"Bearer (\\$env.($auth_var))\" } let servers = (http get \\$\"($api_url)/servers\" --headers \\$auth_header) let found = (\\$servers | where name == \\$server.hostname) (\\$found | length) > 0 } catch {|err| if \\$error_exit { log-error \\$\"Error checking server existence: (\\$err.msg)\" \"($name)\" exit 1 } false } } export def ($name)_get_ip [settings: record, server: record, ip_type: string, error_exit: bool]: nothing -> string { if not (check_auth) { return \"\" } try { let auth_header = { Authorization: \\$\"Bearer (\\$env.($auth_var))\" } let servers = (http get \\$\"($api_url)/servers\" --headers \\$auth_header) let found = (\\$servers | where name == \\$server.hostname | get 0) match \\$ip_type { \"public\" => (\\$found.public_ip? | default \"\") \"private\" => (\\$found.private_ip? | default \"\") _ => (\\$found.public_ip? | default \"\") } } catch {|err| if \\$error_exit { log-error \\$\"Error getting IP: (\\$err.msg)\" \"($name)\" exit 1 } \"\" } } export def ($name)_delete_server [settings: record, server: record, keep_storage: bool, error_exit: bool]: nothing -> bool { if not (check_auth) { return false } try { let auth_header = { Authorization: \\$\"Bearer (\\$env.($auth_var))\" } http delete \\$\"($api_url)/servers/(\\$server.hostname)\" --headers \\$auth_header log-success \\$\"Deleted server: (\\$server.hostname)\" \"($name)\" true } catch {|err| if \\$error_exit { log-error \\$\"Error deleting server: (\\$err.msg)\" \"($name)\" exit 1 } false } } # Implement other required functions... export def ($name)_server_info [server: record, check: bool]: nothing -> record { { hostname: \\$server.hostname, provider: \"($name)\", status: \"unknown\" } } export def ($name)_server_is_running [server: record, error_exit: bool]: nothing -> bool { # Implementation depends on your provider's API true } export def ($name)_check_server_requirements [settings: record, server: record, check: bool]: nothing -> bool { true } export def ($name)_delete_server_storage [settings: record, server: record, error_exit: bool]: nothing -> bool { true } export def ($name)_post_create_server [settings: record, server: record, check: bool]: nothing -> bool { true } export def ($name)_modify_server [settings: record, server: record, new_values: list, error_exit: bool]: nothing -> bool { true } export def ($name)_server_state [server: record, new_state: string, error_exit: bool, wait: bool, settings: record]: nothing -> bool { true } export def ($name)_servers_ips [settings: record, data: list, prov?: string, serverpos?: int]: nothing -> list { [] } export def ($name)_load_infra_servers_info [settings: record, server: record, error_exit: bool]: nothing -> record { { provider: \"($name)\", server: \\$server.hostname } } export def ($name)_load_infra_storages_info [settings: record, server: record, error_exit: bool]: nothing -> record { { provider: \"($name)\", storage: \"managed\" } } export def ($name)_get_infra_storage [server: record, settings: record, cloud_data: record, error_exit: bool]: nothing -> list { [] } export def ($name)_get_infra_item [server: record, settings: record, cloud_data: record, error_exit: bool]: nothing -> record { { provider: \"($name)\", hostname: \\$server.hostname } } export def ($name)_get_infra_price [server: record, data: record, key: string, error_exit: bool, price_col?: string]: nothing -> float { 0.0 } export def ($name)_start_cache_info [settings: record, server: record]: nothing -> nothing { # No-op } export def ($name)_create_cache [settings: record, server: record, error_exit: bool]: nothing -> nothing { # No-op } export def ($name)_read_cache [settings: record, server: record, error_exit: bool]: nothing -> nothing { # No-op } export def ($name)_clean_cache [settings: record, server: record, error_exit: bool]: nothing -> nothing { # No-op } export def ($name)_ip_from_cache [settings: record, server: record, error_exit: bool]: nothing -> string { \"\" } export def ($name)_on_prov_server [server: record]: nothing -> string { \\$\"Using ($name) provider for (\\$server.hostname)\" } " } # Generate container provider implementation def generate_container_implementation [name: string]: nothing -> string { $"# Container provider implementation for ($name) export def ($name)_query_servers [find?: string, cols?: string]: nothing -> list { try { let containers = (docker ps --format json | from json) let filtered = if (\\$find != null) and (\\$find != \"\") { \\$containers | where {|container| \\$container.Names =~ \\$find} } else { \\$containers } if (\\$cols != null) and (\\$cols != \"\") { let field_list = (\\$cols | split row \",\") \\$filtered | select ...(\\$field_list) } else { \\$filtered | select Names State Status Image } } catch {|err| log-error \\$\"Failed to query containers: (\\$err.msg)\" \"($name)\" [] } } export def ($name)_create_server [settings: record, server: record, check: bool, wait: bool]: nothing -> bool { let image = (\\$server.image? | default \"ubuntu:20.04\") let command = [\"docker\", \"run\", \"-d\", \"--name\", \\$server.hostname, \\$image] if \\$check { log-info \\$\"Would create container: (\\$command | str join ' ')\" \"($name)\" return true } try { let result = (run-external \"docker\" \"run\" \"-d\" \"--name\" \\$server.hostname \\$image) log-success \\$\"Created container: (\\$server.hostname)\" \"($name)\" true } catch {|err| log-error \\$\"Failed to create container: (\\$err.msg)\" \"($name)\" false } } # Implement other required functions for container platform... " } # Generate baremetal provider implementation def generate_baremetal_implementation [name: string]: nothing -> string { $"# Bare metal provider implementation for ($name) export def ($name)_query_servers [find?: string, cols?: string]: nothing -> list { try { # Read from inventory file or configuration let inventory_file = \\$\"inventory.(\\$name).yaml\" if not (\\$inventory_file | path exists) { log-warning \\$\"Inventory file not found: (\\$inventory_file)\" \"($name)\" return [] } let inventory = (open \\$inventory_file | from yaml) let servers = \\$inventory.servers let filtered = if (\\$find != null) and (\\$find != \"\") { \\$servers | where {|server| \\$server.hostname =~ \\$find} } else { \\$servers } if (\\$cols != null) and (\\$cols != \"\") { let field_list = (\\$cols | split row \",\") \\$filtered | select ...(\\$field_list) } else { \\$filtered | select hostname ip_address status } } catch {|err| log-error \\$\"Failed to query servers: (\\$err.msg)\" \"($name)\" [] } } export def ($name)_create_server [settings: record, server: record, check: bool, wait: bool]: nothing -> bool { # For bare metal, \"creation\" means ensuring server is accessible if \\$check { log-info \\$\"Would validate bare metal server: (\\$server.hostname)\" \"($name)\" return true } try { # Test SSH connectivity let test_result = (ssh -o ConnectTimeout=5 \\$server.hostname \"echo 'connection test'\") if (\\$test_result | str contains \"connection test\") { log-success \\$\"Bare metal server (\\$server.hostname) is accessible\" \"($name)\" true } else { log-error \\$\"Cannot connect to bare metal server (\\$server.hostname)\" \"($name)\" false } } catch {|err| log-error \\$\"SSH connection failed: (\\$err.msg)\" \"($name)\" false } } # Implement other required functions for bare metal... " } # Generate generic provider implementation def generate_generic_implementation [name: string, auth_var: string, api_url: string]: nothing -> string { $"# Generic provider implementation for ($name) export def ($name)_query_servers [find?: string, cols?: string]: nothing -> list { # TODO: Implement your provider's server listing logic log-warning \"($name)_query_servers not yet implemented\" \"($name)\" [] } export def ($name)_create_server [settings: record, server: record, check: bool, wait: bool]: nothing -> bool { # TODO: Implement your provider's server creation logic if \\$check { log-info \\$\"Would create server: (\\$server.hostname)\" \"($name)\" return true } log-warning \"($name)_create_server not yet implemented\" \"($name)\" false } # TODO: Implement all other required functions... " } # Generate provider README def generate_provider_readme [name: string, description: string, auth_type: string]: nothing -> string { let name_title = ($name | str title-case) let auth_var = match $auth_type { "token" => $"($name | str upcase)_TOKEN" "key" => $"($name | str upcase)_API_KEY" "oauth" => $"($name | str upcase)_CLIENT_ID" _ => $"($name | str upcase)_TOKEN" } $"# ($name_title) Provider ($description) ## Authentication Set the following environment variable: ```bash export ($auth_var)=\"your-($auth_type)-here\" ``` ## Configuration Add servers using the ($name) provider in your KCL configuration: ```kcl servers = [ { hostname = \"my-server\" provider = \"($name)\" zone = \"region-1\" plan = \"small\" image = \"ubuntu-20.04\" } ] ``` ## Features - ✅ Server management - ✅ Basic operations - ⚠️ Advanced features (in development) ## Usage ```bash # Query servers nu -c \"use provisioning/extensions/providers/($name)/provider.nu *; query_servers\" # Test provider ./provisioning/tools/test-provider-agnostic.nu ``` ## Development This provider was generated using the provider creation tool. See `USAGE.md` for implementation examples. ## Status 🚧 **Work in Progress** - This provider needs implementation of core functions. ## Support - Check the [Provider Development Guide](../../../docs/development/QUICK_PROVIDER_GUIDE.md) - Review existing providers for implementation patterns - Run tests with: `./provisioning/tools/test-provider-agnostic.nu` " } # Generate usage examples def generate_usage_examples [name: string]: nothing -> string { let name_title = ($name | str title-case) $"# ($name_title) Provider Usage Examples ## Basic Server Operations ### Query Servers ```bash # List all servers nu -c \"use provisioning/extensions/providers/($name)/provider.nu *; query_servers\" # Find servers by name nu -c \"use provisioning/extensions/providers/($name)/provider.nu *; query_servers 'web'\" # Select specific columns nu -c \"use provisioning/extensions/providers/($name)/provider.nu *; query_servers '' 'name,status,region'\" ``` ### Server Information ```bash # Get detailed server info nu -c \"use provisioning/extensions/providers/($name)/provider.nu *; server_info {hostname: 'my-server'} false\" # Check if server exists nu -c \"use provisioning/extensions/providers/($name)/provider.nu *; server_exists {hostname: 'my-server'} false\" ``` ## Infrastructure Configuration ### KCL Configuration Example ```kcl # workspace/infra/example/servers.k servers = [ { hostname = \"web-01\" provider = \"($name)\" zone = \"us-east-1\" plan = \"t3.micro\" image = \"ubuntu-20.04\" network_public_ip = \"auto\" network_private_ip = \"auto\" } { hostname = \"db-01\" provider = \"($name)\" zone = \"us-east-1\" plan = \"t3.small\" image = \"ubuntu-20.04\" network_public_ip = \"auto\" network_private_ip = \"auto\" } ] ``` ### Multi-Provider Configuration ```kcl # Mix ($name) with other providers servers = [ { hostname = \"compute-01\" provider = \"($name)\" zone = \"us-east-1\" plan = \"large\" } { hostname = \"backup-01\" provider = \"upcloud\" zone = \"us-nyc1\" plan = \"1xCPU-2GB\" } ] ``` ## Provider Testing ### Test Provider Loading ```bash # Test provider registration nu -c \"use provisioning/core/nulib/lib_provisioning/providers/registry.nu *; init-provider-registry; is-provider-available '($name)'\" # Test provider loading nu -c \"use provisioning/core/nulib/lib_provisioning/providers/loader.nu *; load-provider '($name)'\" # Validate interface compliance nu -c \"use provisioning/core/nulib/lib_provisioning/providers/interface.nu *; validate-provider-interface '($name)'\" ``` ### Run Full Test Suite ```bash # Run all provider tests ./provisioning/tools/test-provider-agnostic.nu run-all-tests # Test specific provider ./provisioning/tools/test-provider-agnostic.nu test-provider-loading ``` ## Integration with Provisioning System ### Using with Core CLI ```bash # Create servers using the ($name) provider ./provisioning/core/cli/provisioning server create --infra example --check # List servers from ($name) provider ./provisioning/core/cli/provisioning server list --provider ($name) # Get server info ./provisioning/core/cli/provisioning server info web-01 ``` ### Provider-Agnostic Operations ```bash # Query servers across all providers nu -c \"use provisioning/extensions/providers/prov_lib/middleware_provider_agnostic.nu *; mw_query_servers {data: {servers: []}}\" # Get provider status nu -c \"use provisioning/extensions/providers/prov_lib/middleware_provider_agnostic.nu *; mw_provider_status\" # Multi-provider deployment nu -c \"use provisioning/extensions/providers/prov_lib/middleware_provider_agnostic.nu *; mw_deploy_multi_provider_infra \\$settings \\$plan\" ``` ## Debugging ### Check Provider Status ```bash # List all providers nu -c \"use provisioning/core/nulib/lib_provisioning/providers/registry.nu *; list-providers\" # Get provider capabilities nu -c \"use provisioning/core/nulib/lib_provisioning/providers/registry.nu *; get-provider-capabilities-for '($name)'\" # Check provider health nu -c \"use provisioning/core/nulib/lib_provisioning/providers/loader.nu *; check-provider-health '($name)'\" ``` ### Common Issues 1. **Provider not found** ```bash # Refresh provider registry nu -c \"use provisioning/core/nulib/lib_provisioning/providers/registry.nu *; init-provider-registry\" ``` 2. **Authentication failed** ```bash # Check environment variables env | grep ($name | str upcase) ``` 3. **Interface validation failed** ```bash # Check missing functions nu -c \"use provisioning/core/nulib/lib_provisioning/providers/interface.nu *; validate-provider-interface '($name)'\" ``` ## Advanced Usage ### Custom Provider Functions ```bash # Call provider-specific functions directly nu -c \"use provisioning/extensions/providers/($name)/nulib/($name)/servers.nu *; ($name)_query_servers\" ``` ### Provider Capabilities ```bash # Check what the provider supports nu -c \"use provisioning/extensions/providers/($name)/provider.nu *; get-provider-metadata\" ``` ## Next Steps 1. Implement missing provider functions in `nulib/($name)/servers.nu` 2. Add authentication and API integration 3. Test with real infrastructure 4. Add provider-specific features and optimizations 5. Contribute improvements back to the project " } # Show help export def help []: nothing -> nothing { let help_text = $" Provider Creation Tool USAGE: ./provisioning/tools/create-provider.nu [options] ARGUMENTS: provider_name Name of the new provider (e.g., 'digitalocean', 'linode') OPTIONS: --description Description of the provider (optional) --api-base Base API URL for the provider (optional) --auth-type Authentication type: token, key, oauth (default: token) --template Template type: cloud, container, baremetal (default: cloud) --dry-run Show what would be created without executing EXAMPLES: # Create a cloud provider with token auth ./provisioning/tools/create-provider.nu digitalocean --description \"DigitalOcean cloud provider\" # Create a container platform provider ./provisioning/tools/create-provider.nu podman --template container # Create a bare metal provider ./provisioning/tools/create-provider.nu datacenter --template baremetal # Preview what would be created ./provisioning/tools/create-provider.nu newprovider --dry-run TEMPLATES: cloud - Full cloud provider with API integration (AWS, GCP, Azure style) container - Container platform provider (Docker, Podman style) baremetal - Bare metal or existing server provider (Local, SSH style) NEXT STEPS: 1. Run the tool to create provider structure 2. Implement authentication in the generated files 3. Add provider-specific API calls 4. Test with: ./provisioning/tools/test-provider-agnostic.nu 5. Validate interface compliance 6. Add to infrastructure configurations For more information, see docs/development/QUICK_PROVIDER_GUIDE.md " print $help_text }