# 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