# Custom Extensions

Create custom providers, task services, and clusters to extend the Provisioning platform for your specific infrastructure needs.

## Overview

Extensions allow you to:
- Add support for new cloud providers
- Create custom task services for specialized software
- Define cluster templates for common deployment patterns
- Integrate with proprietary infrastructure

## Extension Types

### Providers

Cloud or infrastructure backend integrations.

**Use Cases**: Custom private cloud, bare metal provisioning, proprietary APIs

### Task Services

Installable software components.

**Use Cases**: Internal applications, specialized databases, custom monitoring

### Clusters

Coordinated service groups.

**Use Cases**: Standard deployment patterns, application stacks, reference architectures

## Creating a Custom Provider

### Directory Structure

```plaintext
provisioning/extensions/providers/my-provider/
├── provider.ncl          # Provider schema
├── resources/
│   ├── server.nu        # Server operations
│   ├── network.nu       # Network operations
│   └── storage.nu       # Storage operations
└── README.md
```

### Provider Schema (provider.ncl)

```nickel
{
  name = "my-provider",
  description = "Custom infrastructure provider",

  config_schema = {
    api_endpoint | String,
    api_key | String,
    region | String | default = "default",
    timeout_seconds | Number | default = 300,
  },

  capabilities = {
    servers = true,
    networks = true,
    storage = true,
    load_balancers = false,
  }
}
```

### Server Operations (resources/server.nu)

```nushell
# Create server
export def "server create" [
  name: string
  plan: string
  --zone: string = "default"
] {
  let config = $env.PROVIDER_CONFIG | from json

  # Call provider API
  http post $"($config.api_endpoint)/servers" {
    name: $name,
    plan: $plan,
    zone: $zone
  } | from json
}

# Delete server
export def "server delete" [name: string] {
  let config = $env.PROVIDER_CONFIG | from json
  http delete $"($config.api_endpoint)/servers/($name)"
}

# List servers
export def "server list" [] {
  let config = $env.PROVIDER_CONFIG | from json
  http get $"($config.api_endpoint)/servers" | from json
}
```

## Creating a Custom Task Service

### Directory Structure

```plaintext
provisioning/extensions/taskservs/my-service/
├── service.ncl           # Service schema
├── install.nu            # Installation script
├── configure.nu          # Configuration script
├── health-check.nu       # Health validation
└── README.md
```

### Service Schema (service.ncl)

```nickel
{
  name = "my-service",
  version = "1.0.0",
  description = "Custom service deployment",

  dependencies = ["kubernetes"],

  config_schema = {
    replicas | Number | default = 3,
    port | Number | default = 8080,
    storage_size_gb | Number | default = 10,
    image | String,
  }
}
```

### Installation Script (install.nu)

```nushell
export def "taskserv install" [config: record] {
  print $"Installing ($config.name)..."

  # Create namespace
  kubectl create namespace $config.name

  # Deploy application
  kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ($config.name)
  namespace: ($config.name)
spec:
  replicas: ($config.replicas)
  template:
    spec:
      containers:
      - name: app
        image: ($config.image)
        ports:
        - containerPort: ($config.port)
EOF

  {status: "installed"}
}
```

### Health Check (health-check.nu)

```nushell
export def "taskserv health" [name: string] {
  let pods = (kubectl get pods -n $name -o json | from json)

  let ready = ($pods.items | all | { | p $p.status.phase == "Running"})

  if $ready {
    {status: "healthy", ready_pods: ($pods.items | length)}
  } else {
    {status: "unhealthy", reason: "pods not running"}
  }
}
```

## Creating a Custom Cluster

### Directory Structure

```plaintext
provisioning/extensions/clusters/my-cluster/
├── cluster.ncl           # Cluster definition
├── deploy.nu             # Deployment script
└── README.md
```

### Cluster Schema (cluster.ncl)

```nickel
{
  name = "my-cluster",
  version = "1.0.0",
  description = "Custom application stack",

  components = {
    servers = [
      {name = "app", count = 3, plan = 'medium},
      {name = "db", count = 1, plan = 'large},
    ],
    services = ["nginx", "postgresql", "redis"],
  },

  config_schema = {
    domain | String,
    app_replicas | Number | default = 3,
    db_storage_gb | Number | default = 100,
  }
}
```

## Testing Extensions

### Local Testing

```bash
# Test provider operations
provisioning provider test my-provider --local

# Test task service installation
provisioning taskserv install my-service --dry-run

# Validate cluster definition
provisioning cluster validate my-cluster
```

### Integration Testing

```bash
# Create test workspace
provisioning workspace create test-extensions

# Deploy extension
provisioning extension deploy my-provider

# Test deployment
provisioning server create test-server --provider my-provider
```

## Extension Best Practices

1. **Define clear schemas** - Use Nickel contracts for type safety
2. **Implement health checks** - Validate service state
3. **Handle errors gracefully** - Return structured error messages
4. **Document configuration** - Provide clear examples
5. **Version extensions** - Track compatibility
6. **Test thoroughly** - Unit and integration tests

## Publishing Extensions

### Extension Registry

Share extensions with the community:

```bash
# Package extension
provisioning extension package my-provider

# Publish to registry
provisioning extension publish my-provider --registry community
```

### Private Registry

Host internal extensions:

```bash
# Configure private registry
provisioning config set extension_registry  [https://registry.internal](https://registry.internal)

# Publish privately
provisioning extension publish my-provider --private
```

## Examples

### Custom Database Provider

Provider for proprietary database platform:

```nickel
{
  name = "mydb-provider",
  capabilities = {databases = true},
  config_schema = {
    cluster_endpoint | String,
    admin_token | String,
  }
}
```

### Monitoring Stack Service

Complete monitoring deployment:

```nickel
{
  name = "monitoring-stack",
  dependencies = ["prometheus", "grafana", "loki"],
  config_schema = {
    retention_days | Number | default = 30,
    alert_email | String,
  }
}
```

## Troubleshooting

### Extension Not Loading

```bash
# Verify extension structure
provisioning extension validate my-extension

# Check logs
provisioning logs extension-loader --tail 100
```

### Deployment Failures

```bash
# Enable debug logging
export PROVISIONING_LOG_LEVEL=debug
provisioning taskserv install my-service

# Check service logs
provisioning taskserv logs my-service
```

## References

- [Extension Development](../development/extension-development.md) - Technical details
- [Provider Development](../development/provider-development.md) - Provider implementation
- [Task Services](../infrastructure/task-services.md) - Task service architecture
