зеркало из
1
0
Форкнуть 0
terraform-azurerm-naming/docs/cdktf_usage.md

3.7 KiB

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.

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

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

        "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.

	// 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.

	// 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