# 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
```plaintext

### 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
```plaintext

### File Structure

```plaintext
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
```plaintext

---

## 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
```plaintext

### 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/
```plaintext

### File Structure

```plaintext
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
```plaintext

### 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"
}
```plaintext

---

## 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
```plaintext

### 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/
```plaintext

### 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)
```plaintext

---

## Command Reference

### Module-Loader Commands

```bash
# 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>
```plaintext

### 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 <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]
```plaintext

---

## 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
```plaintext

**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
```plaintext

**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
```plaintext

**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
```plaintext

**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
```plaintext

**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
```plaintext

### 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
```plaintext

---

## Configuration

### Environment Variables

```bash
# Required for pack commands
export PROVISIONING=/path/to/provisioning

# Alternative
export PROVISIONING_CONFIG=/path/to/provisioning
```plaintext

### 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"
```plaintext

---

## 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/
```plaintext

**Problem**: Changes not reflected

```bash
# Verify symlink is correct
readlink workspace/infra/wuji/.kcl-modules/upcloud_prov

# Should point to extensions/providers/upcloud/kcl/
```plaintext

### 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
```plaintext

**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
```plaintext

---

## 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
