Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding workaround documentation for cdktf usage #120

Merged
merged 2 commits into from
Mar 19, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions docs/cdktf_usage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Notes about module usage with `cdktf`

When working within `cdktf`, the bindings that are autogenerated for the module provide a return type of a `map` instead of a `string`.

For example, calling `ResourceGroupOutput()` yields `${module.resourceNaming.resource_group}`, where the `resource_group` output value is actually a map. When running `tf plan`, we're greeted with the error `module.resourceNaming.resource_group is object with 8 attributes`

CDKTF synthesized `cdktf.json` appears as.

```json
"name": "${module.resourceNaming.resource_group}"
```

Though, the needed cdktf.json is. Note the reference to the `name` object.

```json
"name": "${module.resourceNaming.resource_group.name}"
```

## Problem

Details can be found in the comment at https://github.com/hashicorp/terraform-cdk/issues/3477#issuecomment-1926338050

> It is true that all outputs are currently typed as strings. This is a current shortcoming that happens because types of outputs are inferred by Terraform and not part of the configuration as its written. This means that a future version of cdktf get has to invoke parts of Terraform to parse and evaluate the module in order to get the types right.

> For your case it should be possible to use Fn.Lookup(someModule.ResourceGroupOutput(), "name") to get to the right value. There is also Token.AsList() which can be used to turn the string output into a list token which would be the correct output type we'd expect.

## Workaround

The workaround involves using `cdktf.Fn_Lookup`. Function documentation state that `Fn_lookup()` **retrieves the value of a single element from a map, given its key. If the given key does not exist, the given default value is returned instead.**

Example `ResourceGroupOutput()` that generates the incorrect output.
```go
// the following yields invalid cdk.tf.json output. cdk.tf.json contains the following ...
// "location": "Canada Central",
// "name": "${module.resourceNaming.resource_group}"
// ... which is invalid because the name is not a string literal, we need to access the map key as such
// "name": "${module.resourceNaming.resource_group.name}"
resourcegroup.NewResourceGroup(stack, jsii.String("resource_group"), &resourcegroup.ResourceGroupConfig{
Name: n.ResourceGroupOutput(), // ResourceGroupOutput returns a string instead of a Map object.
Location: jsii.String("Canada Central"),
})
```

To work-around, instead of accessing `ResourceGroupOutput()` directly, pass this object through the `cdktf.Fn_Lookup` and the `name` property.

```go
// See comment at https://github.com/hashicorp/terraform-cdk/issues/3477#issuecomment-1926338050
// Fn_Lookup states: retrieves the value of a single element from a map, given its key. If the given key does not exist,
// the given default value is returned instead.
// Using the following will generate the correct cdk.tf.json output. For example... Notice the name field is now referenced correctly.
// "resource_group_workaround": {
// "//": {
// "metadata": {
// "path": "naming-output-failure-example/resource_group_workaround",
// "uniqueId": "resource_group_workaround"
// }
// },
// "location": "Canada Central",
// "name": "${module.resourceNaming.resource_group.name}"
// }
resourcegroup.NewResourceGroup(stack, jsii.String("resource_group_workaround"), &resourcegroup.ResourceGroupConfig{
Name: cdktf.Token_AsString(cdktf.Fn_Lookup(n.ResourceGroupOutput(), jsii.String("name"), nil), nil),
Location: jsii.String("Canada Central"),
})
```

## References

* https://github.com/Azure/terraform-azurerm-naming/issues/64
* https://github.com/Azure/terraform-azurerm-naming/issues/107
* https://github.com/hashicorp/terraform-cdk/issues/3477
* https://github.com/jesseward/cdktf-aznaming-output-failure-example
Loading