# Quick Developer Guide: Adding New Providers This guide shows how to quickly add a new provider to the provider-agnostic infrastructure system. ## Prerequisites - Understand the [Provider-Agnostic Architecture](PROVIDER_AGNOSTIC_ARCHITECTURE.md) - Have the provider's SDK or API available - Know the provider's authentication requirements ## 5-Minute Provider Addition ### Step 1: Create Provider Directory ```bash mkdir -p provisioning/extensions/providers/{provider_name} mkdir -p provisioning/extensions/providers/{provider_name}/nulib/{provider_name} ``` ### Step 2: Copy Template and Customize ```bash # Copy the local provider as a template cp provisioning/extensions/providers/local/provider.nu \ provisioning/extensions/providers/{provider_name}/provider.nu ``` ### Step 3: Update Provider Metadata Edit `provisioning/extensions/providers/{provider_name}/provider.nu`: ```nushell export def get-provider-metadata []: nothing -> record { { name: "your_provider_name" version: "1.0.0" description: "Your Provider Description" capabilities: { server_management: true network_management: true # Set based on provider features auto_scaling: false # Set based on provider features multi_region: true # Set based on provider features serverless: false # Set based on provider features # ... customize other capabilities } } } ``` ### Step 4: Implement Core Functions The provider interface requires these essential functions: ```nushell # Required: Server operations export def query_servers [find?: string, cols?: string]: nothing -> list { # Call your provider's server listing API your_provider_query_servers $find $cols } export def create_server [settings: record, server: record, check: bool, wait: bool]: nothing -> bool { # Call your provider's server creation API your_provider_create_server $settings $server $check $wait } export def server_exists [server: record, error_exit: bool]: nothing -> bool { # Check if server exists in your provider your_provider_server_exists $server $error_exit } export def get_ip [settings: record, server: record, ip_type: string, error_exit: bool]: nothing -> string { # Get server IP from your provider your_provider_get_ip $settings $server $ip_type $error_exit } # Required: Infrastructure operations export def delete_server [settings: record, server: record, keep_storage: bool, error_exit: bool]: nothing -> bool { your_provider_delete_server $settings $server $keep_storage $error_exit } export def server_state [server: record, new_state: string, error_exit: bool, wait: bool, settings: record]: nothing -> bool { your_provider_server_state $server $new_state $error_exit $wait $settings } ``` ### Step 5: Create Provider-Specific Functions Create `provisioning/extensions/providers/{provider_name}/nulib/{provider_name}/servers.nu`: ```nushell # Example: DigitalOcean provider functions export def digitalocean_query_servers [find?: string, cols?: string]: nothing -> list { # Use DigitalOcean API to list droplets let droplets = (http get "https://api.digitalocean.com/v2/droplets" --headers { Authorization: $"Bearer ($env.DO_TOKEN)" }) $droplets.droplets | select name status memory disk region.name networks.v4 } export def digitalocean_create_server [settings: record, server: record, check: bool, wait: bool]: nothing -> bool { # Use DigitalOcean API to create droplet let payload = { name: $server.hostname region: $server.zone size: $server.plan image: ($server.image? | default "ubuntu-20-04-x64") } if $check { print $"Would create DigitalOcean droplet: ($payload)" return true } let result = (http post "https://api.digitalocean.com/v2/droplets" --headers { Authorization: $"Bearer ($env.DO_TOKEN)" } --content-type application/json $payload) $result.droplet.id != null } ``` ### Step 6: Test Your Provider ```bash # Test provider discovery nu -c "use provisioning/core/nulib/lib_provisioning/providers/registry.nu *; init-provider-registry; list-providers" # Test provider loading nu -c "use provisioning/core/nulib/lib_provisioning/providers/loader.nu *; load-provider 'your_provider_name'" # Test provider functions nu -c "use provisioning/extensions/providers/your_provider_name/provider.nu *; query_servers" ``` ### Step 7: Add Provider to Infrastructure Add to your Nickel configuration: ```nickel # workspace/infra/example/servers.ncl let servers = [ { hostname = "test-server", provider = "your_provider_name", zone = "your-region-1", plan = "your-instance-type", } ] in servers ``` ## Provider Templates ### Cloud Provider Template For cloud providers (AWS, GCP, Azure, etc.): ```nushell # Use HTTP calls to cloud APIs export def cloud_query_servers [find?: string, cols?: string]: nothing -> list { let auth_header = { Authorization: $"Bearer ($env.PROVIDER_TOKEN)" } let servers = (http get $"($env.PROVIDER_API_URL)/servers" --headers $auth_header) $servers | select name status region instance_type public_ip } ``` ### Container Platform Template For container platforms (Docker, Podman, etc.): ```nushell # Use CLI commands for container platforms export def container_query_servers [find?: string, cols?: string]: nothing -> list { let containers = (docker ps --format json | from json) $containers | select Names State Status Image } ``` ### Bare Metal Provider Template For bare metal or existing servers: ```nushell # Use SSH or local commands export def baremetal_query_servers [find?: string, cols?: string]: nothing -> list { # Read from inventory file or ping servers let inventory = (open inventory.yaml | from yaml) $inventory.servers | select hostname ip_address status } ``` ## Best Practices ### 1. Error Handling ```nushell export def provider_operation []: nothing -> any { try { # Your provider operation provider_api_call } catch {|err| log-error $"Provider operation failed: ($err.msg)" "provider" if $error_exit { exit 1 } null } } ``` ### 2. Authentication ```nushell # Check for required environment variables def check_auth []: nothing -> bool { if ($env | get -o PROVIDER_TOKEN) == null { log-error "PROVIDER_TOKEN environment variable required" "auth" return false } true } ``` ### 3. Rate Limiting ```nushell # Add delays for API rate limits def api_call_with_retry [url: string]: nothing -> any { mut attempts = 0 mut max_attempts = 3 while $attempts < $max_attempts { try { return (http get $url) } catch { $attempts += 1 sleep 1sec } } error make { msg: "API call failed after retries" } } ``` ### 4. Provider Capabilities Set capabilities accurately: ```nushell capabilities: { server_management: true # Can create/delete servers network_management: true # Can manage networks/VPCs storage_management: true # Can manage block storage load_balancer: false # No load balancer support dns_management: false # No DNS support auto_scaling: true # Supports auto-scaling spot_instances: false # No spot instance support multi_region: true # Supports multiple regions containers: false # No container support serverless: false # No serverless support encryption_at_rest: true # Supports encryption compliance_certifications: ["SOC2"] # Available certifications } ``` ## Testing Checklist - [ ] Provider discovered by registry - [ ] Provider loads without errors - [ ] All required interface functions implemented - [ ] Provider metadata correct - [ ] Authentication working - [ ] Can query existing resources - [ ] Can create new resources (in test mode) - [ ] Error handling working - [ ] Compatible with existing infrastructure configs ## Common Issues ### Provider Not Found ```bash # Check provider directory structure ls -la provisioning/extensions/providers/your_provider_name/ # Ensure provider.nu exists and has get-provider-metadata function grep "get-provider-metadata" provisioning/extensions/providers/your_provider_name/provider.nu ``` ### Interface Validation Failed ```bash # Check which functions are missing nu -c "use provisioning/core/nulib/lib_provisioning/providers/interface.nu *; validate-provider-interface 'your_provider_name'" ``` ### Authentication Errors ```bash # Check environment variables env | grep PROVIDER # Test API access manually curl -H "Authorization: Bearer $PROVIDER_TOKEN" https://api.provider.com/test ``` ## Next Steps 1. **Documentation**: Add provider-specific documentation to `docs/providers/` 2. **Examples**: Create example infrastructure using your provider 3. **Testing**: Add integration tests for your provider 4. **Optimization**: Implement caching and performance optimizations 5. **Features**: Add provider-specific advanced features ## Getting Help - Check existing providers for implementation patterns - Review the [Provider Interface Documentation](PROVIDER_AGNOSTIC_ARCHITECTURE.md#provider-interface) - Test with the provider test suite: `./provisioning/tools/test-provider-agnostic.nu` - Run migration checks: `./provisioning/tools/migrate-to-provider-agnostic.nu status`