Below is the locals sg_rules
output I am getting check the value for cidr_blocks
and security_group_id
variables. At a time either of the values will be
"security_group_id" = tostring(null)
or
"cidr blocks" = tolist([])
Locals Outputs :
sg_rules = {
"testsg_1-ingress-1521-tcp-10.80.0.10/32" => {
"cidr blocks" = tolist(["10.80.0.10/32",])
"description" = "1521 tcp ingress"
"from_port" = 1521
"protocol" = "tcp"
"security_group_id" = tostring(null)
"sg_name" = "testsg_1"
"to_port" = 1521
"type" = "ingress"
},
"testsg_2-ingress-1524-tcp-sg-23423439" => {
"cidr blocks" = tolist([])
"description" = "1524 tcp ingress"
"from_port" = 1524
"protocol" = "tcp"
"security_group_id" = "sg-23423439"
"sg_name" = "testsg_2"
"to_port" = 1524
"type" = "ingress"
}
}
using the above local in the aws_security_group_rule
resource like below getting conflicting error, that both cidr_blocks
and source_security_group_id
should not exist at the same time.
resource "aws_security_group_rule" "tcp_cidr_blocks" {
for_each = { for key, sg_rule in local.sg_rules : key => sg_rule }
type = each.value.type
from_port = each.value.from_port
to_port = each.value.to_port
cidr_blocks = each.value.cidr_blocks
source_security_group_id = each.value.security_group_id
protocol = each.value.protocol
security_group_id = aws_security_group.security_groups.id
}
what I am expecting as either of inputs are null, at a time, so it shouldn’t conflict and use either cidr_blocks
or source_security_group_id
at a time.
Error:
Error: Conflicting configuration argumentsnn with
module.sg.aws_security_group_ru1e.tcp_cidr_blocks["testsg_2-ingress-1524-tcp-sg-23423439"],n on sg/main.tf line 30, in resource
"aws_security_group_rule" "tcp_cidr_blocks" : n 30:
source_security_group_id
= each.value.security_group_idnn"security_group_id":
conflicts with cidr_blocksn",
3
Answers
The second object in your example has:
"cidr blocks" = tolist([])
"security_group_id" = "sg-23423439"
An empty list is not null, so for this object both of the arguments are set at once.
If you set the CIDR blocks attribute to
tolist(null)
instead then you will have a null value for that argument, which may allow this validation rule to pass.This validation rule is implemented by the
hashicorp/aws
provider in itsaws_security_group_rule
implementation and so exactly how it will interpret these cases is decided by how the logic in the provider is written — the provider could potentially choose to treat an empty list the same as unset — but a null value for a resource argument is always exactly equivalent to leaving it unset and so making sure at least one of them is really null is the most robust way to configure this, which should work regardless of how the provider plugin is implemented.There are a couple of issues with the current code, one being the
=>
which is not a valid syntax in Terraform:The second is explicitly casting to types, e.g.,
tolist(["10.80.0.10/32",])
andtostring(null)
. If the local variablesg_rules
is fixed to look like this:Following that change, using the ternary operator on your code will result in
terraform plan
working:Setting
cidr_blocks
orsource_security_group_id
tonull
will tell terraform to treat it is an absence of the argument which means it will not complain about conflicting arguments.I will leave my answer here just as another example of how to work with JSON files (I imported the security group rules first as I was working with existing resources):