Terraform is an amazing piece of technology but the biggest thing holding it back is HCL. I guess the intention was for it to serve as a happy middle ground between a full blown programming language and a configuration language - enabling some abstractions, but yet rigid enough to stop developers getting too carried away. I think unfortunately that trying to have it both ways doesn't really work and ends up leaving those writing the code frustrated - it's almost as if it's teasing you - you can feel there's all this power under the hood and you are given things like modules which are nice, but you always feel like you're on a of short leash.<p>I switched from Terraform to Pulumi for a personal project recently and haven't looked back (no affiliation). Writing it with Typescript means you get excellent IDE support (using VSCode here) and access to the enormous JS ecosystem. I've also found myself creating a number of useful abstractions - that I would never have bothered to with HCL - like IAM helper functions, eg:<p><pre><code> const limitedReadAccessPolicy = createPolicy(
"product-table-read-access",
allow(
["dynamodb:Get*", "dynamodb:Query"],
[table.arn, interpolate`${table.arn}/index/*`]
)
);
</code></pre>
vs<p><pre><code> resource "aws_iam_policy" "product_read_access" {
name = "madu_${var.env_name}_product_read"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"dynamodb:Get*",
"dynamodb:Query"
],
"Effect": "Allow",
"Resource": [
"${aws_dynamodb_table.products.arn}",
"${aws_dynamodb_table.products.arn}/index/*"
]
}
]
}
EOF
}</code></pre>