2025-12-11 21:50:42 +00:00
# SDK Documentation
This document provides comprehensive documentation for the official SDKs and client libraries available for provisioning.
## Available SDKs
Provisioning provides SDKs in multiple languages to facilitate integration:
### Official SDKs
2026-01-08 09:55:37 +00:00
2025-12-11 21:50:42 +00:00
- **Python SDK** (`provisioning-client` ) - Full-featured Python client
- **JavaScript/TypeScript SDK** (`@provisioning/client` ) - Node.js and browser support
- **Go SDK** (`go-provisioning-client` ) - Go client library
- **Rust SDK** (`provisioning-rs` ) - Native Rust integration
### Community SDKs
2026-01-08 09:55:37 +00:00
2025-12-11 21:50:42 +00:00
- **Java SDK** - Community-maintained Java client
- **C# SDK** - .NET client library
- **PHP SDK** - PHP client library
## Python SDK
### Installation
```bash
# Install from PyPI
pip install provisioning-client
# Or install development version
pip install git+https://github.com/provisioning-systems/python-client.git
```
### Quick Start
```python
from provisioning_client import ProvisioningClient
import asyncio
async def main():
# Initialize client
client = ProvisioningClient(
base_url="http://localhost:9090",
auth_url="http://localhost:8081",
username="admin",
password="your-password"
)
try:
# Authenticate
token = await client.authenticate()
print(f"Authenticated with token: {token[:20]}...")
# Create a server workflow
task_id = client.create_server_workflow(
infra="production",
2026-01-08 09:55:37 +00:00
settings="prod-settings.ncl",
2025-12-11 21:50:42 +00:00
wait=False
)
print(f"Server workflow created: {task_id}")
# Wait for completion
task = client.wait_for_task_completion(task_id, timeout=600)
print(f"Task completed with status: {task.status}")
if task.status == "Completed":
print(f"Output: {task.output}")
elif task.status == "Failed":
print(f"Error: {task.error}")
except Exception as e:
print(f"Error: {e}")
if __name__ == "__main__":
asyncio.run(main())
```
### Advanced Usage
#### WebSocket Integration
```python
async def monitor_workflows():
client = ProvisioningClient()
await client.authenticate()
# Set up event handlers
async def on_task_update(event):
print(f"Task {event['data']['task_id']} status: {event['data']['status']}")
async def on_progress_update(event):
print(f"Progress: {event['data']['progress']}% - {event['data']['current_step']}")
client.on_event('TaskStatusChanged', on_task_update)
client.on_event('WorkflowProgressUpdate', on_progress_update)
# Connect to WebSocket
await client.connect_websocket(['TaskStatusChanged', 'WorkflowProgressUpdate'])
# Keep connection alive
await asyncio.sleep(3600) # Monitor for 1 hour
```
#### Batch Operations
```python
async def execute_batch_deployment():
client = ProvisioningClient()
await client.authenticate()
batch_config = {
"name": "production_deployment",
"version": "1.0.0",
"storage_backend": "surrealdb",
"parallel_limit": 5,
"rollback_enabled": True,
"operations": [
{
"id": "servers",
"type": "server_batch",
"provider": "upcloud",
"dependencies": [],
"config": {
"server_configs": [
2026-01-08 09:55:37 +00:00
{"name": "web-01", "plan": "2xCPU-4 GB", "zone": "de-fra1"},
{"name": "web-02", "plan": "2xCPU-4 GB", "zone": "de-fra1"}
2025-12-11 21:50:42 +00:00
]
}
},
{
"id": "kubernetes",
"type": "taskserv_batch",
"provider": "upcloud",
"dependencies": ["servers"],
"config": {
"taskservs": ["kubernetes", "cilium", "containerd"]
}
}
]
}
# Execute batch operation
batch_result = await client.execute_batch_operation(batch_config)
print(f"Batch operation started: {batch_result['batch_id']}")
# Monitor progress
while True:
status = await client.get_batch_status(batch_result['batch_id'])
print(f"Batch status: {status['status']} - {status.get('progress', 0)}%")
if status['status'] in ['Completed', 'Failed', 'Cancelled']:
break
await asyncio.sleep(10)
print(f"Batch operation finished: {status['status']}")
```
#### Error Handling with Retries
```python
from provisioning_client.exceptions import (
ProvisioningAPIError,
AuthenticationError,
ValidationError,
RateLimitError
)
from tenacity import retry, stop_after_attempt, wait_exponential
class RobustProvisioningClient(ProvisioningClient):
@retry (
stop=stop_after_attempt(3),
wait=wait_exponential(multiplier=1, min=4, max=10)
)
async def create_server_workflow_with_retry(self, **kwargs):
try:
return await self.create_server_workflow(**kwargs)
except RateLimitError as e:
print(f"Rate limited, retrying in {e.retry_after} seconds...")
await asyncio.sleep(e.retry_after)
raise
except AuthenticationError:
print("Authentication failed, re-authenticating...")
await self.authenticate()
raise
except ValidationError as e:
print(f"Validation error: {e}")
# Don't retry validation errors
raise
except ProvisioningAPIError as e:
print(f"API error: {e}")
raise
# Usage
async def robust_workflow():
client = RobustProvisioningClient()
try:
task_id = await client.create_server_workflow_with_retry(
infra="production",
2026-01-08 09:55:37 +00:00
settings="config.ncl"
2025-12-11 21:50:42 +00:00
)
print(f"Workflow created successfully: {task_id}")
except Exception as e:
print(f"Failed after retries: {e}")
```
### API Reference
#### ProvisioningClient Class
```python
class ProvisioningClient:
def __init__ (self,
base_url: str = "http://localhost:9090",
auth_url: str = "http://localhost:8081",
username: str = None,
password: str = None,
token: str = None):
"""Initialize the provisioning client"""
async def authenticate(self) -> str:
"""Authenticate and get JWT token"""
def create_server_workflow(self,
infra: str,
2026-01-08 09:55:37 +00:00
settings: str = "config.ncl",
2025-12-11 21:50:42 +00:00
check_mode: bool = False,
wait: bool = False) -> str:
"""Create a server provisioning workflow"""
def create_taskserv_workflow(self,
operation: str,
taskserv: str,
infra: str,
2026-01-08 09:55:37 +00:00
settings: str = "config.ncl",
2025-12-11 21:50:42 +00:00
check_mode: bool = False,
wait: bool = False) -> str:
"""Create a task service workflow"""
def get_task_status(self, task_id: str) -> WorkflowTask:
"""Get the status of a specific task"""
def wait_for_task_completion(self,
task_id: str,
timeout: int = 300,
poll_interval: int = 5) -> WorkflowTask:
"""Wait for a task to complete"""
async def connect_websocket(self, event_types: List[str] = None):
"""Connect to WebSocket for real-time updates"""
def on_event(self, event_type: str, handler: Callable):
"""Register an event handler"""
```
## JavaScript/TypeScript SDK
### Installation
```bash
# npm
npm install @provisioning/client
# yarn
yarn add @provisioning/client
# pnpm
pnpm add @provisioning/client
```
### Quick Start
```typescript
import { ProvisioningClient } from '@provisioning/client ';
async function main() {
const client = new ProvisioningClient({
baseUrl: 'http://localhost:9090',
authUrl: 'http://localhost:8081',
username: 'admin',
password: 'your-password'
});
try {
// Authenticate
await client.authenticate();
console.log('Authentication successful');
// Create server workflow
const taskId = await client.createServerWorkflow({
infra: 'production',
2026-01-08 09:55:37 +00:00
settings: 'prod-settings.ncl'
2025-12-11 21:50:42 +00:00
});
console.log(`Server workflow created: ${taskId}` );
// Wait for completion
const task = await client.waitForTaskCompletion(taskId);
console.log(`Task completed with status: ${task.status}` );
} catch (error) {
console.error('Error:', error.message);
}
}
main();
```
### React Integration
```tsx
import React, { useState, useEffect } from 'react';
import { ProvisioningClient } from '@provisioning/client ';
interface Task {
id: string;
name: string;
status: string;
progress?: number;
}
const WorkflowDashboard: React.FC = () => {
const [client] = useState(() => new ProvisioningClient({
baseUrl: process.env.REACT_APP_API_URL,
username: process.env.REACT_APP_USERNAME,
password: process.env.REACT_APP_PASSWORD
}));
const [tasks, setTasks] = useState< Task [ ] > ([]);
const [connected, setConnected] = useState(false);
useEffect(() => {
const initClient = async () => {
try {
await client.authenticate();
// Set up WebSocket event handlers
client.on('TaskStatusChanged', (event: any) => {
setTasks(prev => prev.map(task =>
task.id === event.data.task_id
? { ...task, status: event.data.status, progress: event.data.progress }
: task
));
});
client.on('websocketConnected', () => {
setConnected(true);
});
client.on('websocketDisconnected', () => {
setConnected(false);
});
// Connect WebSocket
await client.connectWebSocket(['TaskStatusChanged', 'WorkflowProgressUpdate']);
// Load initial tasks
const initialTasks = await client.listTasks();
setTasks(initialTasks);
} catch (error) {
console.error('Failed to initialize client:', error);
}
};
initClient();
return () => {
client.disconnectWebSocket();
};
}, [client]);
const createServerWorkflow = async () => {
try {
const taskId = await client.createServerWorkflow({
infra: 'production',
2026-01-08 09:55:37 +00:00
settings: 'config.ncl'
2025-12-11 21:50:42 +00:00
});
// Add to tasks list
setTasks(prev => [...prev, {
id: taskId,
name: 'Server Creation',
status: 'Pending'
}]);
} catch (error) {
console.error('Failed to create workflow:', error);
}
};
return (
< div className = "workflow-dashboard" >
< div className = "header" >
< h1 > Workflow Dashboard< / h1 >
< div className = { `connection-status ${connected ? 'connected' : 'disconnected'}` } >
{connected ? '🟢 Connected' : '🔴 Disconnected'}
< / div >
< / div >
< div className = "controls" >
< button onClick = {createServerWorkflow} >
Create Server Workflow
< / button >
< / div >
< div className = "tasks" >
{tasks.map(task => (
< div key = {task.id} className = "task-card" >
< h3 > {task.name}< / h3 >
< div className = "task-status" >
< span className = { `status ${task.status.toLowerCase()}` } >
{task.status}
< / span >
{task.progress & & (
< div className = "progress-bar" >
< div
className="progress-fill"
style={{ width: `${task.progress}%` }}
/>
< span className = "progress-text" > {task.progress}%< / span >
< / div >
)}
< / div >
< / div >
))}
< / div >
< / div >
);
};
export default WorkflowDashboard;
```
### Node.js CLI Tool
```typescript
#!/usr/bin/env node
import { Command } from 'commander';
import { ProvisioningClient } from '@provisioning/client ';
import chalk from 'chalk';
import ora from 'ora';
const program = new Command();
program
.name('provisioning-cli')
.description('CLI tool for provisioning')
.version('1.0.0');
program
.command('create-server')
.description('Create a server workflow')
.requiredOption('-i, --infra < infra > ', 'Infrastructure target')
2026-01-08 09:55:37 +00:00
.option('-s, --settings < settings > ', 'Settings file', 'config.ncl')
2025-12-11 21:50:42 +00:00
.option('-c, --check', 'Check mode only')
.option('-w, --wait', 'Wait for completion')
.action(async (options) => {
const client = new ProvisioningClient({
baseUrl: process.env.PROVISIONING_API_URL,
username: process.env.PROVISIONING_USERNAME,
password: process.env.PROVISIONING_PASSWORD
});
const spinner = ora('Authenticating...').start();
try {
await client.authenticate();
spinner.text = 'Creating server workflow...';
const taskId = await client.createServerWorkflow({
infra: options.infra,
settings: options.settings,
check_mode: options.check,
wait: false
});
spinner.succeed(`Server workflow created: ${chalk.green(taskId)}` );
if (options.wait) {
spinner.start('Waiting for completion...');
// Set up progress updates
client.on('TaskStatusChanged', (event: any) => {
if (event.data.task_id === taskId) {
spinner.text = `Status: ${event.data.status}` ;
}
});
client.on('WorkflowProgressUpdate', (event: any) => {
if (event.data.workflow_id === taskId) {
spinner.text = `${event.data.progress}% - ${event.data.current_step}` ;
}
});
await client.connectWebSocket(['TaskStatusChanged', 'WorkflowProgressUpdate']);
const task = await client.waitForTaskCompletion(taskId);
if (task.status === 'Completed') {
spinner.succeed(chalk.green('Workflow completed successfully!'));
if (task.output) {
console.log(chalk.gray('Output:'), task.output);
}
} else {
spinner.fail(chalk.red(`Workflow failed: ${task.error}` ));
process.exit(1);
}
}
} catch (error) {
spinner.fail(chalk.red(`Error: ${error.message}` ));
process.exit(1);
}
});
program
.command('list-tasks')
.description('List all tasks')
.option('-s, --status < status > ', 'Filter by status')
.action(async (options) => {
const client = new ProvisioningClient();
try {
await client.authenticate();
const tasks = await client.listTasks(options.status);
console.log(chalk.bold('Tasks:'));
tasks.forEach(task => {
const statusColor = task.status === 'Completed' ? 'green' :
task.status === 'Failed' ? 'red' :
task.status === 'Running' ? 'yellow' : 'gray';
console.log(` ${task.id} - ${task.name} [${chalk[statusColor](task.status)}]` );
});
} catch (error) {
console.error(chalk.red(`Error: ${error.message}` ));
process.exit(1);
}
});
program
.command('monitor')
.description('Monitor workflows in real-time')
.action(async () => {
const client = new ProvisioningClient();
try {
await client.authenticate();
console.log(chalk.bold('🔍 Monitoring workflows...'));
console.log(chalk.gray('Press Ctrl+C to stop'));
client.on('TaskStatusChanged', (event: any) => {
const timestamp = new Date().toLocaleTimeString();
const statusColor = event.data.status === 'Completed' ? 'green' :
event.data.status === 'Failed' ? 'red' :
event.data.status === 'Running' ? 'yellow' : 'gray';
console.log(`[${chalk.gray(timestamp)}] Task ${event.data.task_id} → ${chalk[statusColor](event.data.status)}` );
});
client.on('WorkflowProgressUpdate', (event: any) => {
const timestamp = new Date().toLocaleTimeString();
console.log(`[${chalk.gray(timestamp)}] ${event.data.workflow_id}: ${event.data.progress}% - ${event.data.current_step}` );
});
await client.connectWebSocket(['TaskStatusChanged', 'WorkflowProgressUpdate']);
// Keep the process running
process.on('SIGINT', () => {
console.log(chalk.yellow('\nStopping monitor...'));
client.disconnectWebSocket();
process.exit(0);
});
// Keep alive
setInterval(() => {}, 1000);
} catch (error) {
console.error(chalk.red(`Error: ${error.message}` ));
process.exit(1);
}
});
program.parse();
```
### API Reference
```typescript
interface ProvisioningClientOptions {
baseUrl?: string;
authUrl?: string;
username?: string;
password?: string;
token?: string;
}
class ProvisioningClient extends EventEmitter {
constructor(options: ProvisioningClientOptions);
async authenticate(): Promise< string > ;
async createServerWorkflow(config: {
infra: string;
settings?: string;
check_mode?: boolean;
wait?: boolean;
}): Promise< string > ;
async createTaskservWorkflow(config: {
operation: string;
taskserv: string;
infra: string;
settings?: string;
check_mode?: boolean;
wait?: boolean;
}): Promise< string > ;
async getTaskStatus(taskId: string): Promise< Task > ;
async listTasks(statusFilter?: string): Promise< Task [ ] > ;
async waitForTaskCompletion(
taskId: string,
timeout?: number,
pollInterval?: number
): Promise< Task > ;
async connectWebSocket(eventTypes?: string[]): Promise< void > ;
disconnectWebSocket(): void;
async executeBatchOperation(batchConfig: BatchConfig): Promise< any > ;
async getBatchStatus(batchId: string): Promise< any > ;
}
```
## Go SDK
### Installation
```bash
go get github.com/provisioning-systems/go-client
```
### Quick Start
```go
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/provisioning-systems/go-client"
)
func main() {
// Initialize client
client, err := provisioning.NewClient(& provisioning.Config{
BaseURL: "http://localhost:9090",
AuthURL: "http://localhost:8081",
Username: "admin",
Password: "your-password",
})
if err != nil {
log.Fatalf("Failed to create client: %v", err)
}
ctx := context.Background()
// Authenticate
token, err := client.Authenticate(ctx)
if err != nil {
log.Fatalf("Authentication failed: %v", err)
}
fmt.Printf("Authenticated with token: %.20s...\n", token)
// Create server workflow
taskID, err := client.CreateServerWorkflow(ctx, & provisioning.CreateServerRequest{
Infra: "production",
2026-01-08 09:55:37 +00:00
Settings: "prod-settings.ncl",
2025-12-11 21:50:42 +00:00
Wait: false,
})
if err != nil {
log.Fatalf("Failed to create workflow: %v", err)
}
fmt.Printf("Server workflow created: %s\n", taskID)
// Wait for completion
task, err := client.WaitForTaskCompletion(ctx, taskID, 10*time.Minute)
if err != nil {
log.Fatalf("Failed to wait for completion: %v", err)
}
fmt.Printf("Task completed with status: %s\n", task.Status)
if task.Status == "Completed" {
fmt.Printf("Output: %s\n", task.Output)
} else if task.Status == "Failed" {
fmt.Printf("Error: %s\n", task.Error)
}
}
```
### WebSocket Integration
```go
package main
import (
"context"
"fmt"
"log"
"os"
"os/signal"
"github.com/provisioning-systems/go-client"
)
func main() {
client, err := provisioning.NewClient(& provisioning.Config{
BaseURL: "http://localhost:9090",
Username: "admin",
Password: "password",
})
if err != nil {
log.Fatalf("Failed to create client: %v", err)
}
ctx := context.Background()
// Authenticate
_, err = client.Authenticate(ctx)
if err != nil {
log.Fatalf("Authentication failed: %v", err)
}
// Set up WebSocket connection
ws, err := client.ConnectWebSocket(ctx, []string{
"TaskStatusChanged",
"WorkflowProgressUpdate",
})
if err != nil {
log.Fatalf("Failed to connect WebSocket: %v", err)
}
defer ws.Close()
// Handle events
go func() {
for event := range ws.Events() {
switch event.Type {
case "TaskStatusChanged":
fmt.Printf("Task %s status changed to: %s\n",
event.Data["task_id"], event.Data["status"])
case "WorkflowProgressUpdate":
fmt.Printf("Workflow progress: %v%% - %s\n",
event.Data["progress"], event.Data["current_step"])
}
}
}()
// Wait for interrupt
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
< -c
fmt.Println("Shutting down...")
}
```
### HTTP Client with Retry Logic
```go
package main
import (
"context"
"fmt"
"time"
"github.com/provisioning-systems/go-client"
"github.com/cenkalti/backoff/v4"
)
type ResilientClient struct {
*provisioning.Client
}
func NewResilientClient(config *provisioning.Config) (*ResilientClient, error) {
client, err := provisioning.NewClient(config)
if err != nil {
return nil, err
}
return & ResilientClient{Client: client}, nil
}
func (c *ResilientClient) CreateServerWorkflowWithRetry(
ctx context.Context,
req *provisioning.CreateServerRequest,
) (string, error) {
var taskID string
operation := func() error {
var err error
taskID, err = c.CreateServerWorkflow(ctx, req)
// Don't retry validation errors
if provisioning.IsValidationError(err) {
return backoff.Permanent(err)
}
return err
}
exponentialBackoff := backoff.NewExponentialBackOff()
exponentialBackoff.MaxElapsedTime = 5 * time.Minute
err := backoff.Retry(operation, exponentialBackoff)
if err != nil {
return "", fmt.Errorf("failed after retries: %w", err)
}
return taskID, nil
}
func main() {
client, err := NewResilientClient(& provisioning.Config{
BaseURL: "http://localhost:9090",
Username: "admin",
Password: "password",
})
if err != nil {
log.Fatalf("Failed to create client: %v", err)
}
ctx := context.Background()
// Authenticate with retry
_, err = client.Authenticate(ctx)
if err != nil {
log.Fatalf("Authentication failed: %v", err)
}
// Create workflow with retry
taskID, err := client.CreateServerWorkflowWithRetry(ctx, & provisioning.CreateServerRequest{
Infra: "production",
2026-01-08 09:55:37 +00:00
Settings: "config.ncl",
2025-12-11 21:50:42 +00:00
})
if err != nil {
log.Fatalf("Failed to create workflow: %v", err)
}
fmt.Printf("Workflow created successfully: %s\n", taskID)
}
```
## Rust SDK
### Installation
Add to your `Cargo.toml` :
```toml
[dependencies]
provisioning-rs = "2.0.0"
tokio = { version = "1.0", features = ["full"] }
```
### Quick Start
```rust
use provisioning_rs::{ProvisioningClient, Config, CreateServerRequest};
use tokio;
#[tokio::main]
async fn main() -> Result< (), Box< dyn std::error::Error > > {
// Initialize client
let config = Config {
base_url: "http://localhost:9090".to_string(),
auth_url: Some("http://localhost:8081".to_string()),
username: Some("admin".to_string()),
password: Some("your-password".to_string()),
token: None,
};
let mut client = ProvisioningClient::new(config);
// Authenticate
let token = client.authenticate().await?;
println!("Authenticated with token: {}...", &token[..20]);
// Create server workflow
let request = CreateServerRequest {
infra: "production".to_string(),
2026-01-08 09:55:37 +00:00
settings: Some("prod-settings.ncl".to_string()),
2025-12-11 21:50:42 +00:00
check_mode: false,
wait: false,
};
let task_id = client.create_server_workflow(request).await?;
println!("Server workflow created: {}", task_id);
// Wait for completion
let task = client.wait_for_task_completion(& task_id, std::time::Duration::from_secs(600)).await?;
println!("Task completed with status: {:?}", task.status);
match task.status {
TaskStatus::Completed => {
if let Some(output) = task.output {
println!("Output: {}", output);
}
},
TaskStatus::Failed => {
if let Some(error) = task.error {
println!("Error: {}", error);
}
},
_ => {}
}
Ok(())
}
```
### WebSocket Integration
```rust
use provisioning_rs::{ProvisioningClient, Config, WebSocketEvent};
use futures_util::StreamExt;
use tokio;
#[tokio::main]
async fn main() -> Result< (), Box< dyn std::error::Error > > {
let config = Config {
base_url: "http://localhost:9090".to_string(),
username: Some("admin".to_string()),
password: Some("password".to_string()),
..Default::default()
};
let mut client = ProvisioningClient::new(config);
// Authenticate
client.authenticate().await?;
// Connect WebSocket
let mut ws = client.connect_websocket(vec![
"TaskStatusChanged".to_string(),
"WorkflowProgressUpdate".to_string(),
]).await?;
// Handle events
tokio::spawn(async move {
while let Some(event) = ws.next().await {
match event {
Ok(WebSocketEvent::TaskStatusChanged { data }) => {
println!("Task {} status changed to: {}", data.task_id, data.status);
},
Ok(WebSocketEvent::WorkflowProgressUpdate { data }) => {
println!("Workflow progress: {}% - {}", data.progress, data.current_step);
},
Ok(WebSocketEvent::SystemHealthUpdate { data }) => {
println!("System health: {}", data.overall_status);
},
Err(e) => {
eprintln!("WebSocket error: {}", e);
break;
}
}
}
});
// Keep the main thread alive
tokio::signal::ctrl_c().await?;
println!("Shutting down...");
Ok(())
}
```
### Batch Operations
```rust
use provisioning_rs::{BatchOperationRequest, BatchOperation};
#[tokio::main]
async fn main() -> Result< (), Box< dyn std::error::Error > > {
let mut client = ProvisioningClient::new(config);
client.authenticate().await?;
// Define batch operation
let batch_request = BatchOperationRequest {
name: "production_deployment".to_string(),
version: "1.0.0".to_string(),
storage_backend: "surrealdb".to_string(),
parallel_limit: 5,
rollback_enabled: true,
operations: vec![
BatchOperation {
id: "servers".to_string(),
operation_type: "server_batch".to_string(),
provider: "upcloud".to_string(),
dependencies: vec![],
config: serde_json::json!({
"server_configs": [
2026-01-08 09:55:37 +00:00
{"name": "web-01", "plan": "2xCPU-4 GB", "zone": "de-fra1"},
{"name": "web-02", "plan": "2xCPU-4 GB", "zone": "de-fra1"}
2025-12-11 21:50:42 +00:00
]
}),
},
BatchOperation {
id: "kubernetes".to_string(),
operation_type: "taskserv_batch".to_string(),
provider: "upcloud".to_string(),
dependencies: vec!["servers".to_string()],
config: serde_json::json!({
"taskservs": ["kubernetes", "cilium", "containerd"]
}),
},
],
};
// Execute batch operation
let batch_result = client.execute_batch_operation(batch_request).await?;
println!("Batch operation started: {}", batch_result.batch_id);
// Monitor progress
loop {
let status = client.get_batch_status(&batch_result.batch_id).await?;
println!("Batch status: {} - {}%", status.status, status.progress.unwrap_or(0.0));
match status.status.as_str() {
"Completed" | "Failed" | "Cancelled" => break,
_ => tokio::time::sleep(std::time::Duration::from_secs(10)).await,
}
}
Ok(())
}
```
## Best Practices
### Authentication and Security
1. **Token Management** : Store tokens securely and implement automatic refresh
2. **Environment Variables** : Use environment variables for credentials
3. **HTTPS** : Always use HTTPS in production environments
4. **Token Expiration** : Handle token expiration gracefully
### Error Handling
1. **Specific Exceptions** : Handle specific error types appropriately
2. **Retry Logic** : Implement exponential backoff for transient failures
3. **Circuit Breakers** : Use circuit breakers for resilient integrations
4. **Logging** : Log errors with appropriate context
### Performance Optimization
1. **Connection Pooling** : Reuse HTTP connections
2. **Async Operations** : Use asynchronous operations where possible
3. **Batch Operations** : Group related operations for efficiency
4. **Caching** : Cache frequently accessed data appropriately
### WebSocket Connections
1. **Reconnection** : Implement automatic reconnection with backoff
2. **Event Filtering** : Subscribe only to needed event types
3. **Error Handling** : Handle WebSocket errors gracefully
4. **Resource Cleanup** : Properly close WebSocket connections
### Testing
1. **Unit Tests** : Test SDK functionality with mocked responses
2. **Integration Tests** : Test against real API endpoints
3. **Error Scenarios** : Test error handling paths
4. **Load Testing** : Validate performance under load
2026-01-08 09:55:37 +00:00
This comprehensive SDK documentation provides developers with everything needed to integrate with provisioning using their preferred programming language, complete with examples, best practices, and detailed API references.