# 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`: ```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**: ```bash mkdir -p ~/.provisioning-extensions/providers/myprovider/nulib/myprovider ``` 2. **Create manifest.yaml**: ```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`: ```nushell 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**: ```bash mkdir -p ~/.provisioning-extensions/taskservs/mytask/{production,staging,development} ``` 2. **Create manifest.yaml**: ```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**: ```bash # ~/.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`: ```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 ```bash # 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 ```bash # 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 ```bash # 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 ```bash # 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.