# Path Resolution API This document describes the path resolution system used throughout the provisioning infrastructure for discovering configurations, extensions, and resolving workspace paths. ## Overview The path resolution system provides a hierarchical and configurable mechanism for: - Configuration file discovery and loading - Extension discovery (providers, task services, clusters) - Workspace and project path management - Environment variable interpolation - Cross-platform path handling ## Configuration Resolution Hierarchy The system follows a specific hierarchy for loading configuration files: ```toml 1. System defaults (config.defaults.toml) 2. User configuration (config.user.toml) 3. Project configuration (config.project.toml) 4. Infrastructure config (infra/config.toml) 5. Environment config (config.{env}.toml) 6. Runtime overrides (CLI arguments, ENV vars) ``` ### Configuration Search Paths The system searches for configuration files in these locations: ```toml # Default search paths (in order) /usr/local/provisioning/config.defaults.toml $HOME/.config/provisioning/config.user.toml $PWD/config.project.toml $PROVISIONING_KLOUD_PATH/config.infra.toml $PWD/config.{PROVISIONING_ENV}.toml ``` ## Path Resolution API ### Core Functions #### `resolve-config-path(pattern: string, search_paths: list) -> string` Resolves configuration file paths using the search hierarchy. **Parameters:** - `pattern`: File pattern to search for (for example, "config.*.toml") - `search_paths`: Additional paths to search (optional) **Returns:** - Full path to the first matching configuration file - Empty string if no file found **Example:** ```bash use path-resolution.nu * let config_path = (resolve-config-path "config.user.toml" []) # Returns: "/home/user/.config/provisioning/config.user.toml" ``` #### `resolve-extension-path(type: string, name: string) -> record` Discovers extension paths (providers, taskservs, clusters). **Parameters:** - `type`: Extension type ("provider", "taskserv", "cluster") - `name`: Extension name (for example, "upcloud", "kubernetes", "buildkit") **Returns:** ```json { base_path: "/usr/local/provisioning/providers/upcloud", schemas_path: "/usr/local/provisioning/providers/upcloud/schemas", nulib_path: "/usr/local/provisioning/providers/upcloud/nulib", templates_path: "/usr/local/provisioning/providers/upcloud/templates", exists: true } ``` #### `resolve-workspace-paths() -> record` Gets current workspace path configuration. **Returns:** ```json { base: "/usr/local/provisioning", current_infra: "/workspace/infra/production", kloud_path: "/workspace/kloud", providers: "/usr/local/provisioning/providers", taskservs: "/usr/local/provisioning/taskservs", clusters: "/usr/local/provisioning/cluster", extensions: "/workspace/extensions" } ``` ### Path Interpolation The system supports variable interpolation in configuration paths: #### Supported Variables - `{{paths.base}}` - Base provisioning path - `{{paths.kloud}}` - Current kloud path - `{{env.HOME}}` - User home directory - `{{env.PWD}}` - Current working directory - `{{now.date}}` - Current date (YYYY-MM-DD) - `{{now.time}}` - Current time (HH:MM:SS) - `{{git.branch}}` - Current git branch - `{{git.commit}}` - Current git commit hash #### `interpolate-path(template: string, context: record) -> string` Interpolates variables in path templates. **Parameters:** - `template`: Path template with variables - `context`: Variable context record **Example:** ```javascript let template = "{{paths.base}}/infra/{{env.USER}}/{{git.branch}}" let result = (interpolate-path $template { paths: { base: "/usr/local/provisioning" }, env: { USER: "admin" }, git: { branch: "main" } }) # Returns: "/usr/local/provisioning/infra/admin/main" ``` ## Extension Discovery API ### Provider Discovery #### `discover-providers() -> list` Discovers all available providers. **Returns:** ```bash [ { name: "upcloud", path: "/usr/local/provisioning/providers/upcloud", type: "provider", version: "1.2.0", enabled: true, has_schemas: true, has_nulib: true, has_templates: true }, { name: "aws", path: "/usr/local/provisioning/providers/aws", type: "provider", version: "2.1.0", enabled: true, has_schemas: true, has_nulib: true, has_templates: true } ] ``` #### `get-provider-config(name: string) -> record` Gets provider-specific configuration and paths. **Parameters:** - `name`: Provider name **Returns:** ```json { name: "upcloud", base_path: "/usr/local/provisioning/providers/upcloud", config: { api_url: "https://api.upcloud.com/1.3", auth_method: "basic", interface: "API" }, paths: { schemas: "/usr/local/provisioning/providers/upcloud/schemas", nulib: "/usr/local/provisioning/providers/upcloud/nulib", templates: "/usr/local/provisioning/providers/upcloud/templates" }, metadata: { version: "1.2.0", description: "UpCloud provider for server provisioning" } } ``` ### Task Service Discovery #### `discover-taskservs() -> list` Discovers all available task services. **Returns:** ```bash [ { name: "kubernetes", path: "/usr/local/provisioning/taskservs/kubernetes", type: "taskserv", category: "orchestration", version: "1.28.0", enabled: true }, { name: "cilium", path: "/usr/local/provisioning/taskservs/cilium", type: "taskserv", category: "networking", version: "1.14.0", enabled: true } ] ``` #### `get-taskserv-config(name: string) -> record` Gets task service configuration and version information. **Parameters:** - `name`: Task service name **Returns:** ```json { name: "kubernetes", path: "/usr/local/provisioning/taskservs/kubernetes", version: { current: "1.28.0", available: "1.28.2", update_available: true, source: "github", release_url: "https://github.com/kubernetes/kubernetes/releases" }, config: { category: "orchestration", dependencies: ["containerd"], supports_versions: ["1.26.x", "1.27.x", "1.28.x"] } } ``` ### Cluster Discovery #### `discover-clusters() -> list` Discovers all available cluster configurations. **Returns:** ```bash [ { name: "buildkit", path: "/usr/local/provisioning/cluster/buildkit", type: "cluster", category: "build", components: ["buildkit", "registry", "storage"], enabled: true } ] ``` ## Environment Management API ### Environment Detection #### `detect-environment() -> string` Automatically detects the current environment based on: 1. `PROVISIONING_ENV` environment variable 2. Git branch patterns (main → prod, develop → dev, etc.) 3. Directory structure analysis 4. Configuration file presence **Returns:** - Environment name string (dev, test, prod, etc.) #### `get-environment-config(env: string) -> record` Gets environment-specific configuration. **Parameters:** - `env`: Environment name **Returns:** ```json { name: "production", paths: { base: "/opt/provisioning", kloud: "/data/kloud", logs: "/var/log/provisioning" }, providers: { default: "upcloud", allowed: ["upcloud", "aws"] }, features: { debug: false, telemetry: true, rollback: true } } ``` ### Environment Switching #### `switch-environment(env: string, validate: bool = true) -> null` Switches to a different environment and updates path resolution. **Parameters:** - `env`: Target environment name - `validate`: Whether to validate environment configuration **Effects:** - Updates `PROVISIONING_ENV` environment variable - Reconfigures path resolution for new environment - Validates environment configuration if requested ## Workspace Management API ### Workspace Discovery #### `discover-workspaces() -> list` Discovers available workspaces and infrastructure directories. **Returns:** ```bash [ { name: "production", path: "/workspace/infra/production", type: "infrastructure", provider: "upcloud", settings: "settings.ncl", valid: true }, { name: "development", path: "/workspace/infra/development", type: "infrastructure", provider: "local", settings: "dev-settings.ncl", valid: true } ] ``` #### `set-current-workspace(path: string) -> null` Sets the current workspace for path resolution. **Parameters:** - `path`: Workspace directory path **Effects:** - Updates `CURRENT_INFRA_PATH` environment variable - Reconfigures workspace-relative path resolution ### Project Structure Analysis #### `analyze-project-structure(path: string = $PWD) -> record` Analyzes project structure and identifies components. **Parameters:** - `path`: Project root path (defaults to current directory) **Returns:** ```json { root: "/workspace/project", type: "provisioning_workspace", components: { providers: [ { name: "upcloud", path: "providers/upcloud" }, { name: "aws", path: "providers/aws" } ], taskservs: [ { name: "kubernetes", path: "taskservs/kubernetes" }, { name: "cilium", path: "taskservs/cilium" } ], clusters: [ { name: "buildkit", path: "cluster/buildkit" } ], infrastructure: [ { name: "production", path: "infra/production" }, { name: "staging", path: "infra/staging" } ] }, config_files: [ "config.defaults.toml", "config.user.toml", "config.prod.toml" ] } ``` ## Caching and Performance ### Path Caching The path resolution system includes intelligent caching: #### `cache-paths(duration: duration = 5 min) -> null` Enables path caching for the specified duration. **Parameters:** - `duration`: Cache validity duration #### `invalidate-path-cache() -> null` Invalidates the path resolution cache. #### `get-cache-stats() -> record` Gets path resolution cache statistics. **Returns:** ```json { enabled: true, size: 150, hit_rate: 0.85, last_invalidated: "2025-09-26T10:00:00Z" } ``` ## Cross-Platform Compatibility ### Path Normalization #### `normalize-path(path: string) -> string` Normalizes paths for cross-platform compatibility. **Parameters:** - `path`: Input path (may contain mixed separators) **Returns:** - Normalized path using platform-appropriate separators **Example:** ```bash # On Windows normalize-path "path/to/file" # Returns: "path\to\file" # On Unix normalize-path "path\to\file" # Returns: "path/to/file" ``` #### `join-paths(segments: list) -> string` Safely joins path segments using platform separators. **Parameters:** - `segments`: List of path segments **Returns:** - Joined path string ## Configuration Validation API ### Path Validation #### `validate-paths(config: record) -> record` Validates all paths in configuration. **Parameters:** - `config`: Configuration record **Returns:** ```json { valid: true, errors: [], warnings: [ { path: "paths.extensions", message: "Path does not exist" } ], checks_performed: 15 } ``` #### `validate-extension-structure(type: string, path: string) -> record` Validates extension directory structure. **Parameters:** - `type`: Extension type (provider, taskserv, cluster) - `path`: Extension base path **Returns:** ```json { valid: true, required_files: [ { file: "manifest.toml", exists: true }, { file: "schemas/main.ncl", exists: true }, { file: "nulib/mod.nu", exists: true } ], optional_files: [ { file: "templates/server.j2", exists: false } ] } ``` ## Command-Line Interface ### Path Resolution Commands The path resolution API is exposed via Nushell commands: ```nushell # Show current path configuration provisioning show paths # Discover available extensions provisioning discover providers provisioning discover taskservs provisioning discover clusters # Validate path configuration provisioning validate paths # Switch environments provisioning env switch prod # Set workspace provisioning workspace set /path/to/infra ``` ## Integration Examples ### Python Integration ```bash import subprocess import json class PathResolver: def __init__(self, provisioning_path="/usr/local/bin/provisioning"): self.cmd = provisioning_path def get_paths(self): result = subprocess.run([ "nu", "-c", f"use {self.cmd} *; show-config --section=paths --format=json" ], capture_output=True, text=True) return json.loads(result.stdout) def discover_providers(self): result = subprocess.run([ "nu", "-c", f"use {self.cmd} *; discover providers --format=json" ], capture_output=True, text=True) return json.loads(result.stdout) # Usage resolver = PathResolver() paths = resolver.get_paths() providers = resolver.discover_providers() ``` ### JavaScript/Node.js Integration ```javascript const { exec } = require('child_process'); const util = require('util'); const execAsync = util.promisify(exec); class PathResolver { constructor(provisioningPath = '/usr/local/bin/provisioning') { this.cmd = provisioningPath; } async getPaths() { const { stdout } = await execAsync( `nu -c "use ${this.cmd} *; show-config --section=paths --format=json"` ); return JSON.parse(stdout); } async discoverExtensions(type) { const { stdout } = await execAsync( `nu -c "use ${this.cmd} *; discover ${type} --format=json"` ); return JSON.parse(stdout); } } // Usage const resolver = new PathResolver(); const paths = await resolver.getPaths(); const providers = await resolver.discoverExtensions('providers'); ``` ## Error Handling ### Common Error Scenarios 1. **Configuration File Not Found** ```nushell Error: Configuration file not found in search paths Searched: ["/usr/local/provisioning/config.defaults.toml", ...] ``` 1. **Extension Not Found** ```nushell Error: Provider 'missing-provider' not found Available providers: ["upcloud", "aws", "local"] ``` 2. **Invalid Path Template** ```nushell Error: Invalid template variable: {{invalid.var}} Valid variables: ["paths.*", "env.*", "now.*", "git.*"] ``` 3. **Environment Not Found** ```nushell Error: Environment 'staging' not configured Available environments: ["dev", "test", "prod"] ``` ### Error Recovery The system provides graceful fallbacks: - Missing configuration files use system defaults - Invalid paths fall back to safe defaults - Extension discovery continues if some paths are inaccessible - Environment detection falls back to 'local' if detection fails ## Performance Considerations ### Best Practices 1. **Use Path Caching**: Enable caching for frequently accessed paths 2. **Batch Discovery**: Discover all extensions at once rather than individually 3. **Lazy Loading**: Load extension configurations only when needed 4. **Environment Detection**: Cache environment detection results ### Monitoring Monitor path resolution performance: ```bash # Get resolution statistics provisioning debug path-stats # Monitor cache performance provisioning debug cache-stats # Profile path resolution provisioning debug profile-paths ``` ## Security Considerations ### Path Traversal Protection The system includes protections against path traversal attacks: - All paths are normalized and validated - Relative paths are resolved within safe boundaries - Symlinks are validated before following ### Access Control Path resolution respects file system permissions: - Configuration files require read access - Extension directories require read/execute access - Workspace directories may require write access for operations This path resolution API provides a comprehensive and flexible system for managing the complex path requirements of multi-provider, multi-environment infrastructure provisioning.