terraform

CDK for Terraform 0.16 improves automatic HCL conversion

CDK for Terraform v0.16 improves automatic conversion of configuration code from HCL to supported languages by enabling type coercion and providing better support for iterators and functions.

CDK for Terraform (CDKTF) lets you write HashiCorp Terraform configurations in your choice of TypeScript, Python, C#, Java, or Go, and still benefit from the full ecosystem of Terraform providers and modules. CDKTF reached its GA in August, 2022.

Today, we’re releasing CDKTF 0.16, which improves the ability of the Cloud Development Kit (CDK) to convert HCL to TypeScript, Python, C#, Java, or Go. These improvements, primarily in the CDKTF CLI’s convert command, include:

  • Type coercion based on Terraform provider schema: When converting from HCL to a supported language, the CDKTF convert command now matches the type of the value being assigned to an attribute and converts it to the correct type.
  • Enhanced iterators support: Iterators are used by CDKTF to replace attributes like for_each and dynamic blocks within Terraform. The conversion from HCL in the 0.16 release now also uses iterators when possible, reducing the need for escape hatches.
  • Better functions support: The generated code now uses CDKTF library functions to replace Terraform HCL functions, instead of relying solely on string templating. This improves the readability of the code.

Apart from improvements in the convert command, 0.16 upgrades the underlying JSII compiler to use TypeScript 5. This change will improve the performance of CDKTF synth and get. We’ve also updated the minimum version of Node.js to 16 as Node.js 14 will be hitting end of life on April 30, 2023.

»The convert command

The CDKTF CLI released the convert command in version 0.5, which allowed users to automatically convert their existing Terraform HCL code to a CDKTF-compatible language automatically. This is really useful for teams with either an HCL background or a HCL code base who would like to use CDKTF.

While we have been releasing minor bug fixes and improvements to convert, the 0.16 release focuses on improving the conversion process. More information about usage and parameters to the convert command can be found in our documentation.

To give an example of the conversion process, consider the following Terraform HCL:

provider "aws" {
  region  = "us-west-2"
}
 
resource "aws_instance" "app_server" {
  ami           = "ami-830c94e3"
  instance_type = "t2.micro"
 
  tags = {
    Name = "ExampleAppServerInstance"
  }
}

When converted into TypeScript through the convert command, it becomes a construct that can be used directly within a CDKTF application:

import * as constructs from "constructs";
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
 
class MyConvertedCode extends constructs.Construct {
  constructor(scope: constructs.Construct, name: string) {
    super(scope, name);
    new aws.provider.AwsProvider(this, "aws", {
      region: "us-west-2",
    });
    new aws.instance.Instance(this, "app_server", {
      ami: "ami-830c94e3",
      instanceType: "t2.micro",
      tags: {
        Name: "ExampleAppServerInstance",
      },
    });
  }
}

»Type coercion based on Terraform provider schema

Since CDKTF uses Terraform to perform any infrastructure changes, problems like type mismatches are hard to detect until the terraform plan stage. Prior to the 0.16 release, the convert command could generate invalid code because it would try to convert by only looking at the HCL source code.

With 0.16, convert also compares the type being generated from HCL and matches it with the provider schema. In case of a type mismatch, it wraps the incoming value to the type expected by the attribute. This makes the conversion process a lot more accurate and results in fewer conversion errors.

Take a look at a simple contrived example:

resource "aws_route53_record" "my_record" {
  name    = "example.com"
  type    = "TXT"
  ttl     = "300"
  records = ["test"]
}

The schema for aws_route53_record marks ttl as a number here, so it seems like an error. However, Terraform automatically converts primitive types to match the schema, therefore the above code will not trigger an error within Terraform.

Contrary to that, CDKTF code wouldn’t allow that, since strongly typed languages will not allow a string to be assigned to a number type. To handle these scenarios, we built type coercion into convert. The code above will now generate the following:

new aws.route53Record.Route53Record(
  this,
  "my_record",
  {
    name: "example.com",
    records: ["test"],
    ttl: cdktf.Token.asNumber("300"),
    type: "TXT",
  }
);

Here, convert wraps the string value to a number before passing it to ttl. convert not only does this for primitive types, but also for more complex types like Maps, and Lists.

»Enhanced iterators support

Terraform HCL has meta-arguments that help users create multiple resources, like count, and for_each. There’s also the concept of dynamic blocks, which deals with complex resources that have repeated configurations within. The equivalent concept within CDKTF is called iterators.

In the 0.16 release, the count meta-attribute can also be represented as iterators through an escape hatch. For more details about usage and code examples, please refer to our documentation.

convert is now also able to use iterators to replace for_each, count, and even dynamic blocks. Previously convert reverted to using escape hatches for iterators.

»Using CDKTF functions when converting from built-in Terraform functions

HCL to CDKTF conversion is now able to convert Terraform functions to their corresponding CDKTF functions. This is nicer for readability as well as being able to get autocomplete and documentation support from the IDE for CDKTF projects. convert also uses functions representing unary, binary, or ternary expressions.

If we take the contrived example of an HCL expression containing functions and operators below:

replace("hello-${22+22}", "44", "world")

This now gets converted into:

cdktf.Fn.replace("hello-" + cdktf.Token.asString(cdktf.Op.add(22, 22)), "44", "world")

»What's next for CDKTF?

The upcoming CDKTF 0.17 release will focus on building on top of the 0.16 improvements, especially with regard to converting HCL to languages like Java, C#, and Go.

»Try CDK for Terraform

If you’re new to the project, these tutorials for CDK for Terraform are the best way to get started. You can dive deeper into our documentation with this overview of CDKTF.

Whether you’re still experimenting or actively using CDK for Terraform, we’d love to hear from you. Please file any bugs you encounter, let us know about your feature requests, and share your questions, thoughts, and experiences in the CDK for Terraform discussion forum.


Sign up for the latest HashiCorp news