provisioning/EXTENSIONS.md
2025-09-22 23:11:41 +01:00

7.0 KiB

Provisioning Extension System

The provisioning system supports extensions to add custom providers, task services, and access control without forking the main codebase.

Extension Architecture

Extension Discovery Paths

Extensions are loaded from multiple locations in priority order:

  1. Project-specific: .provisioning/extensions/ (highest priority)
  2. User-specific: ~/.provisioning-extensions/
  3. System-wide: /opt/provisioning-extensions/
  4. Environment: $PROVISIONING_EXTENSIONS_PATH

Extension Types

1. Providers

Custom cloud providers or infrastructure backends.

~/.provisioning-extensions/providers/
├── digitalocean/
│   ├── manifest.yaml
│   └── nulib/digitalocean/
│       ├── servers.nu
│       ├── env.nu
│       └── cache.nu
└── internal-cloud/
    ├── manifest.yaml
    └── nulib/internal-cloud/
        └── servers.nu

2. TaskServs

Custom task services for application deployment or system configuration.

~/.provisioning-extensions/taskservs/
├── custom-app/
│   ├── manifest.yaml
│   ├── production/
│   │   └── install-custom-app.sh
│   ├── staging/
│   │   └── install-custom-app.sh
│   └── development/
│       └── install-custom-app.sh
└── monitoring/
    ├── manifest.yaml
    └── default/
        └── install-monitoring.sh

3. Profiles

Access control profiles for restricted environments.

~/.provisioning-extensions/profiles/
├── cicd.yaml
├── developer.yaml
└── readonly.yaml

Extension Configuration

Environment Variables

Variable Description Default
PROVISIONING_EXTENSION_MODE Extension loading mode: full, restricted, disabled full
PROVISIONING_PROFILE Active access control profile "" (unrestricted)
PROVISIONING_EXTENSIONS_PATH Custom extension base path ""
PROVISIONING_ALLOWED_EXTENSIONS Comma-separated allowlist ""
PROVISIONING_BLOCKED_EXTENSIONS Comma-separated blocklist ""

Configuration via Context

Add to ~/.provisioning/context.yaml:

extension_mode: restricted
profile: cicd
allowed_extensions: "digitalocean,custom-app"
blocked_extensions: "aws,dangerous-taskserv"
extensions_path: "/custom/path/to/extensions"

Creating Extensions

Provider Extension

  1. Create directory structure:

    mkdir -p ~/.provisioning-extensions/providers/myprovider/nulib/myprovider
    
  2. Create manifest.yaml:

    name: myprovider
    version: 1.0.0
    type: provider
    description: My custom cloud provider
    requires:
      - mycloud-cli
    permissions:
      - network
      - compute
    hooks:
      pre_create: validate.nu
      post_create: notify.nu
    
  3. Implement provider functions in nulib/myprovider/servers.nu:

    export def myprovider_create_servers [settings: record, servers: table, check: bool, wait: bool] {
        # Implementation here
    }
    
    export def myprovider_delete_servers [settings: record, servers: table, check: bool] {
        # Implementation here
    }
    
    export def myprovider_query_servers [find: string, cols: string] {
        # Implementation here
    }
    
    export def myprovider_get_ip [settings: record, server: record, ip_type: string, fallback: bool] {
        # Implementation here
    }
    

TaskServ Extension

  1. Create directory structure:

    mkdir -p ~/.provisioning-extensions/taskservs/mytask/{production,staging,development}
    
  2. Create manifest.yaml:

    name: mytask
    version: 2.0.0
    type: taskserv
    description: My custom task service
    requires:
      - docker
      - kubectl
    profiles:
      - production
      - staging
      - development
    
  3. Create installation scripts:

    # ~/.provisioning-extensions/taskservs/mytask/production/install-mytask.sh
    #!/bin/bash
    echo "Installing mytask in production mode"
    # Implementation here
    

Profile Extension

Create ~/.provisioning-extensions/profiles/myprofile.yaml:

profile: myprofile
description: Custom access profile
restricted: true
allowed:
  commands: ["server list", "taskserv status"]
  providers: ["local", "myprovider"]
  taskservs: ["kubernetes", "mytask"]
blocked:
  commands: ["server delete", "sops"]
  providers: ["aws"]
  taskservs: ["postgres"]

Usage Examples

Using Custom Provider

# Enable extensions
export PROVISIONING_EXTENSION_MODE=full

# Use custom provider in settings.k
servers = [
    {
        hostname: "web-01"
        provider: "digitalocean"  # Custom provider
        region: "nyc1"
        size: "s-1vcpu-1gb"
    }
]

Restricted CI/CD Environment

# Set CI/CD profile
export PROVISIONING_PROFILE=cicd
export PROVISIONING_EXTENSION_MODE=restricted

# These commands work
provisioning server list          ✅
provisioning taskserv status      ✅

# These commands are blocked
provisioning server delete        ❌
provisioning sops edit secrets    ❌

Project-Specific Extensions

# In your project directory
mkdir -p .provisioning/extensions/taskservs/project-deploy/default
echo '#!/bin/bash\necho "Deploying project"' > .provisioning/extensions/taskservs/project-deploy/default/install-project-deploy.sh

# Use in taskservs
taskservs = [
    {
        name: "project-deploy"  # Automatically discovered
        profile: "default"
    }
]

Extension Management Commands

# List available extensions
provisioning extensions list

# Show extension details
provisioning extensions show digitalocean

# Validate extension
provisioning extensions validate ~/.provisioning-extensions/providers/myprovider

# Create example profiles
provisioning profiles create-examples

# Show current profile
provisioning profile show

Security Considerations

  1. Profile Enforcement: Use profiles in CI/CD to limit capabilities
  2. Extension Validation: Check manifests and requirements before loading
  3. Path Isolation: Extensions can't access core provisioning internals
  4. Permission System: Extensions declare required permissions
  5. Allowlist/Blocklist: Control which extensions can be loaded

Migration Guide

From Forked Provisioning

  1. Extract Custom Code: Move custom providers/taskservs to extension directories
  2. Create Manifests: Add manifest.yaml for each extension
  3. Update Configuration: Use environment variables instead of code changes
  4. Test Extensions: Verify functionality with extension system

Gradual Adoption

  1. Start Small: Begin with profile-based access control
  2. Move TaskServs: Migrate custom task services to extensions
  3. Add Providers: Create provider extensions as needed
  4. Full Migration: Remove forks and use pure extension system

This extension system allows the main provisioning project to remain clean and focused while providing unlimited customization capabilities.