provisioning/config/templates/README_SST_PATTERN.md
Jesús Pérez 6a59d34bb1
chore: update provisioning configuration and documentation
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.
2025-12-11 21:50:42 +00:00

8.8 KiB

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

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

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)

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)

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:

# 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:

# Merge sub-sections
paths = defaults.paths | {
    base: "/custom/path"  # Override only base, keep others
}

Verification After Template Application

After generating workspace from templates:

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:

    schema MyNewConfig:
        field: str
    

    Add to workspace-config-schema.k.template

  2. Add default value:

    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:

provisioning workspace sync --all

This updates .provisioning/ files in all workspaces, keeping workspace-specific config/provisioning.k files intact.

Example: Complete Workspace Creation Flow

# 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"
  • 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)