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:
- Project-specific:
.provisioning/extensions/
(highest priority) - User-specific:
~/.provisioning-extensions/
- System-wide:
/opt/provisioning-extensions/
- 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
-
Create directory structure:
mkdir -p ~/.provisioning-extensions/providers/myprovider/nulib/myprovider
-
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
-
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
-
Create directory structure:
mkdir -p ~/.provisioning-extensions/taskservs/mytask/{production,staging,development}
-
Create manifest.yaml:
name: mytask version: 2.0.0 type: taskserv description: My custom task service requires: - docker - kubectl profiles: - production - staging - development
-
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
- Profile Enforcement: Use profiles in CI/CD to limit capabilities
- Extension Validation: Check manifests and requirements before loading
- Path Isolation: Extensions can't access core provisioning internals
- Permission System: Extensions declare required permissions
- Allowlist/Blocklist: Control which extensions can be loaded
Migration Guide
From Forked Provisioning
- Extract Custom Code: Move custom providers/taskservs to extension directories
- Create Manifests: Add
manifest.yaml
for each extension - Update Configuration: Use environment variables instead of code changes
- Test Extensions: Verify functionality with extension system
Gradual Adoption
- Start Small: Begin with profile-based access control
- Move TaskServs: Migrate custom task services to extensions
- Add Providers: Create provider extensions as needed
- 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.