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
- Have the provider’s SDK or API available
- Know the provider’s authentication requirements
5-Minute Provider Addition
Step 1: Create Provider Directory
mkdir -p provisioning/extensions/providers/{provider_name}
mkdir -p provisioning/extensions/providers/{provider_name}/nulib/{provider_name}
Step 2: Copy Template and Customize
# 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:
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:
# 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:
# 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
# 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 KCL configuration:
# workspace/infra/example/servers.k
servers = [
{
hostname = "test-server"
provider = "your_provider_name"
zone = "your-region-1"
plan = "your-instance-type"
}
]
Provider Templates
Cloud Provider Template
For cloud providers (AWS, GCP, Azure, etc.):
# 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.):
# 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:
# 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
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
# 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
# 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:
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
# 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
# Check which functions are missing
nu -c "use provisioning/core/nulib/lib_provisioning/providers/interface.nu *; validate-provider-interface 'your_provider_name'"
Authentication Errors
# Check environment variables
env | grep PROVIDER
# Test API access manually
curl -H "Authorization: Bearer $PROVIDER_TOKEN" https://api.provider.com/test
Next Steps
- Documentation: Add provider-specific documentation to
docs/providers/ - Examples: Create example infrastructure using your provider
- Testing: Add integration tests for your provider
- Optimization: Implement caching and performance optimizations
- Features: Add provider-specific advanced features
Getting Help
- Check existing providers for implementation patterns
- Review the Provider Interface Documentation
- Test with the provider test suite:
./provisioning/tools/test-provider-agnostic.nu - Run migration checks:
./provisioning/tools/migrate-to-provider-agnostic.nu status