Parameterize TofuTemplateRenderer by Provider
Epic: #205 - Add Hetzner Provider Support
Phase: 1 - Make LXD Explicit
Dependencies: #206, #207, #208
Overview
This task makes the TofuTemplateRenderer provider-aware so it can render templates for different infrastructure providers (LXD, Hetzner). Currently, the renderer has hardcoded paths to tofu/lxd/ templates. After this change, it will dynamically select the template directory based on the provider specified in the environment configuration.
This is Task 4 in Phase 1 ("Make LXD Explicit") of the Hetzner Provider Support epic.
Specification
See detailed specification: docs/issues/212-parameterize-tofu-template-renderer-by-provider.md
🏗️ Architecture Requirements
DDD Layer: Infrastructure
Module Path: src/infrastructure/external_tools/tofu/template/
Pattern: Template Renderer with Strategy Pattern for provider-specific rendering
Key Design Decisions
- No template sharing between providers: Each provider has its own independent templates. This makes providers easier to add, maintain, and debug.
- Provider-specific code isolation: All Rust code specific to a provider must be in its own module (e.g.,
wrappers/hetzner/, wrappers/lxd/).
- Only
variables.tfvars.tera needed: The application generates the final variables.tfvars from the Tera template at runtime.
Anti-Patterns to Avoid
- ❌ Hardcoding provider-specific paths in generic code
- ❌ Complex conditionals that grow with each new provider
- ❌ Sharing templates between providers (each provider must be self-contained)
- ❌ Placing provider-specific Rust code in shared modules (use
wrappers/{provider}/ structure)
Implementation Plan
Phase 1: Create and Validate Hetzner OpenTofu Templates (estimated 2-3 hours)
Goal: Create static OpenTofu files and test them manually with real Hetzner infrastructure before any Rust code changes. This isolates infrastructure issues from code issues.
Phase 2: Integrate Hetzner Templates with Rust Code (estimated 3-4 hours)
Goal: Convert working static files to Tera templates and integrate with the Rust codebase.
Hetzner Template Structure
templates/tofu/hetzner/
├── versions.tf # Provider version requirements (hcloud ~> 1.47, time ~> 0.11)
├── main.tf # Server resource, outputs, and variable definitions
├── variables.tfvars.tera # Tera template for variable values (generated at runtime)
└── cloud-init.yml.tera # Cloud-init template (independent from LXD)
Note: Only variables.tfvars.tera is needed for the Tera rendering pipeline.
Acceptance Criteria
Quality Checks:
Phase 1 Criteria (Manual Testing):
Phase 2 Criteria (Rust Integration):
Related
Parameterize TofuTemplateRenderer by Provider
Epic: #205 - Add Hetzner Provider Support
Phase: 1 - Make LXD Explicit
Dependencies: #206, #207, #208
Overview
This task makes the
TofuTemplateRendererprovider-aware so it can render templates for different infrastructure providers (LXD, Hetzner). Currently, the renderer has hardcoded paths totofu/lxd/templates. After this change, it will dynamically select the template directory based on the provider specified in the environment configuration.This is Task 4 in Phase 1 ("Make LXD Explicit") of the Hetzner Provider Support epic.
Specification
See detailed specification: docs/issues/212-parameterize-tofu-template-renderer-by-provider.md
🏗️ Architecture Requirements
DDD Layer: Infrastructure
Module Path:
src/infrastructure/external_tools/tofu/template/Pattern: Template Renderer with Strategy Pattern for provider-specific rendering
Key Design Decisions
wrappers/hetzner/,wrappers/lxd/).variables.tfvars.teraneeded: The application generates the finalvariables.tfvarsfrom the Tera template at runtime.Anti-Patterns to Avoid
wrappers/{provider}/structure)Implementation Plan
Phase 1: Create and Validate Hetzner OpenTofu Templates (estimated 2-3 hours)
Goal: Create static OpenTofu files and test them manually with real Hetzner infrastructure before any Rust code changes. This isolates infrastructure issues from code issues.
versions.tf,main.tf,variables.tfvars,cloud-init.yml)tofu init,validate,plan,apply,output -json, SSH test,destroy)Phase 2: Integrate Hetzner Templates with Rust Code (estimated 3-4 hours)
Goal: Convert working static files to Tera templates and integrate with the Rust codebase.
templates/tofu/hetzner/(independent from LXD, no sharing)wrappers/hetzner/module (HetznerVariablesTemplate,HetznerCloudInitTemplate)TofuTemplateRendererto acceptProviderparameter and select templates dynamicallyTofuTemplateRendererto pass providerdocs/contributing/templates.mdHetzner Template Structure
Acceptance Criteria
Quality Checks:
./scripts/pre-commit.shPhase 1 Criteria (Manual Testing):
tofu init,validate,plan,applywork correctlytofu output -jsonproducesinstance_infostructure matching Rust parsertofu destroyworkPhase 2 Criteria (Rust Integration):
templates/tofu/hetzner/(no sharing with LXD)HetznerVariablesTemplateandHetznerCloudInitTemplatewrappers inwrappers/hetzner/moduleTofuTemplateRendereracceptsProviderparameterRelated