[Terraform] Conditionally Add Key/Value to Map

Recently, I was setting up a Kubernetes ingress using Terraform, and faced the case when based on an input variable I have to add a new annotation to the ingress configuration or not.
In my use case, I had to specify a security group to be attached to the Load Balancer created by the ingress controller. The thing was that I also wanted an easy way to remove the security group, without changing the Terraform code.
Searching the web, I came across this Reddit post, but the solution proposed by the user Bitflight was not what I really wanted, so I came with a similar approach that I will present next.
Let’s say we have the following local variable named ingress_annotations_required
that contains required annotations for the Kubernetes ingress, and another optional variable named security_group_id
that can be passed as input variable at apply time.
# variables.tf
variable "security_group_id" {
default = ""
definition = "ID of the Security Group that we want to attach to the Kubernetes ingress"
}
# main.tf
locals {
ingress_annotations_required = {
"kubernetes.io/ingress.class" = "alb"
"alb.ingress.kubernetes.io/scheme" = "internet-facing"
"alb.ingress.kubernetes.io/target-type" = "ip"
"alb.ingress.kubernetes.io/listen-ports" = [{ "HTTP": 80 }, { "HTTPS": 443 }]
}
}
If the variable security_group_id
is set at apply time, we want to add to the ingress annotations the key alb.ingress.kubernetes.io/security-groups
with the value provided by the variable security_group_id
. To do so, we can set a new local based on a conditional expression that checks if the variable security_group_id
holds the default value (which is the empty string "”
) or not. If it holds the default value, we set an empty map
, if not, we will create a key-value map with our desired information.
locals {
ingress_annotations_optional = {
security_group = var.security_group_id == "" ? {} : { "alb.ingress.kubernetes.io/security-groups" = var.security_group_id }
}
}
Finally, we can merge the two local variables, using the merge function from Terraform.
locals {
ingress_annotations = merge(
local.ingress_annotations_required,
local.ingress_annotations_optional["security_group"]
)
}
Then, we can use the formed merged map in the kubernetes_ingreess resource.
resource "kubernetes_ingress" "ingress" {
[...]
metadata {
[...]
annotations = local.ingress_annotations
}
[...]
}
Now, when we apply the Terraform script, if we pass the variable security_group_id
the security group annotation is added to the map, and implicitly to the Kubernetes ingress. If we don’t pass the variable, the annotation is not set (or it is removed if it was previously set).
Thank you for reading this post, I hope that you found it useful. Here you can find the Gist with the full code from the example presented above.