16 KiB
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:
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:
# 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>) -> 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:
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:
{
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:
{
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 variablescontext: Variable context record
Example:
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<record>
Discovers all available providers.
Returns:
[
{
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:
{
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<record>
Discovers all available task services.
Returns:
[
{
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:
{
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<record>
Discovers all available cluster configurations.
Returns:
[
{
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:
PROVISIONING_ENVenvironment variable- Git branch patterns (main → prod, develop → dev, etc.)
- Directory structure analysis
- 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:
{
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 namevalidate: Whether to validate environment configuration
Effects:
- Updates
PROVISIONING_ENVenvironment variable - Reconfigures path resolution for new environment
- Validates environment configuration if requested
Workspace Management API
Workspace Discovery
discover-workspaces() -> list<record>
Discovers available workspaces and infrastructure directories.
Returns:
[
{
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_PATHenvironment 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:
{
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:
{
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:
# 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>) -> 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:
{
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:
{
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:
# 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
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
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
-
Configuration File Not Found
Error: Configuration file not found in search paths Searched: ["/usr/local/provisioning/config.defaults.toml", ...] -
Extension Not Found
Error: Provider 'missing-provider' not found Available providers: ["upcloud", "aws", "local"] -
Invalid Path Template
Error: Invalid template variable: {{invalid.var}} Valid variables: ["paths.*", "env.*", "now.*", "git.*"] -
Environment Not Found
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
- Use Path Caching: Enable caching for frequently accessed paths
- Batch Discovery: Discover all extensions at once rather than individually
- Lazy Loading: Load extension configurations only when needed
- Environment Detection: Cache environment detection results
Monitoring
Monitor path resolution performance:
# 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.