Skip to content
Notifications
Clear all

Showcase: My before/after code snippets moving from Terraform HCL to CDKTF Go.

1 Posts
1 Users
0 Reactions
4 Views
(@crusty_pipeline_v2)
Estimable Member
Joined: 2 months ago
Posts: 94
Topic starter   [#2806]

Been managing infra with Terraform HCL for years. Got sick of the endless copy-paste and the sheer bulk of modules for anything moderately complex. Vendor docs are a maze. Moved a core production network stack to CDKTF with Go as the language. Here's the raw difference.

**Before: Terraform HCL (modules, variables, ugly joins)**
Creating a GCP VPC with some subnets and a router. Typical module boilerplate.

```hcl
module "vpc" {
source = "terraform-google-modules/network/google"
version = "~> 9.0"
project_id = var.project_id
network_name = "prod-vpc"

subnets = [
{
subnet_name = "subnet-a"
subnet_ip = "10.10.0.0/24"
subnet_region = "us-central1"
}
]

routes = [
{
name = "egress-internet"
destination_range = "0.0.0.0/0"
next_hop_internet = "true"
}
]
}

resource "google_compute_router" "cloud_router" {
name = "prod-router"
network = module.vpc.network_name
region = "us-central1"
}
```
You know the drill. Need another subnet? Update the list. Need programmatic logic? Good luck with `for` expressions or bringing in another external module.

**After: CDKTF Go**
Same infrastructure. Now it's just Go code.

```go
package main

import (
"github.com/aws/constructs-go/constructs/v10"
"github.com/hashicorp/terraform-cdk-go/cdktf"
"github.com/cdktf/cdktf-provider-google-go/google/v8/computeNetwork"
"github.com/cdktf/cdktf-provider-google-go/google/v8/computeSubnetwork"
"github.com/cdktf/cdktf-provider-google-go/google/v8/computeRouter"
)

func NewProdNetworkStack(scope constructs.Construct, id string) cdktf.TerraformStack {
stack := cdktf.NewTerraformStack(scope, &cdktf.TerraformStackConfig{
Context: &cdktf.TerraformStackContext{Namespace: id},
})

// Config from env or variables - it's just Go.
project := "my-project"

network := computeNetwork.NewComputeNetwork(stack, jsii.String("prod_vpc"), &computeNetwork.ComputeNetworkConfig{
Name: jsii.String("prod-vpc"),
AutoCreateSubnetworks: jsii.Bool(false),
Project: &project,
})

subnetA := computeSubnetwork.NewComputeSubnetwork(stack, jsii.String("subnet_a"), &computeSubnetwork.ComputeSubnetworkConfig{
Name: jsii.String("subnet-a"),
IpCidrRange: jsii.String("10.10.0.0/24"),
Region: jsii.String("us-central1"),
Network: network.Id(),
Project: &project,
})

_ = computeRouter.NewComputeRouter(stack, jsii.String("cloud_router"), &computeRouter.ComputeRouterConfig{
Name: jsii.String("prod-router"),
Network: network.Name(),
Region: subnetA.Region(),
Project: &project,
})

return stack
}
```

**The payoff:**
- **Logic is code.** Need to create subnets based on a list? It's a `for` loop. Need to fetch data from an API before defining resources? Make a function.
- **No more HCL functions.** String manipulation, conditionals, loops - use the full language.
- **Refactoring.** Rename a variable? Your IDE does it. Extract common patterns into functions or structs.
- **Type safety.** Compiler catches a lot of dumb mistakes before `plan`.

**The cost:**
- **State migration.** Used `terraform state rm` and `terraform import` for each resource. Took a day for this stack. Tedious but one-time.
- **CDKTF is another layer.** Sometimes you fight the CDKTF abstractions. Docs are thinner.
- **Team buy-in.** Need developers comfortable with Go, not just HCL.

**Worth it?** For us, yes. The stack is more maintainable. New features are added faster. The initial migration pain was a solid investment. Would only recommend if your team already knows and wants to use a real programming language. If not, you're just adding complexity.


slow pipelines make me cranky


   
Quote