Update configuration files, templates, and internal documentation for the provisioning repository system. Configuration Updates: - KMS configuration modernization - Plugin system settings - Service port mappings - Test cluster topologies - Installation configuration examples - VM configuration defaults - Cedar authorization policies Documentation Updates: - Library module documentation - Extension API guides - AI system documentation - Service management guides - Test environment setup - Plugin usage guides - Validator configuration documentation All changes are backward compatible.
439 lines
12 KiB
Markdown
439 lines
12 KiB
Markdown
# Configuration Templates
|
|
|
|
**Purpose**: Template files for generating workspace configurations
|
|
|
|
## Template Extension Conventions
|
|
|
|
This project uses **TWO template extensions** for different purposes:
|
|
|
|
### `.template` Extension (This Directory)
|
|
|
|
- **Purpose**: Workspace initialization only
|
|
- **Engine**: Simple string substitution (`{{variable}}`)
|
|
- **Usage**: One-time generation during workspace creation
|
|
- **Dependency**: None (no plugins required)
|
|
- **Complexity**: Low (no loops/conditionals needed)
|
|
|
|
**Example**:
|
|
```yaml
|
|
workspace:
|
|
name: "{{workspace.name}}"
|
|
created: "{{now.iso}}"
|
|
```
|
|
|
|
**When to use**:
|
|
- Workspace initialization templates
|
|
- One-time setup files
|
|
- No dynamic logic needed
|
|
|
|
### `.j2` Extension (Rest of Codebase)
|
|
|
|
- **Purpose**: Runtime configuration generation
|
|
- **Engine**: Jinja2 (via `nu_plugin_tera`)
|
|
- **Usage**: Dynamic config rendering during operations
|
|
- **Dependency**: Requires `nu_plugin_tera` plugin
|
|
- **Complexity**: High (conditionals, loops, filters)
|
|
|
|
**Example**:
|
|
```jinja2
|
|
{%- if taskserv.mode == "ha" %}
|
|
REPLICAS={{taskserv.replicas}}
|
|
{%- endif %}
|
|
|
|
{% for node in cluster.nodes -%}
|
|
NODE_{{loop.index}}={{node.hostname}}
|
|
{% endfor %}
|
|
```
|
|
|
|
**When to use**:
|
|
- Runtime configuration generation
|
|
- Dynamic values from environment
|
|
- Complex logic (conditionals, loops)
|
|
|
|
### Why Two Extensions?
|
|
|
|
1. **Separation of Concerns**: Init and runtime are fundamentally different operations
|
|
- Init happens once during workspace creation
|
|
- Runtime happens continuously during operations
|
|
|
|
2. **No Plugin Dependency for Init**: Workspace creation works without external plugins
|
|
- Simple string replacement is sufficient for initialization
|
|
- `nu_plugin_tera` is only needed for runtime rendering
|
|
- Initialization is more portable and reliable
|
|
|
|
3. **Semantic Clarity**: Extension signals the purpose immediately
|
|
- Developers see `.template` and know: "This is for initialization"
|
|
- Developers see `.j2` and know: "This is for runtime rendering"
|
|
- No ambiguity about usage context
|
|
|
|
4. **Appropriate Complexity**: Each extension matches its use case
|
|
- Init templates don't need loops/conditionals (simple substitution is enough)
|
|
- Runtime templates need full Jinja2 power (conditionals, loops, filters)
|
|
- Using the right tool for the job
|
|
|
|
### Codebase Statistics
|
|
|
|
**Template Distribution**:
|
|
- `.j2` templates: 134 files (88%) - Runtime generation
|
|
- `.template` templates: 16 files (10%) - Workspace initialization
|
|
- `.tera` templates: 3 files (2%) - Plugin examples
|
|
|
|
The two-tier system reflects the actual use case distribution in the codebase.
|
|
|
|
## KCL Module Structure
|
|
|
|
Workspaces use a **clear directory structure for KCL modules**:
|
|
|
|
```
|
|
workspace/
|
|
├── config/
|
|
│ ├── kcl.mod # Workspace package, imports provisioning from ../.kcl
|
|
│ └── provisioning.k # Workspace-specific config overrides (SST pattern)
|
|
├── .provisioning/ # Metadata only
|
|
│ └── metadata.yaml # Workspace metadata and version info
|
|
└── .kcl/ # Main KCL package "provisioning"
|
|
├── kcl.mod # Package definition
|
|
├── workspace_config.k # Schema definitions (SST)
|
|
├── workspace_config_defaults.k # Default values (SST)
|
|
├── batch.k
|
|
├── cluster.k
|
|
└── ... other KCL modules
|
|
```
|
|
|
|
### Directory Purposes
|
|
|
|
| Directory | Purpose | Contents |
|
|
|-----------|---------|----------|
|
|
| `.provisioning/` | **Metadata only** | `metadata.yaml` - workspace versioning and compatibility |
|
|
| `.kcl/` | **KCL modules** | All KCL configuration files and schemas |
|
|
| `config/` | **Workspace config** | Runtime configuration files generated from templates |
|
|
|
|
### SST Pattern (Single Source of Truth)
|
|
|
|
Workspace configuration follows the SST pattern:
|
|
1. **Schema** (`.kcl/workspace_config.k`) - Type-safe schema definitions
|
|
2. **Defaults** (`.kcl/workspace_config_defaults.k`) - Base default values
|
|
3. **Overrides** (`config/provisioning.k`) - Workspace-specific customizations
|
|
|
|
**Never edit** `.provisioning/workspace_config.k` or `.provisioning/workspace_config_defaults.k` - they are copies only.
|
|
**Always edit** in `.kcl/` directory instead.
|
|
|
|
## Important
|
|
|
|
**These files are TEMPLATES ONLY. They are NEVER loaded at runtime.**
|
|
|
|
The provisioning system generates workspace configurations from these templates during workspace initialization. Once generated, the workspace uses its own `config/provisioning.yaml` and related configs.
|
|
|
|
## Available Templates
|
|
|
|
### 1. workspace-provisioning.yaml.template
|
|
|
|
Main workspace configuration template. Generates: `{workspace}/config/provisioning.yaml`
|
|
|
|
**Variables:**
|
|
- `{{workspace.name}}` - Workspace name
|
|
- `{{workspace.path}}` - Absolute workspace path
|
|
- `{{now.iso}}` - Timestamp
|
|
|
|
**Sections:**
|
|
- workspace - Workspace metadata
|
|
- paths - All system paths
|
|
- core - Core settings
|
|
- debug - Debug configuration
|
|
- output - Output preferences
|
|
- providers - Provider settings
|
|
- platform - Platform services
|
|
- secrets - Secret management
|
|
- kms - Key management
|
|
- sops - SOPS configuration
|
|
- taskservs - Task service paths
|
|
- clusters - Cluster paths
|
|
- cache - Cache settings
|
|
|
|
### 2. provider-aws.toml.template
|
|
|
|
AWS provider configuration template. Generates: `{workspace}/config/providers/aws.toml`
|
|
|
|
**Variables:**
|
|
- `{{workspace.name}}` - Workspace name
|
|
- `{{workspace.path}}` - Absolute workspace path
|
|
- `{{now.iso}}` - Timestamp
|
|
|
|
**Sections:**
|
|
- provider - Provider metadata
|
|
- provider.auth - AWS authentication
|
|
- provider.paths - Provider-specific paths
|
|
- provider.api - API settings
|
|
|
|
### 3. provider-local.toml.template
|
|
|
|
Local provider configuration template. Generates: `{workspace}/config/providers/local.toml`
|
|
|
|
**Variables:**
|
|
- `{{workspace.name}}` - Workspace name
|
|
- `{{workspace.path}}` - Absolute workspace path
|
|
- `{{now.iso}}` - Timestamp
|
|
|
|
**Sections:**
|
|
- provider - Provider metadata
|
|
- provider.auth - Local auth (minimal)
|
|
- provider.paths - Provider-specific paths
|
|
|
|
### 4. provider-upcloud.toml.template
|
|
|
|
UpCloud provider configuration template. Generates: `{workspace}/config/providers/upcloud.toml`
|
|
|
|
**Variables:**
|
|
- `{{workspace.name}}` - Workspace name
|
|
- `{{workspace.path}}` - Absolute workspace path
|
|
- `{{now.iso}}` - Timestamp
|
|
|
|
**Sections:**
|
|
- provider - Provider metadata
|
|
- provider.auth - UpCloud authentication
|
|
- provider.paths - Provider-specific paths
|
|
- provider.api - API settings (UpCloud API URL)
|
|
|
|
### 5. kms.toml.template
|
|
|
|
Key Management Service configuration template. Generates: `{workspace}/config/kms.toml`
|
|
|
|
**Variables:**
|
|
- `{{workspace.name}}` - Workspace name
|
|
- `{{workspace.path}}` - Absolute workspace path
|
|
- `{{now.iso}}` - Timestamp
|
|
|
|
**Sections:**
|
|
- kms - KMS mode and settings
|
|
- kms.local - Local KMS (Age)
|
|
- kms.remote - Remote KMS server
|
|
|
|
### 6. user-context.yaml.template
|
|
|
|
User context configuration template. Generates: `~/Library/Application Support/provisioning/ws_{name}.yaml`
|
|
|
|
**Variables:**
|
|
- `{{workspace.name}}` - Workspace name
|
|
- `{{workspace.path}}` - Absolute workspace path
|
|
- `{{now.iso}}` - Timestamp
|
|
|
|
**Sections:**
|
|
- workspace - Workspace reference
|
|
- debug - User debug overrides
|
|
- output - User output preferences
|
|
- providers - User provider preferences
|
|
- paths - User path overrides
|
|
|
|
## Template Variable Syntax
|
|
|
|
Templates use `{{variable}}` syntax for interpolation:
|
|
|
|
```yaml
|
|
# Example
|
|
workspace:
|
|
name: "{{workspace.name}}"
|
|
path: "{{workspace.path}}"
|
|
created: "{{now.iso}}"
|
|
```
|
|
|
|
## Supported Variables
|
|
|
|
### Core Variables
|
|
- `{{workspace.name}}` - Workspace name (string)
|
|
- `{{workspace.path}}` - Absolute workspace path (string)
|
|
|
|
### Timestamp Variables
|
|
- `{{now.iso}}` - ISO 8601 timestamp (YYYY-MM-DDTHH:MM:SSZ)
|
|
- `{{now.date}}` - Date only (YYYY-MM-DD)
|
|
- `{{now.timestamp}}` - Unix timestamp
|
|
|
|
### Environment Variables (safe list)
|
|
- `{{env.HOME}}` - User home directory
|
|
- `{{env.USER}}` - Current user
|
|
- `{{env.HOSTNAME}}` - System hostname
|
|
|
|
## Usage
|
|
|
|
### Generate Workspace from Template
|
|
|
|
```nushell
|
|
use provisioning/core/nulib/lib_provisioning/workspace/init.nu *
|
|
|
|
# Initialize workspace with AWS and Local providers
|
|
workspace-init "my-workspace" "/path/to/workspace" \
|
|
--providers ["aws" "local"] \
|
|
--activate
|
|
```
|
|
|
|
### What Happens
|
|
|
|
1. Templates are read from this directory
|
|
2. Variables are interpolated with actual values
|
|
3. Generated configs are saved to workspace
|
|
4. User context (if --activate) is created
|
|
|
|
### Generated Structure
|
|
|
|
```
|
|
/path/to/workspace/
|
|
├── config/
|
|
│ ├── provisioning.yaml # From workspace-provisioning.yaml.template
|
|
│ ├── kms.toml # From kms.toml.template
|
|
│ └── providers/
|
|
│ ├── aws.toml # From provider-aws.toml.template
|
|
│ └── local.toml # From provider-local.toml.template
|
|
|
|
~/Library/Application Support/provisioning/
|
|
└── ws_my-workspace.yaml # From user-context.yaml.template
|
|
```
|
|
|
|
## Adding New Templates
|
|
|
|
### 1. Create Template File
|
|
|
|
```bash
|
|
# Example: New provider template
|
|
touch provider-gcp.toml.template
|
|
```
|
|
|
|
### 2. Add Template Content
|
|
|
|
```toml
|
|
# GCP Provider Configuration for Workspace: {{workspace.name}}
|
|
# Generated: {{now.iso}}
|
|
|
|
[provider]
|
|
name = "gcp"
|
|
enabled = true
|
|
workspace = "{{workspace.name}}"
|
|
|
|
[provider.auth]
|
|
project = "default"
|
|
region = "us-central1"
|
|
|
|
[provider.paths]
|
|
base = "{{workspace.path}}/.providers/gcp"
|
|
cache = "{{workspace.path}}/.providers/gcp/cache"
|
|
```
|
|
|
|
### 3. Update Workspace Init
|
|
|
|
Add GCP template handling to `workspace/init.nu`:
|
|
|
|
```nushell
|
|
def generate-provider-config [
|
|
workspace_path: string
|
|
workspace_name: string
|
|
provider_name: string
|
|
] {
|
|
let template_path = $"/path/to/templates/provider-($provider_name).toml.template"
|
|
|
|
if not ($template_path | path exists) {
|
|
print $"⚠️ No template for provider '($provider_name)'"
|
|
return
|
|
}
|
|
|
|
# Generate config...
|
|
}
|
|
```
|
|
|
|
## Template Best Practices
|
|
|
|
### 1. Always Include Metadata
|
|
|
|
```yaml
|
|
# Configuration for Workspace: {{workspace.name}}
|
|
# Generated: {{now.iso}}
|
|
# DO NOT EDIT - Regenerate from template
|
|
```
|
|
|
|
### 2. Use Absolute Paths
|
|
|
|
```yaml
|
|
paths:
|
|
base: "{{workspace.path}}" # ✅ Absolute
|
|
cache: "{{workspace.path}}/.cache" # ✅ Absolute
|
|
|
|
# NOT relative:
|
|
# cache: ".cache" # ❌ Relative
|
|
```
|
|
|
|
### 3. Provide Sensible Defaults
|
|
|
|
```yaml
|
|
debug:
|
|
enabled: false # Safe default
|
|
log_level: "info" # Reasonable default
|
|
|
|
providers:
|
|
default: "local" # Safe default
|
|
```
|
|
|
|
### 4. Document Sections
|
|
|
|
```yaml
|
|
# Debug settings (can be overridden by user context)
|
|
debug:
|
|
enabled: false
|
|
log_level: "info"
|
|
```
|
|
|
|
### 5. Group Related Settings
|
|
|
|
```toml
|
|
[kms]
|
|
mode = "local"
|
|
|
|
[kms.local]
|
|
provider = "age"
|
|
key_path = "{{workspace.path}}/.kms/keys/age.txt"
|
|
|
|
[kms.remote]
|
|
server = ""
|
|
```
|
|
|
|
## Validation
|
|
|
|
Templates should be validated before use:
|
|
|
|
1. **Syntax Valid**: YAML/TOML parseable
|
|
2. **Variables Complete**: All `{{variables}}` have values
|
|
3. **Paths Absolute**: All paths use `{{workspace.path}}`
|
|
4. **Sensible Defaults**: Safe, secure defaults
|
|
|
|
## Troubleshooting
|
|
|
|
### Template Not Found
|
|
|
|
```
|
|
⚠️ Warning: No template found for provider 'xyz'
|
|
```
|
|
|
|
**Solution**: Create template or check provider name spelling.
|
|
|
|
### Variable Not Interpolated
|
|
|
|
Config shows `{{workspace.name}}` instead of actual name.
|
|
|
|
**Solution**: Check variable exists in interpolation list, update workspace/init.nu.
|
|
|
|
### Invalid YAML/TOML
|
|
|
|
Generated config fails to parse.
|
|
|
|
**Solution**: Validate template syntax, ensure proper escaping.
|
|
|
|
## Related Files
|
|
|
|
- **Workspace Init**: `provisioning/core/nulib/lib_provisioning/workspace/init.nu`
|
|
- **Config Loader**: `provisioning/core/nulib/lib_provisioning/config/loader.nu`
|
|
- **Documentation**: `docs/configuration/workspace-config-architecture.md`
|
|
|
|
## Summary
|
|
|
|
- Templates are **source files only**, never loaded at runtime
|
|
- Used to **generate workspace configs** during initialization
|
|
- Support **variable interpolation** with `{{variable}}` syntax
|
|
- Each template creates specific config file in workspace
|
|
- **Modify templates** to change default workspace structure
|