2026-01-14 02:59:52 +00:00
|
|
|
# Integration Patterns\n\n## Overview\n\nProvisioning implements sophisticated integration patterns to coordinate between its hybrid Rust/Nushell architecture, manage multi-provider\nworkflows, and enable extensible functionality. This document outlines the key integration patterns, their implementations, and best practices.\n\n## Core Integration Patterns\n\n### 1. Hybrid Language Integration\n\n#### Rust-to-Nushell Communication Pattern\n\n**Use Case**: Orchestrator invoking business logic operations\n\n**Implementation**:\n\n```\nuse tokio::process::Command;\nuse serde_json;\n\npub async fn execute_nushell_workflow(\n workflow: &str,\n args: &[String]\n) -> Result<WorkflowResult, Error> {\n let mut cmd = Command::new("nu");\n cmd.arg("-c")\n .arg(format!("use core/nulib/workflows/{}.nu *; {}", workflow, args.join(" ")));\n\n let output = cmd.output().await?;\n let result: WorkflowResult = serde_json::from_slice(&output.stdout)?;\n Ok(result)\n}\n```\n\n**Data Exchange Format**:\n\n```\n{\n "status": "success" | "error" | "partial",\n "result": {\n "operation": "server_create",\n "resources": ["server-001", "server-002"],\n "metadata": { ... }\n },\n "error": null | { "code": "ERR001", "message": "..." },\n "context": { "workflow_id": "wf-123", "step": 2 }\n}\n```\n\n#### Nushell-to-Rust Communication Pattern\n\n**Use Case**: Business logic submitting workflows to orchestrator\n\n**Implementation**:\n\n```\ndef submit-workflow [workflow: record] -> record {\n let payload = $workflow | to json\n\n http post "http://localhost:9090/workflows/submit" {\n headers: { "Content-Type": "application/json" }\n body: $payload\n }\n | from json\n}\n```\n\n**API Contract**:\n\n```\n{\n "workflow_id": "wf-456",\n "name": "multi_cloud_deployment",\n "operations": [...],\n "dependencies": { ... },\n "configuration": { ... }\n}\n```\n\n### 2. Provider Abstraction Pattern\n\n#### Standard Provider Interface\n\n**Purpose**: Uniform API across different cloud providers\n\n**Interface Definition**:\n\n```\n# Standard provider interface that all providers must implement\nexport def list-servers [] -> table {\n # Provider-specific implementation\n}\n\nexport def create-server [config: record] -> record {\n # Provider-specific implementation\n}\n\nexport def delete-server [id: string] -> nothing {\n # Provider-specific implementation\n}\n\nexport def get-server [id: string] -> record {\n # Provider-specific implementation\n}\n```\n\n**Configuration Integration**:\n\n```\n[providers.aws]\nregion = "us-west-2"\ncredentials_profile = "default"\ntimeout = 300\n\n[providers.upcloud]\nzone = "de-fra1"\napi_endpoint = "https://api.upcloud.com"\ntimeout = 180\n\n[providers.local]\ndocker_socket = "/var/run/docker.sock"\nnetwork_mode = "bridge"\n```\n\n#### Provider Discovery and Loading\n\n```\ndef load-providers [] -> table {\n let provider_dirs = glob "providers/*/nulib"\n\n $provider_dirs\n | each { |dir|\n let provider_name = $dir | path basename | path dirname | path basename\n let provider_config = get-provider-config $provider_name\n\n {\n name: $provider_name,\n path: $dir,\n config: $provider_config,\n available: (test-provider-connectivity $provider_name)\n }\n }\n}\n```\n\n### 3. Configuration Resolution Pattern\n\n#### Hierarchical Configuration Loading\n\n**Implementation**:\n\n```\ndef resolve-configuration [context: record] -> record {\n let base_config = open config.defaults.toml\n let user_config = if ("config.user.toml" | path exists) {\n open config.user.toml\n } else { {} }\n\n let env_config = if ($env.PROVISIONING_ENV? | is-not-empty) {\n let env_file = $"config.($env.PROVISIONING_ENV).toml"\n if ($env_file | path exists) { open $env_file } else { {} }\n } else { {} }\n\n let merged_config = $base_config\n | merge $user_config\n | merge $env_config\n | merge ($context.runtime_config? |
|