# Provider Interface Specification # Defines the contract that all providers must implement for provider-agnostic operations # # AUTHENTICATION NOTE: # Provider operations are authenticated at the infrastructure command level. # All provider implementations can assume authentication has been verified before # these functions are called. Provider API calls should include authentication # metadata for audit logging purposes. # Standard provider interface - all providers must implement these functions export def get-provider-interface []: nothing -> record { { # Server query operations query_servers: { signature: "find?: string, cols?: string -> list" description: "Query servers with optional find/column filtering" } # Server information operations server_info: { signature: "server: record, check: bool, find?: string, cols?: string -> record" description: "Get detailed information about a specific server" } # Server existence and status operations server_exists: { signature: "server: record, error_exit: bool -> bool" description: "Check if server exists in provider" } server_is_running: { signature: "server: record, error_exit: bool -> bool" description: "Check if server is in running state" } # Server lifecycle operations check_server_requirements: { signature: "settings: record, server: record, check: bool -> bool" description: "Validate server configuration meets provider requirements" } create_server: { signature: "settings: record, server: record, check: bool, wait: bool -> bool" description: "Create a new server instance" } delete_server: { signature: "settings: record, server: record, keep_storage: bool, error_exit: bool -> bool" description: "Delete server instance" } delete_server_storage: { signature: "settings: record, server: record, error_exit: bool -> bool" description: "Delete server storage volumes" } post_create_server: { signature: "settings: record, server: record, check: bool -> bool" description: "Post-creation server configuration" } modify_server: { signature: "settings: record, server: record, new_values: list, error_exit: bool -> bool" description: "Modify server configuration" } # Server state management server_state: { signature: "server: record, new_state: string, error_exit: bool, wait: bool, settings: record -> bool" description: "Change server state (start/stop/restart)" } # Network operations get_ip: { signature: "settings: record, server: record, ip_type: string, error_exit: bool -> string" description: "Get server IP address (public/private)" } servers_ips: { signature: "settings: record, data: list, prov?: string, serverpos?: int -> list" description: "Get IP addresses for multiple servers" } # Infrastructure operations load_infra_servers_info: { signature: "settings: record, server: record, error_exit: bool -> record" description: "Load infrastructure server information" } load_infra_storages_info: { signature: "settings: record, server: record, error_exit: bool -> record" description: "Load infrastructure storage information" } get_infra_storage: { signature: "server: record, settings: record, cloud_data: record, error_exit: bool -> list" description: "Get infrastructure storage details" } get_infra_item: { signature: "server: record, settings: record, cloud_data: record, error_exit: bool -> record" description: "Get infrastructure item details" } get_infra_price: { signature: "server: record, data: record, key: string, error_exit: bool, price_col?: string -> float" description: "Get infrastructure pricing information" } # Cache operations start_cache_info: { signature: "settings: record, server: record -> nothing" description: "Initialize cache information" } create_cache: { signature: "settings: record, server: record, error_exit: bool -> nothing" description: "Create server cache" } read_cache: { signature: "settings: record, server: record, error_exit: bool -> nothing" description: "Read server cache" } clean_cache: { signature: "settings: record, server: record, error_exit: bool -> nothing" description: "Clean server cache" } ip_from_cache: { signature: "settings: record, server: record, error_exit: bool -> nothing" description: "Get IP from server cache" } # Provider metadata operations on_prov_server: { signature: "server: record -> string" description: "Get provider display message for server" } } } # Validate that a provider implements the required interface export def validate-provider-interface [ provider_name: string provider_module: record ]: nothing -> record { let interface = (get-provider-interface) let required_functions = ($interface | columns) mut validation_result = { provider: $provider_name valid: true missing_functions: [] invalid_functions: [] warnings: [] } # Check each required function for function_name in $required_functions { let has_function = ($function_name in ($provider_module | columns)) if not $has_function { $validation_result.missing_functions = ($validation_result.missing_functions | append $function_name) $validation_result.valid = false } } # Add warnings for extra functions (not required but noted) let provider_functions = ($provider_module | columns) for function_name in $provider_functions { if not ($function_name in $required_functions) { $validation_result.warnings = ($validation_result.warnings | append $"Extra function: ($function_name)") } } $validation_result } # Get provider interface documentation export def get-provider-interface-docs []: nothing -> table { let interface = (get-provider-interface) $interface | transpose function details | each {|row| { function: $row.function signature: $row.details.signature description: $row.details.description } } } # Provider capability flags - optional extensions export def get-provider-capabilities []: nothing -> record { { # Core capabilities (required for all providers) server_management: true network_management: true storage_management: true # Optional capabilities (provider-specific) load_balancer: false dns_management: false cdn: false backup_service: false monitoring: false logging: false # Advanced capabilities auto_scaling: false spot_instances: false containers: false serverless: false # Multi-region support multi_region: false # Compliance and security encryption_at_rest: false encryption_in_transit: false compliance_certifications: [] } } # Provider interface version export def get-interface-version []: nothing -> string { "1.0.0" } # Authentication Guidelines for Provider Implementations # # All provider implementations should follow these authentication principles: # # 1. **Trust Upstream Authentication**: Provider functions can trust that authentication # has been verified at the infrastructure command level before being called. # # 2. **Include Auth Metadata**: When making API calls to cloud providers, include # authentication metadata in request headers/context for audit trail purposes. # # 3. **Log Operations**: Use the auth.nu functions to log operations with user context: # ```nushell # use ../plugins/auth.nu [log-authenticated-operation, get-auth-metadata] # # def create_server [...] { # let auth_metadata = (get-auth-metadata) # log-authenticated-operation "provider_create_server" { # provider: "aws" # server_name: $server.hostname # user: $auth_metadata.username # } # # ... actual implementation # } # ``` # # 4. **Provider-Specific Auth**: If the provider has its own authentication system # (e.g., AWS credentials, UpCloud API keys), those are configured separately and # are independent of the platform authentication system. # # 5. **Error Handling**: If a provider operation fails due to provider-specific # authentication issues (expired API keys, invalid credentials), return clear # error messages that distinguish between platform auth and provider auth: # - Platform auth: User not logged into provisioning platform # - Provider auth: Cloud provider credentials invalid/expired # # Example provider implementation with authentication: # # ```nushell # use ../plugins/auth.nu [log-authenticated-operation, get-auth-metadata] # # export def create_server [ # settings: record # server: record # check: bool # wait: bool # ]: nothing -> bool { # # Log the operation with user context # let auth_metadata = (get-auth-metadata) # log-authenticated-operation "aws_create_server" { # server_name: $server.hostname # region: $server.region # instance_type: $server.plan # user: $auth_metadata.username # } # # # Proceed with AWS-specific implementation # # AWS credentials are loaded from AWS config/env (separate from platform auth) # try { # # ... create EC2 instance ... # } catch { # error make { # msg: "AWS API error" # label: {text: "Check AWS credentials in ~/.aws/credentials"} # } # } # } # ```