> ## Documentation Index
> Fetch the complete documentation index at: https://cdktn.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# HCL Interoperability - CDK Terrain

> Use configurations written in HCL and configurations written in CDK for Terraform together to define and provision infrastructure.

Terraform requires infrastructure configuration files written in either [HashiCorp Configuration Language (HCL)](https://developer.hashicorp.com/terraform/language/syntax/configuration) or JSON syntax. CDK Terrain (CDKTN) works by translating configurations defined in an imperative programming language to JSON configuration files for Terraform.
Starting from version 0.20, CDKTN can also generate Terraform HCL as output by setting the `--hcl` flag when running `cdktn synth`.

CDKTN may not be the right choice for every team and project within your organization. For example, some teams may already be very familiar with Terraform and have created HCL modules, providers, etc. To provide flexibility, CDKTN applications are interoperable with Terraform projects written in HCL. Specifically:

* CDKTN applications can use all existing Terraform [providers](/concepts/providers) and HCL [modules](/concepts/modules).
* CDKTN can generate modules that HCL Terraform projects can use in their configurations.

This page shows how you can interoperate HCL and CDK Terrain configuration.

## CDKTN to HCL

The following example is a CDKTN application that uses the `hashicorp/random` provider to generate a random name.

<CodeGroup>
  ```ts TypeScript theme={null}
  import { Construct } from "constructs";
  import { TerraformOutput, TerraformStack, TerraformVariable } from "cdktn";
  import { Pet } from "@cdktn/provider-random/lib/pet";
  import { RandomProvider } from "@cdktn/provider-random/lib/provider";

  export class HCLInteropStack extends TerraformStack {
    constructor(scope: Construct, name: string) {
      super(scope, name);

      new RandomProvider(this, "default", {});
      const petNameLength = new TerraformVariable(this, "petNameLength", {
        type: "number",
        default: 2,
        description: "Pet name length",
      });

      const myPet = new Pet(this, "example", {
        length: petNameLength.value,
      });

      new TerraformOutput(this, "name", {
        value: myPet.id,
      });
    }
  }
  ```

  ```java Java theme={null}
  import software.constructs.Construct;
  import io.cdktn.cdktn.TerraformStack;
  import io.cdktn.cdktn.TerraformOutput;
  import io.cdktn.cdktn.TerraformOutputConfig;
  import io.cdktn.cdktn.TerraformVariable;
  import io.cdktn.cdktn.TerraformVariableConfig;
  import io.cdktn.cdktn.App;
  import imports.random.provider.RandomProvider;
  import imports.random.pet.Pet;
  import imports.random.pet.PetConfig;

  public class MainHCL extends TerraformStack {

      public MainHCL(Construct scope, String id) {
          super(scope, id);

          new RandomProvider(this, "default");
          TerraformVariable petNameLength = new TerraformVariable(this, "petNameLength", TerraformVariableConfig.builder()
                  .type("number")
                  .defaultValue(2)
                  .description("Pet name length")
                  .build());

          Pet myPet = new Pet(this, "example", PetConfig.builder()
                  .length(petNameLength.getNumberValue())
                  .build());

          new TerraformOutput(this, "name", TerraformOutputConfig.builder()
                  .value(myPet.getId())
                  .build());
      }

      public static void main(String[] args) {
          final App app = new App();
          new MainHCL(app, "random-pet-module");
          app.synth();
      }
  }
  ```

  ```python Python theme={null}
  from constructs import Construct
  from cdktn import App, TerraformOutput, TerraformStack, TerraformVariable
  from imports.random.pet import Pet
  from imports.random.provider import RandomProvider

  class HclInteropStack(TerraformStack):
      def __init__(self, scope: Construct, name: str):
          super().__init__(scope, name)

          RandomProvider(self, "default")
          petNameLength = TerraformVariable(self, "petNameLength",
                              type="number",
                              default=2,
                              description="Pet name length"
                          )

          myPet = Pet(self, "example",
                      length=petNameLength.number_value
                  )

          TerraformOutput(self, "name",
              value=myPet.id
          )
  # app = App()
  # HclInteropStack(app, "random-pet-module")
  # app.synth()
  ```

  ```csharp C# theme={null}
  using System;
  using System.IO;
  using System.Collections.Generic;
  using System.Linq;
  using Constructs;
  using Io.Cdktn;
  using random.Provider;
  using random.Pet;

  namespace Examples
  {
      class HclInteropStack : TerraformStack
      {
          public HclInteropStack(Construct scope, string name) : base(scope, name)
          {
              new RandomProvider(this, "default", new RandomProviderConfig { });

              var petNameLength = new TerraformVariable(this, "petNameLength", new TerraformVariableConfig
              {
                  Type = "number",
                  Default = 2,
                  Description = "Pet name length"
              });

              var myPet = new Pet(this, "example", new PetConfig
              {
                  Length = petNameLength.NumberValue
              });

              new TerraformOutput(this, "name", new TerraformOutputConfig
              {
                  Value = myPet.Id
              });
          }
      }
  }
  ```

  ```go Go theme={null}
  import (
  	"github.com/aws/constructs-go/constructs/v10"
  	"github.com/aws/jsii-runtime-go"
  	"github.com/open-constructs/cdk-terrain-go/cdktn"
  	"github.com/open-constructs/cdk-terrain/examples/go/documentation/generated/hashicorp/random/pet"
  	random "github.com/open-constructs/cdk-terrain/examples/go/documentation/generated/hashicorp/random/provider"
  )

  func NewHclInteropStack(scope constructs.Construct, name string) cdktn.TerraformStack {
  	stack := cdktn.NewTerraformStack(scope, &name)

  	random.NewRandomProvider(stack, jsii.String("default"), &random.RandomProviderConfig{})

  	petNameLength := cdktn.NewTerraformVariable(stack, jsii.String("petNameLength"), &cdktn.TerraformVariableConfig{
  		Type:        jsii.String("number"),
  		Default:     jsii.Number(2),
  		Description: jsii.String("Pet name length"),
  	})

  	myPet := pet.NewPet(stack, jsii.String("example"), &pet.PetConfig{
  		Length: petNameLength.NumberValue(),
  	})

  	cdktn.NewTerraformOutput(stack, jsii.String("name"), &cdktn.TerraformOutputConfig{
  		Value: myPet.Id(),
  	})

  	return stack
  }

  ```
</CodeGroup>

To use this as a Terraform module, run `cdktn synth` and copy the resulting `cdktf.out/stacks/random-pet-module/cdk.tf.json` file out to the module directory in your HCL project.
By default, `cdktn synth` generates Terraform JSON, but starting from version 0.20, CDKTN can also generate Terraform HCL output by passing the `--hcl` flag to `cdktn synth`.

After you transfer the `cdk.tf.json` (or `cdk.tf`) file, you can reference the pet name module as you would any other HCL Terraform module.

```terraform theme={null}
terraform {
  required_providers {
    docker = {
      source = "hashicorp/random"
      version = "~> 3.1"
    }
  }
}

module "pet" {
    source = "./mods/pet"
    petNameLength = "1"
}

output "name" {
  value = module.pet.name
}
```

## HCL to CDKTN

HCL can be used with Terraform CDK in two ways. Converting HCL code directly to a CDKTN language, and using Terraform modules directly within CDKTN projects.

* In order to convert HCL to a CDKTN language, the [`cdktn convert`](/cli-reference/commands#convert) command can be used. It automatically translates HCL into a preferred CDKTN language. This is useful when working with an existing codebase that needs to be converted to CDKTN. Built-in functions in the HCL are emitted as `Fn.*` calls, which are subject to CDK Terrain's [function availability validation](/concepts/functions#function-availability-across-terraform-and-opentofu) against your project's declared [`targetVersions`](/create-and-deploy/configuration-file#declare-target-runtimes).

* While CDKTN has the ability to import HCL modules through `cdktn get` when referenced within the `cdktf.json` file, Terraform modules can also be referenced without generating language specific bindings. The [modules documentation](/concepts/modules) shows how to use existing Terraform modules in CDK Terrain projects.
