I’m trying to conditionally create a Dynamic statement, by checking if a variable is empty or not, while checking for some Regex patterns.
data "aws_organizations_organization" "this_org" {}
dynamic "statement" {
for_each = [for y in var.arns_with_access : y if length(regexall("\\*+", y)) == 0]
content {
actions = [
"kms:DescribeKey"
]
effect = "Allow"
principals {
type = "AWS"
identifiers = [statement.value]
}
resources = ["*"]
condition {
test = "StringEquals"
variable = "aws:PrincipalOrgID"
values = [
data.aws_organizations_organization.this_org.id,
]
}
}
}
That statement should only evaluate if var.arns_with_access
isn’t empty.
for_each = var.arns_with_access != "" {
for y in var.arns_with_access : y if length(regexall("\\*+", y)) == 0
} : 0
The above test does not work. Any suggestions, please?
Hi @manu.nz,
There are a few things about the example you shared which seem confusing to me:
- You test
var.arns_with_access != ""
, implying that var.arns_with_access
is a string, but then you use it in for y in var.arns_with_access
which implies that the variable has a collection type.
- If your
for_each
expression was intended to be a conditional expression, I notice that there is no ?
symbol after the first condition expression.
- Your
for
expression is delimited by braces {
}
and so will generate a mapping, but you’ve only provided one element expression y
. To generate a mapping you need to specify key => value
, where key
and value
are both expressions.
- The second result operand of your conditional is the expression
0
, which cannot possibly match the type of a for
expression with braces, since 0
is a number.
Because of the above I’m not entirely sure what your goal is here, but I can make a few guesses:
-
var.arns_with_access
is a list or set, rather than a string.
- Your
content
block doesn’t mention statement.key
so it seems that you don’t really need to set for_each
to a mapping, so we can use a sequence for
, with brackets [
]
instead.
- If
var.arns_with_access
is an empty list, you’d like to generate zero statement
blocks.
With those assumptions in mind, I would suggest the following as a starting point:
for_each = [
for y in var.arns_with_access : y
if length(regexall("\\*+", y)) == 0
]
After writing this out I realized I essentially just reproduced your original example, which suggests to me that I guessed incorrectly about what your goal is. If so, can you say some more about why this simpler expression isn’t sufficient for what you need?
Sorry for the misunderstanding and lack of information.
var.arns_with_access
is a list(string)
:
variable "arns_with_access" {
type = list(string)
default = []
}
The original code - I believe is checking if there is any wildcard (*
) in the value and if there is, it won’t evaluate the dynamic statement? - is:
for_each = [for y in var.arns_with_access : y if length(regexall("\\*+", y)) == 0]
My goal is to keep the original condition, but at the same time make data.aws_organizations_organization.this_org
conditional so it doesn’t evaluate if var.arns_with_access
is empty.
Hi @manu.nz,
A for
expression with an if
clause will never generate a resulting collection that has more elements than the input collection – var.arns_with_access
in your case.
So if we consider the example I included in my previous response:
for_each = [
for y in var.arns_with_access : y
if length(regexall("\\*+", y)) == 0
]
If var.arns_with_access
has zero elements (i.e. it’s empty) then the result of this for
expression must also necessarily be empty, since there are no elements for it to consider with the if
condition. So this expression already seems to achieve the goal you stated: if your var.arns_with_access
is empty then your for_each
argument will also be an empty list, and so the dynamic
block will generate zero statement
blocks.