# Provider Distribution Guide **Strategic Guide for Provider Management and Distribution** This guide explains the two complementary approaches for managing providers in the provisioning system and when to use each. --- ## Table of Contents - [Overview](#overview) - [Module-Loader Approach](#module-loader-approach) - [Provider Packs Approach](#provider-packs-approach) - [Comparison Matrix](#comparison-matrix) - [Recommended Hybrid Workflow](#recommended-hybrid-workflow) - [Command Reference](#command-reference) - [Real-World Scenarios](#real-world-scenarios) - [Best Practices](#best-practices) --- ## Overview The provisioning system supports **two complementary approaches** for provider management: 1. **Module-Loader**: Symlink-based local development with dynamic discovery 2. **Provider Packs**: Versioned, distributable artifacts for production Both approaches work seamlessly together and serve different phases of the development lifecycle. --- ## Module-Loader Approach ### Purpose Fast, local development with direct access to provider source code. ### How It Works ```bash # Install provider for infrastructure (creates symlinks) provisioning providers install upcloud wuji # Internal Process: # 1. Discovers provider in extensions/providers/upcloud/ # 2. Creates symlink: workspace/infra/wuji/.nickel-modules/upcloud_prov -> extensions/providers/upcloud/nickel/ # 3. Updates workspace/infra/wuji/manifest.toml with local path dependency # 4. Updates workspace/infra/wuji/providers.manifest.yaml ``` ### Key Features ✅ **Instant Changes**: Edit code in `extensions/providers/`, immediately available in infrastructure ✅ **Auto-Discovery**: Automatically finds all providers in extensions/ ✅ **Simple Commands**: `providers install/remove/list/validate` ✅ **Easy Debugging**: Direct access to source code ✅ **No Packaging**: Skip build/package step during development ### Best Use Cases - 🔧 **Active Development**: Writing new provider features - 🧪 **Testing**: Rapid iteration and testing cycles - 🏠 **Local Infrastructure**: Single machine or small team - 📝 **Debugging**: Need to modify and test provider code - 🎓 **Learning**: Understanding how providers work ### Example Workflow ```bash # 1. List available providers provisioning providers list # 2. Install provider for infrastructure provisioning providers install upcloud wuji # 3. Verify installation provisioning providers validate wuji # 4. Edit provider code vim extensions/providers/upcloud/nickel/server_upcloud.ncl # 5. Test changes immediately (no repackaging!) cd workspace/infra/wuji nickel export main.ncl # 6. Remove when done provisioning providers remove upcloud wuji ``` ### File Structure ```bash extensions/providers/upcloud/ ├── nickel/ │ ├── manifest.toml │ ├── server_upcloud.ncl │ └── network_upcloud.ncl └── README.md workspace/infra/wuji/ ├── .nickel-modules/ │ └── upcloud_prov -> ../../../../extensions/providers/upcloud/nickel/ # Symlink ├── manifest.toml # Updated with local path dependency ├── providers.manifest.yaml # Tracks installed providers └── schemas/ └── servers.ncl ``` --- ## Provider Packs Approach ### Purpose Create versioned, distributable artifacts for production deployments and team collaboration. ### How It Works ```bash # Package providers into distributable artifacts export PROVISIONING=/Users/Akasha/project-provisioning/provisioning ./provisioning/core/cli/pack providers # Internal Process: # 1. Enters each provider's nickel/ directory # 2. Runs: nickel export . --format json (generates JSON for distribution) # 3. Creates: upcloud_prov_0.0.1.tar # 4. Generates metadata: distribution/registry/upcloud_prov.json ``` ### Key Features ✅ **Versioned Artifacts**: Immutable, reproducible packages ✅ **Portable**: Share across teams and environments ✅ **Registry Publishing**: Push to artifact registries ✅ **Metadata**: Version, maintainer, license information ✅ **Production-Ready**: What you package is what you deploy ### Best Use Cases - 🚀 **Production Deployments**: Stable, tested provider versions - 📦 **Distribution**: Share across teams or organizations - 🔄 **CI/CD Pipelines**: Automated build and deploy - 📊 **Version Control**: Track provider versions explicitly - 🌐 **Registry Publishing**: Publish to artifact registries - 🔒 **Compliance**: Immutable artifacts for auditing ### Example Workflow ```bash # Set environment variable export PROVISIONING=/Users/Akasha/project-provisioning/provisioning # 1. Package all providers ./provisioning/core/cli/pack providers # Output: # ✅ Creates: distribution/packages/upcloud_prov_0.0.1.tar # ✅ Creates: distribution/packages/aws_prov_0.0.1.tar # ✅ Creates: distribution/packages/local_prov_0.0.1.tar # ✅ Metadata: distribution/registry/*.json # 2. List packaged modules ./provisioning/core/cli/pack list # 3. Package only core schemas ./provisioning/core/cli/pack core # 4. Clean old packages (keep latest 3 versions) ./provisioning/core/cli/pack clean --keep-latest 3 # 5. Upload to registry (your implementation) # rsync distribution/packages/*.tar repo.jesusperez.pro:/registry/ ``` ### File Structure ```bash provisioning/ ├── distribution/ │ ├── packages/ │ │ ├── provisioning_0.0.1.tar # Core schemas │ │ ├── upcloud_prov_0.0.1.tar # Provider packages │ │ ├── aws_prov_0.0.1.tar │ │ └── local_prov_0.0.1.tar │ └── registry/ │ ├── provisioning_core.json # Metadata │ ├── upcloud_prov.json │ ├── aws_prov.json │ └── local_prov.json └── extensions/providers/ # Source code ``` ### Package Metadata Example ```json { "name": "upcloud_prov", "version": "0.0.1", "package_file": "/path/to/upcloud_prov_0.0.1.tar", "created": "2025-09-29 20:47:21", "maintainer": "JesusPerezLorenzo", "repository": "https://repo.jesusperez.pro/provisioning", "license": "MIT", "homepage": "https://github.com/jesusperezlorenzo/provisioning" } ``` --- ## Comparison Matrix | Feature | Module-Loader | Provider Packs | | --------- | -------------- | ---------------- | | **Speed** | ⚡ Instant (symlinks) | 📦 Requires packaging | | **Versioning** | ❌ No explicit versions | ✅ Semantic versioning | | **Portability** | ❌ Local filesystem only | ✅ Distributable archives | | **Development** | ✅ Excellent (live reload) | ⚠️ Need repackage cycle | | **Production** | ⚠️ Mutable source | ✅ Immutable artifacts | | **Discovery** | ✅ Auto-discovery | ⚠️ Manual tracking | | **Team Sharing** | ⚠️ Git repository only | ✅ Registry + Git | | **Debugging** | ✅ Direct source access | ❌ Need to unpack | | **Rollback** | ⚠️ Git revert | ✅ Version pinning | | **Compliance** | ❌ Hard to audit | ✅ Signed artifacts | | **Setup Time** | ⚡ Seconds | ⏱️ Minutes | | **CI/CD** | ⚠️ Not ideal | ✅ Perfect | --- ## Recommended Hybrid Workflow ### Development Phase ```bash # 1. Start with module-loader for development provisioning providers list provisioning providers install upcloud wuji # 2. Develop and iterate quickly vim extensions/providers/upcloud/nickel/server_upcloud.ncl # Test immediately - no packaging needed # 3. Validate before release provisioning providers validate wuji nickel export workspace/infra/wuji/main.ncl ``` ### Release Phase ```bash # 4. Create release packages export PROVISIONING=/Users/Akasha/project-provisioning/provisioning ./provisioning/core/cli/pack providers # 5. Verify packages ./provisioning/core/cli/pack list # 6. Tag release git tag v0.0.2 git push origin v0.0.2 # 7. Publish to registry (your workflow) rsync distribution/packages/*.tar user@repo.jesusperez.pro:/registry/v0.0.2/ ``` ### Production Deployment ```bash # 8. Download specific version from registry wget https://repo.jesusperez.pro/registry/v0.0.2/upcloud_prov_0.0.2.tar # 9. Extract and install tar -xf upcloud_prov_0.0.2.tar -C infrastructure/providers/ # 10. Use in production infrastructure # (Configure manifest.toml to point to extracted package) ``` --- ## Command Reference ### Module-Loader Commands ```bash # List all available providers provisioning providers list [--kcl] [--format table|json|yaml] # Show provider information provisioning providers info [--kcl] # Install provider for infrastructure provisioning providers install [--version 0.0.1] # Remove provider from infrastructure provisioning providers remove [--force] # List installed providers provisioning providers installed [--format table|json|yaml] # Validate provider installation provisioning providers validate # Sync KCL dependencies ./provisioning/core/cli/module-loader sync-kcl ``` ### Provider Pack Commands ```bash # Set environment variable (required) export PROVISIONING=/path/to/provisioning # Package core provisioning schemas ./provisioning/core/cli/pack core [--output dir] [--version 0.0.1] # Package single provider ./provisioning/core/cli/pack provider [--output dir] [--version 0.0.1] # Package all providers ./provisioning/core/cli/pack providers [--output dir] # List all packages ./provisioning/core/cli/pack list [--format table|json|yaml] # Clean old packages ./provisioning/core/cli/pack clean [--keep-latest 3] [--dry-run] ``` --- ## Real-World Scenarios ### Scenario 1: Solo Developer - Local Infrastructure **Situation**: Working alone on local infrastructure projects **Recommendation**: Module-Loader only ```bash # Simple and fast providers install upcloud homelab providers install aws cloud-backup # Edit and test freely ``` **Why**: No need for versioning, packaging overhead unnecessary. --- ### Scenario 2: Small Team - Shared Development **Situation**: 2-5 developers sharing code via Git **Recommendation**: Module-Loader + Git ```bash # Each developer git clone repo providers install upcloud project-x # Make changes, commit to Git git commit -m "Add upcloud GPU support" git push # Others pull changes git pull # Changes immediately available via symlinks ``` **Why**: Git provides version control, symlinks provide instant updates. --- ### Scenario 3: Medium Team - Multiple Projects **Situation**: 10+ developers, multiple infrastructure projects **Recommendation**: Hybrid (Module-Loader dev + Provider Packs releases) ```bash # Development (team member) providers install upcloud staging-env # Make changes... # Release (release engineer) pack providers # Create v0.2.0 git tag v0.2.0 # Upload to internal registry # Other projects # Download upcloud_prov_0.2.0.tar # Use stable, tested version ``` **Why**: Developers iterate fast, other teams use stable versions. --- ### Scenario 4: Enterprise - Production Infrastructure **Situation**: Critical production systems, compliance requirements **Recommendation**: Provider Packs only ```bash # CI/CD Pipeline pack providers # Build artifacts # Run tests on packages # Sign packages # Publish to artifact registry # Production Deployment # Download signed upcloud_prov_1.0.0.tar # Verify signature # Deploy immutable artifact # Document exact versions for compliance ``` **Why**: Immutability, auditability, and rollback capabilities required. --- ### Scenario 5: Open Source - Public Distribution **Situation**: Sharing providers with community **Recommendation**: Provider Packs + Registry ```bash # Maintainer pack providers # Create release on GitHub gh release create v1.0.0 distribution/packages/*.tar # Community User # Download from GitHub releases wget https://github.com/project/releases/v1.0.0/upcloud_prov_1.0.0.tar # Extract and use ``` **Why**: Easy distribution, versioning, and downloading for users. --- ## Best Practices ### For Development 1. **Use Module-Loader by default** - Fast iteration is crucial during development - Symlinks allow immediate testing 2. **Keep providers.manifest.yaml in Git** - Documents which providers are used - Team members can sync easily 3. **Validate before committing** ```bash providers validate wuji nickel eval defs/servers.ncl ``` ### For Releases 1. **Version Everything** - Use semantic versioning (0.1.0, 0.2.0, 1.0.0) - Update version in kcl.mod before packing 2. **Create Packs for Releases** ```bash pack providers --version 0.2.0 git tag v0.2.0 ``` 3. **Test Packs Before Publishing** - Extract and test packages - Verify metadata is correct ### For Production 1. **Pin Versions** - Use exact versions in production kcl.mod - Never use "latest" or symlinks 2. **Maintain Artifact Registry** - Store all production versions - Keep old versions for rollback 3. **Document Deployments** - Record which versions deployed when - Maintain change log ### For CI/CD 1. **Automate Pack Creation** ```yaml # .github/workflows/release.yml - name: Pack Providers run: | export PROVISIONING=$GITHUB_WORKSPACE/provisioning ./provisioning/core/cli/pack providers ``` 2. **Run Tests on Packs** - Extract packages - Run validation tests - Ensure they work in isolation 3. **Publish Automatically** - Upload to artifact registry on tag - Update package index --- ## Migration Path ### From Module-Loader to Packs When you're ready to move to production: ```bash # 1. Clean up development setup providers remove upcloud wuji # 2. Create release pack pack providers --version 1.0.0 # 3. Extract pack in infrastructure cd workspace/infra/wuji tar -xf ../../../distribution/packages/upcloud_prov_1.0.0.tar vendor/ # 4. Update kcl.mod to use vendored path # Change from: upcloud_prov = { path = "./.kcl-modules/upcloud_prov" } # To: upcloud_prov = { path = "./vendor/upcloud_prov", version = "1.0.0" } # 5. Test nickel eval defs/servers.ncl ``` ### From Packs Back to Module-Loader When you need to debug or develop: ```bash # 1. Remove vendored version rm -rf workspace/infra/wuji/vendor/upcloud_prov # 2. Install via module-loader providers install upcloud wuji # 3. Make changes in extensions/providers/upcloud/kcl/ # 4. Test immediately cd workspace/infra/wuji nickel eval defs/servers.ncl ``` --- ## Configuration ### Environment Variables ```bash # Required for pack commands export PROVISIONING=/path/to/provisioning # Alternative export PROVISIONING_CONFIG=/path/to/provisioning ``` ### Config Files Distribution settings in `provisioning/config/config.defaults.toml`: ```toml [distribution] pack_path = "{{paths.base}}/distribution/packages" registry_path = "{{paths.base}}/distribution/registry" cache_path = "{{paths.base}}/distribution/cache" registry_type = "local" [distribution.metadata] maintainer = "JesusPerezLorenzo" repository = "https://repo.jesusperez.pro/provisioning" license = "MIT" homepage = "https://github.com/jesusperezlorenzo/provisioning" [kcl] core_module = "{{paths.base}}/kcl" core_version = "0.0.1" core_package_name = "provisioning_core" use_module_loader = true modules_dir = ".kcl-modules" ``` --- ## Troubleshooting ### Module-Loader Issues **Problem**: Provider not found after install ```bash # Check provider exists providers list | grep upcloud # Validate installation providers validate wuji # Check symlink ls -la workspace/infra/wuji/.kcl-modules/ ``` **Problem**: Changes not reflected ```bash # Verify symlink is correct readlink workspace/infra/wuji/.kcl-modules/upcloud_prov # Should point to extensions/providers/upcloud/kcl/ ``` ### Provider Pack Issues **Problem**: No .tar file created ```bash # Check KCL version (need 0.11.3+) kcl version # Check kcl.mod exists ls extensions/providers/upcloud/kcl/kcl.mod ``` **Problem**: PROVISIONING environment variable not set ```bash # Set it export PROVISIONING=/Users/Akasha/project-provisioning/provisioning # Or add to shell profile echo 'export PROVISIONING=/path/to/provisioning' >> ~/.zshrc ``` --- ## Conclusion **Both approaches are valuable and complementary:** - **Module-Loader**: Development velocity, rapid iteration - **Provider Packs**: Production stability, version control **Default Strategy:** - Use **Module-Loader** for day-to-day development - Create **Provider Packs** for releases and production - Both systems work seamlessly together **The system is designed for flexibility** - choose the right tool for your current phase of work! --- ## Additional Resources - [Module-Loader Implementation](../provisioning/core/nulib/lib_provisioning/kcl_module_loader.nu) - [KCL Packaging Implementation](../provisioning/core/nulib/lib_provisioning/kcl_packaging.nu) - [Providers CLI](.provisioning providers) - [Pack CLI](../provisioning/core/cli/pack) - [KCL Documentation](https://kcl-lang.io/) --- **Document Version**: 1.0.0 **Last Updated**: 2025-09-29 **Maintained by**: JesusPerezLorenzo