Watt TF is a powerful CLI tool that transforms JSON and YAML configurations into Terraform JSON files - Because writing complex nested loops in HCL shouldn't make you question your career choices
Generate Terraform configuration from structured application data.
Ideal for:
- Internal Developer Platforms
- SaaS platforms
- Multi-tenant deployments
- CI/CD pipelines
- Self-service infrastructure portals
Installation
Via Go
go install github.com/devsebastianops/watt-tf/cmd/wtf@latest
From Source
git clone https://github.com/devsebastianops/watt-tf.git
cd watt-tf
go build -o wtf ./cmd/wtf/main.go
./wtf --help
Quick Start
Basic Usage
wtf build --input config.json --config .wtf.yaml --output terraform.tf.json
input.json
{
"cloudrun": {
"image": "gcr.io/cloudrun/hello",
"port": 8080
}
}
.wtf.yaml
transform:
- target: resource.google_cloud_run_service.default
value:
image: "${input.cloudrun.image}"
port: "${input.cloudrun.port}"
Output (terraform.tf.json)
{
"resource": {
"google_cloud_run_service": {
"default": {
"image": "gcr.io/cloudrun/hello",
"port": 8080
}
}
}
}
Please refer to the examples directory for more detailed use cases and configurations.
Configuration Guide
The .wtf.yaml file defines how to transform your input into Terraform configuration.
transform:
- target: resource.aws_s3_bucket.my_bucket
value:
bucket: "my-bucket-name"
acl: "private"
String Interpolation
Use ${input.path.to.value} to interpolate values from your input:
transform:
- target: resource.aws_s3_bucket.${input.bucket_name}
value:
bucket: "${input.bucket_name}-${input.environment}"
tags:
Environment: "${input.environment}"
Owner: "${input.owner}"
Use CEL expressions in the if field to conditionally apply transformations:
transform:
- target: resource.aws_rds.production
if: input.environment == 'prod'
value:
instance_class: "db.r5.2xlarge"
multi_az: true
- target: resource.aws_rds.development
if: input.environment == 'dev'
value:
instance_class: "db.t3.micro"
multi_az: false
Complex Conditions
CEL supports complex boolean logic:
transform:
- target: resource.cache.redis
if: input.enable_cache && (input.env == 'production' || input.env == 'staging')
value:
size: "large"
String Methods
Use string methods for pattern matching:
transform:
- target: resource.iam_role.admin
if: input.email.startsWith('admin@')
value:
permissions: ["admin"]
- target: resource.cert.wildcard
if: input.domain.contains('*.example.com')
value:
wildcard: true
Deep Merge
Multiple transformations to the same target are automatically merged:
transform:
- target: resource.aws_instance.server
value:
instance_type: "${input.instance_type}"
- target: resource.aws_instance.server # Same target!
value:
tags:
Name: "${input.server_name}"
Environment: "${input.environment}"
Result: Both instance_type and tags exist in the final output.
Nested Paths
Deeply nested structures are automatically unflattened:
transform:
- target: resource.aws_vpc.main.subnets.primary.tags
value:
Name: "${input.vpc_name}-primary"
Tier: "public"
Command Reference
wtf build
Transforms your input configuration into Terraform JSON.
wtf build [OPTIONS]
Options:
--input <FILE> Input file (JSON or YAML) [required]
--config <FILE> Transformation config (.wtf.yaml) [default: .wtf.yaml]
--output <FILE> Output file [default: watt.tf.json]
Examples:
# Simple build
wtf build --input config.json
# Custom output
wtf build --input input.yaml --output main.tf.json
# Different config
wtf build --input config.json --config transformations.yaml --output output.tf.json
Testing
Watt TF includes comprehensive E2E tests covering all features:
# Run all tests
go test ./tests/e2e -v
# Run specific example
go test ./tests/e2e -v -run "TestE2EExamples/01-simple-json"
# View test examples
ls -la example/
Use Cases
Multi-Environment Deployments
Generate environment-specific Terraform configurations from a single input:
transform:
- target: resource.aws_instance.app
if: input.environment == 'prod'
value:
instance_type: "t3.large"
monitoring: true
- target: resource.aws_instance.app
if: input.environment == 'dev'
value:
instance_type: "t3.micro"
monitoring: false
Infrastructure Templating
Reuse configuration templates across projects:
transform:
- target: resource.aws_s3_bucket.${input.project}
value:
bucket: "${input.project}-${input.environment}-data"
versioning:
enabled: "${input.enable_versioning}"
tags:
Project: "${input.project}"
Environment: "${input.environment}"
CostCenter: "${input.cost_center}"
CI/CD Integration
Generate Terraform configurations dynamically in your pipeline:
#!/bin/bash
# Extract environment from Git branch
ENV=$(git rev-parse --abbrev-ref HEAD)
# Generate configuration
wtf build \
--input environment.json \
--config transforms.yaml \
--output terraform-${ENV}.tf.json
# Apply Terraform
terraform init
terraform plan -out=plan.tfplan
terraform apply plan.tfplan
Feedback & Contribution
We ❤️ contributions! Whether it's bug reports, feature requests, or pull requests:
Report Issues
Found a bug? Open an Issue
Contribute Code
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature
- Commit changes:
git commit -m 'Add amazing feature'
- Push to branch:
git push origin feature/amazing-feature
- Open a Pull Request
Roadmap
- Plugin system for custom transformers
- Jinja2 template engine for complex scenarios
- Interactive CLI mode
- VS Code extension
License
This project is licensed under the MIT License - see the LICENSE file for details.
Made with ❤️, Happy Terraforming! 🚀