provisioning/config/templates/README_SST_PATTERN.md

279 lines
8.8 KiB
Markdown
Raw Normal View History

# SST Pattern - Workspace Configuration Templates
This directory contains all templates for creating workspace configurations using the KCL SST (Single Source of Truth) pattern.
## Quick Reference
### For Creating New Workspaces
```bash
# The provisioning system should use these templates
provisioning workspace init <name> \
--path /path/to/workspace \
--use-templates
```
### File Mapping
| Template File | Output Location | Purpose |
|---------------|-----------------|---------|
| `kcl.mod.template` | `{ws}/kcl.mod` | Workspace package definition |
| `workspace-config-schema.k.template` | `{ws}/.provisioning/workspace_config.k` | Schema (SST) |
| `workspace-config-defaults.k.template` | `{ws}/.provisioning/workspace_config_defaults.k` | Defaults (SST) |
| `.provisioning-kcl.mod.template` | `{ws}/.provisioning/kcl.mod` | .provisioning package |
| `config-kcl.mod.template` | `{ws}/config/kcl.mod` | config package |
| `workspace-config.k.template` | `{ws}/config/provisioning.k` | Workspace overrides (**workspace-specific**) |
## Template Variables
These variables are replaced during workspace creation:
- `{{WORKSPACE_NAME}}` - Workspace identifier (e.g., "librecloud", "production")
- `{{WORKSPACE_PATH}}` - Absolute path to workspace directory
- `{{PROVISIONING_PATH}}` - Absolute path to provisioning system
- `{{CREATED_TIMESTAMP}}` - ISO 8601 creation timestamp
- `{{INFRA_NAME}}` - Infrastructure context name (default: "default")
## Directory Structure
```
provisioning/config/templates/
├── README_SST_PATTERN.md ← You are here
├── WORKSPACE_CONFIG_TEMPLATES.md ← Detailed documentation
├── workspace-config-schema.k.template
├── workspace-config-defaults.k.template
├── workspace-config.k.template
├── kcl.mod.template
├── config-kcl.mod.template
└── .provisioning-kcl.mod.template
```
## The Three-Part SST Pattern
### 1. Schema (workspace_config.k)
```kcl
schema WorkspaceConfig:
workspace: Workspace
paths: Paths
# ... 19+ schemas total
```
**Purpose**: Type definitions and validation rules
**Update**: When schema needs to change (all workspaces affected)
**Frequency**: Rare (breaking changes)
### 2. Defaults (workspace_config_defaults.k)
```kcl
default_workspace_config: WorkspaceConfig = {
workspace = { name = "default-workspace", ... }
paths = { infra = "infra", cache = ".cache", ... }
debug = { enabled = False, ... }
# ... all sections with default values
}
```
**Purpose**: Base configuration inherited by all workspaces
**Update**: When default values should change globally
**Frequency**: Occasional (new features, policy changes)
### 3. Workspace Overrides (provisioning.k)
```kcl
workspace_config = defaults.default_workspace_config | {
workspace = { name = "librecloud", ... }
paths = defaults.default_workspace_config.paths | {
base = "/Users/Akasha/project-provisioning/workspace_librecloud"
}
provisioning = { path = "/Users/Akasha/project-provisioning/provisioning" }
}
```
**Purpose**: Workspace-specific values (only diffs from defaults)
**Update**: When workspace settings change
**Frequency**: Per-workspace changes
## KCL Merge Pattern
The `|` operator merges KCL objects:
```kcl
# Start with defaults
base_config = { a: 1, b: 2, c: 3 }
# Override specific values
final_config = base_config | {
b: 20 # Override b
# a and c remain from base
}
# Result: { a: 1, b: 20, c: 3 }
```
For nested objects:
```kcl
# Merge sub-sections
paths = defaults.paths | {
base: "/custom/path" # Override only base, keep others
}
```
## Verification After Template Application
After generating workspace from templates:
```bash
cd {workspace}/config
kcl run provisioning.k
```
Expected output:
- Valid YAML on stdout
- No errors or validation failures
- All configuration sections populated
- Values properly merged from defaults and overrides
## Adding New Configuration Sections
When adding a new section to workspaces:
1. **Update schema template**:
```kcl
schema MyNewConfig:
field: str
```
Add to `workspace-config-schema.k.template`
2. **Add default value**:
```kcl
my_new_config = {
field: "default-value"
}
```
Add to `workspace-config-defaults.k.template`
3. **Existing workspaces inherit automatically**
- No changes needed to `workspace-config.k.template`
- New workspaces get the new section by default
- Override in workspace's `provisioning.k` if needed
## Maintenance Tasks
### Updating All Workspaces (Template-Driven)
1. Edit the template files in this directory
2. Re-generate workspaces using the `workspace init` command
3. Or: Run `provisioning workspace sync` to update existing workspaces
### Updating Single Workspace
Edit `{workspace}/config/provisioning.k` directly - only this file is workspace-specific.
### Updating Schema/Defaults Globally
Edit templates, then sync all workspaces:
```bash
provisioning workspace sync --all
```
This updates `.provisioning/` files in all workspaces, keeping workspace-specific `config/provisioning.k` files intact.
## Example: Complete Workspace Creation Flow
```bash
# 1. Initialize workspace structure
workspace_name="production"
workspace_path="/opt/workspaces/production"
provisioning_path="/usr/local/provisioning"
# 2. Use templates (provisioning should do this)
mkdir -p "$workspace_path"
# Create workspace root kcl.mod
sed "s|{{WORKSPACE_NAME}}|$workspace_name|g" \
kcl.mod.template > "$workspace_path/kcl.mod"
# Create .provisioning/ directory
mkdir -p "$workspace_path/.provisioning"
# Copy .provisioning files (no variable replacement needed)
cp workspace-config-schema.k.template \
"$workspace_path/.provisioning/workspace_config.k"
cp workspace-config-defaults.k.template \
"$workspace_path/.provisioning/workspace_config_defaults.k"
cp .provisioning-kcl.mod.template \
"$workspace_path/.provisioning/kcl.mod"
# Create config/ directory
mkdir -p "$workspace_path/config"
cp config-kcl.mod.template \
"$workspace_path/config/kcl.mod"
# Create workspace config with variable replacement
sed -e "s|{{WORKSPACE_NAME}}|$workspace_name|g" \
-e "s|{{WORKSPACE_PATH}}|$workspace_path|g" \
-e "s|{{PROVISIONING_PATH}}|$provisioning_path|g" \
-e "s|{{CREATED_TIMESTAMP}}|$(date -u +%Y-%m-%dT%H:%M:%SZ)|g" \
workspace-config.k.template > "$workspace_path/config/provisioning.k"
# 3. Verify
cd "$workspace_path/config"
kcl run provisioning.k
echo "✅ Workspace created successfully"
```
## Links
- **Schema Documentation**: See `workspace-config-schema.k.template`
- **Defaults Reference**: See `workspace-config-defaults.k.template`
- **Workspace Override Pattern**: See `workspace-config.k.template`
- **Detailed Guide**: See `WORKSPACE_CONFIG_TEMPLATES.md`
- **Architecture Decision**: See `docs/architecture/adr/ADR-010-configuration-format-strategy.md`
## Benefits
**Single Source of Truth** - Schema and defaults defined once
**DRY Principle** - No duplication across workspaces
**Type-Safe** - Full KCL schema validation
**Maintainable** - Update templates to affect all new workspaces
**Clear Intent** - Workspace configs show only differences
**Mergeable** - Clean KCL merge semantics
**Scalable** - Easy to add new config sections
## Template Extension Convention: `.template`
The workspace initialization templates in this directory use the **`.template`** extension (not `.j2`) for specific reasons:
### Why `.template` for Initialization?
1. **Simple Substitution Only**: Workspace init doesn't need complex logic
- Just `{{variable}}` replacement for workspace-specific values
- No conditionals, loops, or filters needed
2. **No Plugin Dependency**: Initialization works without external tools
- `nu_plugin_tera` (Jinja2) is not required for workspace creation
- More portable, reliable, simpler to bootstrap
3. **Semantic Clarity**: Extension signals the purpose immediately
- `.template` = one-time initialization
- `.j2` = runtime configuration generation
- Developers know intent at a glance
4. **Appropriate Complexity**: Using the right tool for the job
- Runtime templates (`.j2`): Complex logic, full Jinja2 syntax
- Init templates (`.template`): Simple substitution, no complexity
### Codebase Template Distribution
- **`.j2` templates**: 134 files (88%) - Runtime configuration generation
- **`.template` templates**: 16 files (10%) - Workspace initialization
- **`.tera` templates**: 3 files (2%) - Plugin examples only
See `provisioning/config/templates/README.md` for complete template conventions documentation.
## Status
✅ Templates implemented and tested with librecloud workspace
✅ SST pattern functional (verified with `kcl run`)
✅ Template convention documented (`.template` for init, `.j2` for runtime)
⏳ Integration into workspace initialization system (TODO)
⏳ Documentation in ADR-010 (TODO)