# 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 \ --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)