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