# Extension Loading System **Version**: 1.0.0 **Status**: Implemented **Date**: 2025-10-06 ## Overview A comprehensive extension loading mechanism with OCI registry support, lazy loading, caching, and version resolution. Supports loading extensions from multiple sources: OCI registries, Gitea repositories, and local filesystems. ## Architecture ``` Extension Loading System ├── OCI Client (oci/client.nu) │ ├── Artifact pull/push operations │ ├── Registry authentication │ └── Manifest management ├── Cache System (cache.nu) │ ├── Local artifact caching │ ├── Cache index management │ └── Automatic pruning ├── Loader (loader_oci.nu) │ ├── Multi-source loading │ ├── Lazy loading │ └── Automatic source detection ├── Version Resolution (versions.nu) │ ├── Semver parsing and comparison │ ├── Constraint satisfaction (^, ~, ranges) │ └── OCI tag resolution ├── Discovery (discovery.nu) │ ├── Multi-source discovery │ ├── Extension search │ └── Metadata extraction └── CLI Commands (commands.nu) ├── Load, search, list ├── Cache management └── Publishing ``` ## Features ### 1. Multi-Source Support Load extensions from: - **OCI Registry**: Container artifact registry (localhost:5000 by default) - **Gitea**: Git repository hosting (planned) - **Local**: Filesystem paths ### 2. Lazy Loading Extensions are loaded on-demand: 1. Check if already in memory → return 2. Check cache → load from cache 3. Determine source (auto-detect or explicit) 4. Download from source 5. Cache locally 6. Load into memory ### 3. OCI Registry Integration Full OCI artifact support: - Pull artifacts with authentication - Push extensions to registry - List and search artifacts - Version tag management - Manifest metadata extraction ### 4. Caching System Intelligent local caching: - Cache directory: `~/.provisioning/cache/extensions/{type}/{name}/{version}/` - Cache index: JSON-based index for fast lookups - Automatic pruning: Remove old cached versions - Statistics: Track cache size and usage ### 5. Version Resolution Semver-compliant version resolution: - **Exact**: `1.2.3` → exactly version 1.2.3 - **Caret**: `^1.2.0` → >=1.2.0 <2.0.0 (compatible) - **Tilde**: `~1.2.0` → >=1.2.0 <1.3.0 (approximately) - **Range**: `1.2.0-1.5.0` → between versions - **Latest**: `*` or `latest` → highest version ### 6. Discovery & Search Multi-source extension discovery: - Discover all extensions across sources - Search by name or type - Filter by extension type (provider, taskserv, cluster) - Get available versions ## Configuration ### OCI Registry Configuration Add to workspace config (`workspace/config/local-overrides.toml`): ```toml [oci] registry = "localhost:5000" namespace = "provisioning-extensions" auth_token_path = "~/.provisioning/oci-token" insecure = false timeout = 300 retry_count = 3 [extensions] source_type = "auto" # auto, oci, gitea, local ``` ### Environment Variables - `PROVISIONING_OCI_REGISTRY`: Override OCI registry - `PROVISIONING_OCI_NAMESPACE`: Override namespace - `PROVISIONING_EXTENSIONS_PATH`: Additional extension paths ## CLI Usage ### Load Extension ```bash # Load latest from auto-detected source provisioning ext load kubernetes # Load specific version from OCI provisioning ext load kubernetes --version 1.28.0 --source oci # Force reload provisioning ext load kubernetes --force # Load provider provisioning ext load aws --type provider ``` ### Search Extensions ```bash # Search all sources provisioning ext search kubernetes # Search OCI registry only provisioning ext search kubernetes --source oci # Search local only provisioning ext search kube --source local ``` ### List Extensions ```bash # List all extensions provisioning ext list # Filter by type provisioning ext list --type taskserv # JSON output provisioning ext list --format json # List from specific source provisioning ext list --source oci ``` ### Extension Information ```bash # Show extension info provisioning ext info kubernetes # Show specific version provisioning ext info kubernetes --version 1.28.0 # Show versions provisioning ext versions kubernetes ``` ### Cache Management ```bash # List cached extensions provisioning ext cache list # Show cache statistics provisioning ext cache stats # Clear cache for specific extension provisioning ext cache clear --type taskserv --name kubernetes # Clear all cache provisioning ext cache clear --all # Prune old entries (older than 30 days) provisioning ext cache prune --days 30 ``` ### Pull to Cache ```bash # Pull without loading provisioning ext pull kubernetes --version 1.28.0 # Pull from specific source provisioning ext pull redis --source oci ``` ### Publishing ```bash # Publish to OCI registry provisioning ext publish ./my-extension --version 1.0.0 # Publish to specific registry provisioning ext publish ./my-extension \ --version 1.0.0 \ --registry localhost:5000 \ --namespace my-namespace # Force overwrite existing provisioning ext publish ./my-extension --version 1.0.0 --force ``` ### Discovery ```bash # Discover all extensions provisioning ext discover # Filter by type provisioning ext discover --type taskserv # Force refresh provisioning ext discover --refresh ``` ### Test OCI Connection ```bash # Test OCI registry connectivity provisioning ext test-oci ``` ## Publishing Tool Usage The standalone publishing tool provides additional commands: ```bash # Publish extension nu provisioning/tools/publish_extension.nu ./my-extension --version 1.0.0 # Dry run (validate without publishing) nu provisioning/tools/publish_extension.nu ./my-extension --version 1.0.0 --dry-run # List published extensions nu provisioning/tools/publish_extension.nu list # Show extension info nu provisioning/tools/publish_extension.nu info kubernetes 1.28.0 # Delete extension nu provisioning/tools/publish_extension.nu delete kubernetes 1.28.0 --force ``` ## Extension Structure ### Required Files ``` my-extension/ ├── extension.yaml # Manifest (required) ├── kcl/ # KCL schemas (optional) │ ├── my-extension.k │ └── kcl.mod ├── scripts/ # Scripts (optional) │ └── install.nu ├── templates/ # Templates (optional) │ └── config.yaml.j2 └── docs/ # Documentation (optional) └── README.md ``` ### Extension Manifest (extension.yaml) ```yaml extension: name: my-extension version: 1.0.0 type: taskserv # provider, taskserv, cluster description: My awesome extension author: Your Name requires: - docker - kubernetes dependencies: - containerd - etcd metadata: homepage: https://example.com repository: https://github.com/user/extension license: MIT ``` ## API Reference ### OCI Client (oci/client.nu) | Function | Description | |----------|-------------| | `oci-pull-artifact` | Pull artifact from OCI registry | | `oci-push-artifact` | Push artifact to OCI registry | | `oci-list-artifacts` | List all artifacts in registry | | `oci-get-artifact-tags` | Get tags for artifact | | `oci-get-artifact-manifest` | Get manifest for artifact | | `oci-artifact-exists` | Check if artifact exists | | `oci-delete-artifact` | Delete artifact from registry | | `is-oci-available` | Check OCI registry availability | | `test-oci-connection` | Test connection and auth | ### Cache System (cache.nu) | Function | Description | |----------|-------------| | `get-from-cache` | Get extension from cache | | `save-oci-to-cache` | Save OCI artifact to cache | | `save-gitea-to-cache` | Save Gitea artifact to cache | | `remove-from-cache` | Remove from cache | | `clear-cache` | Clear entire cache or specific type | | `list-cached` | List cached extensions | | `get-cache-stats` | Get cache statistics | | `prune-cache` | Remove old cache entries | ### Loader (loader_oci.nu) | Function | Description | |----------|-------------| | `load-extension` | Load extension from any source | ### Version Resolution (versions.nu) | Function | Description | |----------|-------------| | `resolve-version` | Resolve version from spec | | `resolve-oci-version` | Resolve from OCI tags | | `is-semver` | Check if valid semver | | `compare-semver` | Compare two versions | | `sort-by-semver` | Sort versions | | `get-latest-version` | Get latest from list | | `satisfies-constraint` | Check constraint satisfaction | ### Discovery (discovery.nu) | Function | Description | |----------|-------------| | `discover-oci-extensions` | Discover OCI extensions | | `discover-local-extensions` | Discover local extensions | | `discover-all-extensions` | Discover from all sources | | `search-extensions` | Search extensions | | `list-extensions` | List with formatting | | `get-extension-versions` | Get available versions | | `get-oci-extension-metadata` | Get OCI metadata | ## Testing Run the test suite: ```bash # Run all tests nu provisioning/core/nulib/lib_provisioning/extensions/tests/run_all_tests.nu # Run specific test suite nu provisioning/core/nulib/lib_provisioning/extensions/tests/run_all_tests.nu --suite oci nu provisioning/core/nulib/lib_provisioning/extensions/tests/run_all_tests.nu --suite cache nu provisioning/core/nulib/lib_provisioning/extensions/tests/run_all_tests.nu --suite versions nu provisioning/core/nulib/lib_provisioning/extensions/tests/run_all_tests.nu --suite discovery # Run individual test nu provisioning/core/nulib/lib_provisioning/extensions/tests/test_oci_client.nu nu provisioning/core/nulib/lib_provisioning/extensions/tests/test_cache.nu nu provisioning/core/nulib/lib_provisioning/extensions/tests/test_versions.nu nu provisioning/core/nulib/lib_provisioning/extensions/tests/test_discovery.nu ``` ## Integration Examples ### Example 1: Load Taskserv from OCI ```nushell use lib_provisioning/extensions/loader_oci.nu load-extension let result = (load-extension "taskserv" "kubernetes" "^1.28.0" --source-type "oci") if $result.success { print $"Loaded kubernetes:($result.version) from ($result.source)" } else { print $"Failed: ($result.error)" } ``` ### Example 2: Discover and Cache All Extensions ```nushell use lib_provisioning/extensions/discovery.nu discover-all-extensions use lib_provisioning/extensions/loader_oci.nu load-extension let extensions = (discover-all-extensions --include-oci) for ext in $extensions { print $"Caching ($ext.name):($ext.latest)..." load-extension $ext.type $ext.name $ext.latest } ``` ### Example 3: Version Resolution ```nushell use lib_provisioning/extensions/versions.nu resolve-oci-version let version = (resolve-oci-version "taskserv" "kubernetes" "^1.28.0") print $"Resolved to: ($version)" ``` ## Troubleshooting ### OCI Registry Not Reachable ```bash # Test connection provisioning ext test-oci # Check config provisioning env | grep OCI # Verify registry is running curl http://localhost:5000/v2/ ``` ### Extension Not Found ```bash # Search all sources provisioning ext search # Check specific source provisioning ext list --source oci provisioning ext list --source local # Discover with refresh provisioning ext discover --refresh ``` ### Cache Issues ```bash # Check cache stats provisioning ext cache stats # Clear and rebuild provisioning ext cache clear --all # Prune old entries provisioning ext cache prune --days 7 ``` ### Version Resolution Issues ```bash # Check available versions provisioning ext versions # Try explicit version provisioning ext load --version 1.2.3 # Force reload provisioning ext load --force ``` ## Performance Considerations - **Lazy Loading**: Extensions loaded on-demand, not at startup - **Caching**: Downloaded artifacts cached locally for fast access - **Parallel Discovery**: Multiple sources discovered concurrently - **Index-Based Lookup**: Cache index for O(1) lookups ## Security - **Token-Based Auth**: OCI registry authentication via tokens - **Manifest Validation**: Extension structure validated before loading - **Permission Checks**: Extension permission policies enforced - **Secure Defaults**: HTTPS for registries (HTTP only for localhost) ## Future Enhancements - [ ] Gitea source implementation - [ ] Digital signature verification - [ ] Multi-registry support - [ ] Extension dependency resolution - [ ] Automatic updates - [ ] Extension sandboxing - [ ] WebAssembly extensions - [ ] Extension marketplace UI ## Contributing See main project contributing guidelines. Extension system follows: - Nushell idiomatic patterns - PAP (Project Architecture Principles) - KCL idiomatic patterns for schemas ## License Same as main project.