I feel like I've tried this a bunch of different ways but I may be a little off in terms of how I am calling these variables. I have the following code:
config_rule_params = {
"access_keys_rotated" = {
"input_parameters" = "{\"maxAccessKeyAge\": \"90\"}",
"maximum_execution_frequency" = "TwentyFour_Hours",
"source" = {
"owner" = "AWS",
"source_identifier" = "ACCESS_KEYS_ROTATED"
}
},
"acm_certificate_expiration_check" = {
"input_parameters" = "{\"daysToExpiration\": \"30\"}",
"maximum_execution_frequency" = "TwentyFour_Hours",
"source" = {
"owner" = "AWS",
"source_identifier" = "ACM_CERTIFICATE_EXPIRATION_CHECK"
},
"scope" = {
"compliance_resource_types" = "AWS::ACM::Certificate"
}
}
}
}
resource "aws_config_config_rule" "parameterised_config_rules" {
for_each = local.config_rule_params
name = each.key
input_parameters = each.value.input_parameters
maximum_execution_frequency = each.value.maximum_execution_frequency
dynamic "source" {
for_each = local.config_rule_params[*].source[*]
content {
owner = each.value.owner
source_identifier = each.source_identifier
}
}
dynamic "scope" {
for_each = local.config_rule_params[*].scope[*]
content {
compliance_resource_types = each.value.compliance_resource_types
}
}
}
Eventually I will have a ton of rules added under config_rule_params
and not all of them will have source
, scope
or even other parameters. How can I properly call these variables when creating my resource? Currently getting the following error:
Error: Unsupported attribute
on .terraform/modules/baselines_config_rules_module/modules/baseline-config-rules/main.tf line 53, in resource "aws_config_config_rule" "parameterised_config_rules":
53: for_each = local.config_rule_params[*].source[*]
This object does not have an attribute named "source".
Error: Unsupported attribute
on .terraform/modules/baselines_config_rules_module/modules/baseline-config-rules/main.tf line 61, in resource "aws_config_config_rule" "parameterised_config_rules":
61: for_each = local.config_rule_params[*].scope[*]
This object does not have an attribute named "scope".
ERROR: Job failed: exit code 1
You're correctly using the [*]
operator as a concise way to adapt a value that might either be null or not into a list with either zero or one elements, but there are two things to change here:
dynamic
block is, by default, the name of the block you are generating. each
is the iterator symbol for the top-level resource itself, even inside a dynamic
block.each.value
as part of the for_each
expression in your dynamic
block, to refer to the current element of local.config_rule_params
.Putting those together, we get something like this:
resource "aws_config_config_rule" "parameterised_config_rules" {
for_each = local.config_rule_params
name = each.key
input_parameters = each.value.input_parameters
maximum_execution_frequency = each.value.maximum_execution_frequency
dynamic "source" {
for_each = each.value.source[*]
content {
owner = source.value.owner
source_identifier = source.value.source_identifier
}
}
dynamic "scope" {
for_each = each.value.scope[*]
content {
compliance_resource_types = scope.value.compliance_resource_types
}
}
}
Notice that in the dynamic "source"
block the current element is source.value
, while in the dynamic "scope"
block the current element is scope.value
. Because of that, it's valid to also use each.value
in those dynamic
blocks, and so you can refer to both levels of repetition together when building out these nested blocks.