Referencing map from a TF module output, in `default_tags` argument in `AwsProvider`, returns unexpected output in TF plan

Hey team.

I’m trying to define default_tags in AwsProvider from an output of another module.
This is how the variable definition and output look like in the TF module config:

variable "aws_common_tags" {
  description = "(Optional) Common AWS tags to be used on all AWS resources created by Terraform"
  type        = map(any)
  default = {
    auto-stop   = "no"
    auto-delete = "no"
  }
}

output "aws_common_tags" {
  description = "Common AWS tags to be used on all AWS resources created by Terraform"
  value       = var.aws_common_tags
}

This is the module definition followed by the provider definition, followed by another module that uses the provider, in the CDKTF code:

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

        common_module = TerraformHclModule(self, "common", source="../../../../../modules/common",
                                           skip_asset_creation_from_local_modules=True)

        pipeline_aws_provider = AwsProvider(self, "pipeline-provider", region="us-east-1",
                                            profile="udid+datacollection-Admin",
                                            shared_config_files=common_module.get_list("aws_shared_config_files"),
                                            shared_credentials_files=common_module.get_list(
                                                "aws_shared_credentials_files"),
                                            default_tags=[
                                                {
                                                    "tags": common_module.get("aws_common_tags")
                                                }
                                            ])

        pipeline_module = TerraformHclModule(self, "pipeline",
                                             source = "../../../../../modules/pipeline",
                                             variables={
                                                 "glue_crawler_schedule": "0 1 * * ? *",
                                                 "kubecost_ca_certificates_list": [
                                                     {
                                                         "cert_path": "~/openssl/ca/certs/ca.cert.pem",
                                                         "cert_secret_name": "kubecost",
                                                         "cert_secret_allowed_principals": [
                                                             "arn:aws:iam::111111111111:root",
                                                             "arn:aws:iam::111111111111:role/Admin"]
                                                     }
                                                 ]
                                             },
                                             skip_asset_creation_from_local_modules=True)

However, in the plan output, the tags_all block shows "$jsii.byref" = "Object@10003", as can be seen below:

kubecost_cid    # module.pipeline.aws_secretsmanager_secret.kubecost_ca_cert_secret[0] will be updated in-place
                ~ resource "aws_secretsmanager_secret" "kubecost_ca_cert_secret" {
                      id                             = "arn:aws:secretsmanager:us-east-1:111111111111:secret:test-abcdef"
                      name                           = "secret"
                      tags                           = {}
                    ~ tags_all                       = {
                        + "$jsii.byref" = "Object@10003"
                      }
                      # (4 unchanged attributes hidden)
                  }

As opposed to that, when I use common_module.get("aws_common_tags") in TerraformOutput, it works:

TerraformOutput(self, "aws_common_tags", value=common_module.get("aws_common_tags"))
kubecost_cid  Changes to Outputs:
                + aws_common_tags                         = {
                    + auto-delete = "no"
                    + auto-stop   = "no"
                  }

Any idea why it behaves like this specifically in the default_tags argument in AwsProvider?

I believe the jsii runtime (that cdktf uses) doesn’t understand what type of value it’s working with when used in the other context.
You may be able to wrap in something like Token.as_string_map or Fn.to_map.
You could also try explicitly specifying types for the default tags.

1 Like

Wrapping in Token.as_string_map worked (and in Fn.tomap didn’t).
Thanks!