Skip to main content

Template System Architecture

OpenPrime uses a custom template processing system powered by Injecto to generate infrastructure code.

Overview​

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Templates β”‚ β”‚ Configuration β”‚ β”‚ Injecto β”‚
β”‚ (.tf.tpl) │────▢│ (JSON) │────▢│ Processor β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Generated Code β”‚
β”‚ (.tf files) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Template Syntax​

Parameters (@param)​

Define configurable values:

# @param cluster_name required
# @param cluster_version default=1.28
# @param node_count default=3 type=number

resource "aws_eks_cluster" "main" {
name = "${cluster_name}"
version = "${cluster_version}"
}

Parameter Options:

OptionDescriptionExample
requiredMust be provided# @param name required
defaultDefault value# @param count default=3
typeValue type# @param enabled type=boolean

Conditional Sections (@section)​

Include/exclude code blocks:

# @section enable_logging begin
resource "aws_cloudwatch_log_group" "cluster" {
name = "/aws/eks/${cluster_name}/cluster"
retention_in_days = 30
}
# @section enable_logging end

Sections are included when the condition evaluates to truthy.

Loops (@foreach)​

Iterate over collections:

# @foreach node_group in node_groups begin
resource "aws_eks_node_group" "${node_group.name}" {
cluster_name = aws_eks_cluster.main.name
node_group_name = "${node_group.name}"

scaling_config {
desired_size = ${node_group.desired_size}
min_size = ${node_group.min_size}
max_size = ${node_group.max_size}
}

instance_types = ["${node_group.instance_type}"]

# @section node_group.labels begin
labels = ${jsonencode(node_group.labels)}
# @section end
}
# @foreach end

Conditionals (@if)​

Inline conditional expressions:

resource "aws_eks_cluster" "main" {
name = var.cluster_name
version = var.cluster_version

# @if public_access begin
vpc_config {
endpoint_public_access = true
}
# @if end

# @if private_access begin
vpc_config {
endpoint_public_access = false
endpoint_private_access = true
}
# @if end
}

Injecto Service​

API Endpoints​

Process Templates​

POST /process-upload
Content-Type: multipart/form-data

template_file: <template.tf.tpl>
config: {"cluster_name": "my-cluster", ...}

Response:

{
"success": true,
"files": {
"main.tf": "...",
"variables.tf": "...",
"outputs.tf": "..."
}
}

Health Check​

GET /health

Response:

{
"status": "healthy",
"version": "1.0.0"
}

Processing Pipeline​

def process_template(template: str, config: dict) -> str:
# 1. Parse parameters
params = extract_params(template)
validate_params(params, config)

# 2. Process sections
template = process_sections(template, config)

# 3. Process loops
template = process_loops(template, config)

# 4. Substitute variables
template = substitute_variables(template, config)

# 5. Clean up directives
template = cleanup_directives(template)

return template

Template Organization​

Directory Structure​

openprime-infra-templates/
β”œβ”€β”€ templates/
β”‚ β”œβ”€β”€ aws/
β”‚ β”‚ β”œβ”€β”€ eks/
β”‚ β”‚ β”‚ β”œβ”€β”€ main.tf.tpl
β”‚ β”‚ β”‚ β”œβ”€β”€ variables.tf.tpl
β”‚ β”‚ β”‚ β”œβ”€β”€ outputs.tf.tpl
β”‚ β”‚ β”‚ └── iam.tf.tpl
β”‚ β”‚ β”œβ”€β”€ rds/
β”‚ β”‚ β”‚ β”œβ”€β”€ main.tf.tpl
β”‚ β”‚ β”‚ └── security-group.tf.tpl
β”‚ β”‚ └── s3/
β”‚ β”‚ └── main.tf.tpl
β”‚ β”œβ”€β”€ azure/
β”‚ β”‚ └── aks/
β”‚ └── gcp/
β”‚ └── gke/
β”œβ”€β”€ shared/
β”‚ β”œβ”€β”€ backend.tf.tpl
β”‚ └── versions.tf.tpl
└── local/
β”œβ”€β”€ terraforge.sh
└── extract_parameters.sh

Shared Templates​

Common code reused across providers:

# shared/backend.tf.tpl
# @param backend_bucket required
# @param backend_key required
# @param backend_region default=us-east-1

terraform {
backend "s3" {
bucket = "${backend_bucket}"
key = "${backend_key}"
region = "${backend_region}"
dynamodb_table = "terraform-state-lock"
encrypt = true
}
}

Configuration Mapping​

Service Schema β†’ Template Config​

// servicesConfig.js
kubernetes: {
template: 'aws/eks',
schema: {
clusterName: { type: 'string', param: 'cluster_name' },
version: { type: 'select', param: 'cluster_version' },
nodeGroups: { type: 'array', param: 'node_groups' }
}
}

Environment β†’ Injecto Input​

// Backend transforms environment to template config
function buildTemplateConfig(environment) {
const config = {
environment_name: environment.name,
provider: environment.provider,
region: environment.region,
...environment.configuration
};

// Map services to template params
for (const [service, settings] of Object.entries(environment.services)) {
if (settings.enabled) {
const schema = servicesConfig[service].schema;
for (const [key, value] of Object.entries(settings)) {
const param = schema[key]?.param || key;
config[param] = value;
}
}
}

return config;
}

Generated Output​

Example: EKS Cluster​

Input Configuration:

{
"cluster_name": "production",
"cluster_version": "1.28",
"node_groups": [
{
"name": "general",
"instance_type": "t3.large",
"desired_size": 5,
"min_size": 2,
"max_size": 10
}
],
"enable_logging": true
}

Generated main.tf:

module "eks" {
source = "terraform-aws-modules/eks/aws"
version = "~> 19.0"

cluster_name = "production"
cluster_version = "1.28"

vpc_id = module.vpc.vpc_id
subnet_ids = module.vpc.private_subnets

eks_managed_node_groups = {
general = {
instance_types = ["t3.large"]
min_size = 2
max_size = 10
desired_size = 5
}
}

cluster_enabled_log_types = [
"api",
"audit",
"authenticator",
"controllerManager",
"scheduler"
]
}

resource "aws_cloudwatch_log_group" "cluster" {
name = "/aws/eks/production/cluster"
retention_in_days = 30
}

Testing Templates​

Local Testing​

cd openprime-infra-templates/local

# Process templates
./terraforge.sh

# Validate generated code
cd output/
terraform init
terraform validate
terraform plan

Unit Testing​

# test_templates.py
def test_eks_template_basic():
template = load_template('aws/eks/main.tf.tpl')
config = {
'cluster_name': 'test',
'cluster_version': '1.28',
'node_groups': []
}

result = process_template(template, config)

assert 'cluster_name = "test"' in result
assert 'cluster_version = "1.28"' in result

Best Practices​

  1. Keep templates DRY - Extract common patterns to shared templates
  2. Use modules - Reference Terraform Registry modules
  3. Pin versions - Lock provider and module versions
  4. Document parameters - Add descriptions to all @param directives
  5. Validate early - Catch errors before code generation
  6. Test thoroughly - Ensure generated code compiles and plans cleanly