Define Resources
Resource definitions and properties vary depending on the type of resource and the provider. Consult your provider’s documentation for a full list of available resources and their configuration options. The following example defines a DynamoDB table resource on the AWS provider.Scope
You can instantiate the same resource multiple times throughout your infrastructure. For example, you may want to create multiple S3 Buckets with different configurations. Instances that share the same parent element are considered to be part of the same scope. You must set a differentname property for each instance to avoid naming conflicts.
Refer to the constructs documentation for more details and an example.
References
You can reference resource properties throughout your configuration. For example, you may want to use the name of a parent resource when assigning names to related child resources. Refer to your provider’s documentation for a full list of available properties for each resource type. To create references, callmyResource.<propertyName> on the resource instance. For example, you could use myResource.name to retrieve the name property from myResource. Terraform does not support passing an entire block (e.g. exampleNamespace.metadata) into a resource or data source, so you must create a reference for each individual property.
References are also useful when you need to track logical dependencies. For example, Kubernetes resources live in a namespace, so a namespace must exist before Terraform can provision the associated resources. The following example uses a reference for the namespace property in the the deployment. This reference tells Terraform that it needs to create the namespace before creating the resources.
Refactoring & Renaming Resources
When working with your infrastructure definitions and the need arises to refactor or rename resources without destroying and recreating them, you can leverage themoveTo function like so:
Provisioners
Provisioners can be used to model specific actions on the local machine or on a remote machine in order to prepare servers or other infrastructure objects for service. You can find more information on the concept of provisioners in the Terraform docs. You can pass theprovisioners key to define a list of provisioners, connections can be configured with the connection key. A working example can be found at examples/typescript/provisioner.
If you need to use the special self object that can only be used in provisioner and connection blocks to refer to the parent resource you can use the TerraformSelf class like this: TerraformSelf.getString("public_ip").
Custom Condition Checks
If you need to ensure a condition is met either before or after a resource was created you can specify conditions. To add one configure thelifecycle key on your resource with an object containing a precondition and / or a postcondition. These keys take a list of conditions with a condition key containing a Terraform Expression to be evaluated and an errorMessage key containing a string to be displayed if the condition is not met.
Importing Resources
If you have existing resources that you want to manage with CDKTN, you can import them into your CDKTN application. The best way to do this is using theimport block feature of Terraform >= 1.5. You can do this in CDKTN either with a specified configuration or without.
How To Import
To import a resource, first instantiate an instance of the resource type you wish to import – in our case we’ll be using an S3Bucket. No configuration is explicitly needed. You then call theimportFrom method on the resource object. This method takes the ID of the resource to be imported as the first argument and the provider as an optional second. The provider is only required if you have multiple providers of the same type in your configuration.
importFrom call and the resource will become managed by CDKTN.
Please note that Terraform is going to update existing fields on the imported resource to match your configuration as it puts it under management. In our case we did not define any specific properties on the S3Bucket which causes Terraform e.g. to remove the tags currently defined on the resource (as can be seen on the plan below). If you want to keep existing settings, you can run a plan first, add everything that Terraform would change to your resource config, and only then apply the changes.
Your output might look as follows:
Generate Configuration For Import
If you don’t want to specify the configuration of your imported resource yourself you can use the static methodgenerateConfigForImport on the class of the resource you want to import. This method takes the scope as the first argument, the construct id of the resource to import to (as will be given in the generated config returned), the resource id of the resource to be imported, and the provider as an optional fourth. The provider is only required if you have multiple providers of the same type in your configuration.
cdktn plan <stack-name> Terraform will generate code for the resource you are importing and CDKTN will convert it to the language you are using.
Your output might look as follows:
generateConfigForImport. Finally, follow the steps outlined in the section “How To Import” above. On apply, your resource will be imported, then becoming managed by CDKTN.
Escape Hatch
Terraform provides meta-arguments to change resource behavior. For example, thefor_each meta-argument creates multiple resource instances according to a map, or set of strings. The escape hatch allows you to use these meta-arguments to your CDKTN application and to override attributes that CDKTN cannot yet fully express.
The following example defines a provisioner for a resource using the addOverride method.
cdktn synth, CDKTN generates a Terraform configuration with the provisioner added to the JSON object.
addOverride. The attribute in the escape hatch is in snake case because the Terraform JSON configuration uses snake case instead of camel case.
cdktn synth, CDKTN generates a Terraform configuration with the value overwritten.
resource.addOverride("configurations.0.https", true).
Escape Hatch for Dynamic Blocks
Terraform configurations sometimes usedynamic blocks to create related resources based on dynamic data, or data that is only known after Terraform (or OpenTofu) provisions the infrastructure. For example, you could create a series of nested blocks for a series of Virtual Private Cloud (VPC) ingress ports. A dynamic block loops over a complex value and generates a nested resource block for each element of that complex value.
In CDKTN applications, you must use an escape hatch when you want to loop through a dynamic value like a TerraformVariable or a resource output.
To use an escape hatch to loop over dynamic data, you must:
- Set the first argument of
addOverrideto bedynamic.<attribute_name>. - Create a
for_eachvalue for the second argument and set it to the list you want to iterate over. - Take the attribute as base for the reference when you reference values from the list. For example, use
"${<attribute_name>.value.nested_value}".
TerraformVariable.
Special Cases
Built-in terraform_data resource
The terraform_data resource implements the standard resource lifecycle but does not directly perform any other actions. In CDKTN, the resource is exposed as the TerraformData class and you can import it directly from the cdktn package.
Large Resource Configurations
A few individual Terraform Resources have very deeply nested schemas with a lot of attributes. This blows up the config classes and slows down the code generation for languages besides Typescript. To work around this we sometimes limit the depth of the config classes and useany on deeper level, some attributes we directly expose as any on the top level config class.
awsProvider:aws_quicksight_template.definition,aws_quicksight_dashboard.definition, andaws_quicksight_analysis.definitionare set toanywafv2related resources have a lot of deeply nested attributes that might be skipped