Core concepts
To get the most out of Watt TF, it helps to understand the underlying architecture and the philosophy that drives it.
At its heart, Watt TF is a declarative blueprint engine designed to solve a single, painful problem: the mixing of raw business/application data with complex infrastructure logic in Terraform.
1. Separation of Concerns
In traditional Terraform setups, you often end up with complex configurations because your data structure doesn't match Terraform's flat resource architecture. You are forced to write dynamic blocks, nested for_each loops, and complex local variables in HCL.
Watt TF completely decouples your data from your infrastructure templates:
- Input Data (The "What"): Clean, nested, raw data (e.g., a list of microservices, database schemas, or routing tables) without any Terraform-specific code.
- Blueprint (The "How"): A declarative instruction set that describes how to map your input data onto Terraform resources.
- Terraform JSON (The "Execution"): Receives native, statically compiled JSON. No loops, no complex logic, just plain configuration.
2. Declarative Transformation (The Blueprint)
Unlike general-purpose template engines (like Jinja2 or Go Templates) which rely on text-based manipulation, Watt TF parses your inputs and blueprints into a structured AST (Abstract Syntax Tree) and evaluates them.
A blueprint consists of a list of transform blocks. Each block has a target and a value:
transform:
- target: resource.local_file.${input.name}
value:
filename: ${input.name}
content: ${input.content}Path Resolution
The target is a dot-notated path. Watt TF evaluates the variables inside the path and dynamically constructs the nested JSON object structure on the fly.
- It evaluates
${input.name}and${input.content}from the input data. - It resolves the path to
resource->local_file->microservice. - It places the evaluated
valueobject exactly at that destination.
If parent objects (like resource or local_file) do not exist yet, Watt TF creates them automatically.
3. Variable Interpolation
Watt TF uses a lightweight syntax ${...} to dynamically inject values. You can reference:
${input}: Accesses the root of your input file (e.g.,${input.nested.property}).${env}: Accesses environment variables of the running system (e.g.,${env.STAGE}). Useful for injecting workspace or credential details on the fly.${vars}: Access precomputed vars of yourvariablesblock of your blueprints.
Because the evaluation happens in Go memory, it is deterministic, lightning-fast, and happens before Terraform is ever invoked.
4. Advanced Logic with CEL (Common Expression Language)
While simple path resolution covers basic use cases, real-world infrastructure often requires logic—like filtering lists, setting defaults, or conditional evaluation.
Instead of inventing a proprietary shifting logic, Watt TF embeds Google's Common Expression Language (CEL). CEL is a lightning-fast, safe, and highly predictable expression language used heavily throughout Kubernetes, Envoy, and Firebase.
You can supercharge your variable interpolation by writing inline CEL expressions inside your blueprints:
transform:
- target: resource.aws_instance.${input.name}
value:
ami: ${input.ami}
# Using a CEL ternary operator for fallback logic:
instance_type: ${input.size == "large" ? "t3.large" : "t3.micro"}
# Transforming data inline:
tags:
Environment: ${env.STAGE.upper()}
ManagedBy: "Watt TF"5. Conditional Transformations (if conditions)
Sometimes you don't just want to change a value dynamically, but decide whether an entire resource or block should be generated at all. In traditional Terraform, this requires confusing count or for_each hacks.
In Watt TF, every transformation block can have an optional if statement powered by CEL. If the expression evaluates to false, the entire block is skipped during compilation.
transform:
# This resource is only created if production mode is enabled in the input
- if: input.environment == "prod"
target: resource.aws_instance.production_bastion
value:
ami: "ami-12345678"
instance_type: "t3.medium"
# Seamlessly inject cluster-specific settings
- if: has(input.cluster_config) && input.cluster_config.enabled
target: resource.kubernetes_cluster.main
value:
version: ${input.cluster_config.version}6. Iterations (for_each loops)
Sometimes you want to perform actions multiple times, based on inputs. You can use the declarative for_each statement on any transformation block.
Watt TF iterates over the collection provided via CEL, exposes the current element as item, and its 0-indexed position as item_index.
transform:
- for_each: input.jobs
target: "resource.job.${item.name}"
value:
name: "${item.name}"
enabled: true
# You can easily use math on the index via CEL
id: "job-${item_index + 1}"Variables inside for_each
item: The current element in the iteration.item_index: The 0-based index of the current element.
Afterword: Continue your journey
From now on you are good to go! You can start writing your own blueprints and input data to generate Terraform JSON configurations.
In case you want to learn more, please check out the Configuration Overview section for a deeper dive into Watt TF's capabilities.
