provisioning/docs/src/development/providers/provider-distribution-guide.md

682 lines
17 KiB
Markdown
Raw Normal View History

2026-01-14 04:53:21 +00:00
# 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
```text
# 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
```text
# 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
```text
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
```text
# 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
```text
# 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
```text
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
```text
{
"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
```text
# 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
```text
# 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
```text
# 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
```text
# List all available providers
provisioning providers list [--kcl] [--format table|json|yaml]
# Show provider information
provisioning providers info <provider> [--kcl]
# Install provider for infrastructure
provisioning providers install <provider> <infra> [--version 0.0.1]
# Remove provider from infrastructure
provisioning providers remove <provider> <infra> [--force]
# List installed providers
provisioning providers installed <infra> [--format table|json|yaml]
# Validate provider installation
provisioning providers validate <infra>
# Sync KCL dependencies
./provisioning/core/cli/module-loader sync-kcl <infra>
```
### Provider Pack Commands
```text
# 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 <name> [--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
```text
# 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
```text
# 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)
```text
# 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
```text
# 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
```text
# 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:
```text
# 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:
```text
# 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
```text
# 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`:
```text
[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
```text
# 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
```text
# 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
```text
# 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
```text
# 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