Hi tf community,
I have a question on how to use setintersection() and keys() on vars. I have used it on locals and it worked as I expected, but it doesn’t produce the same results on vars. wondering how I can use them on vars to achieve what I wanted to do?
# local.regions is to serve as the setintersection control set of strings
# as the keys(s_v) has non-region-related keys
locals {
regions = ["region-1", "region-2"]
}
# local.local_obj has the exact same data structure as of var.var_obj
locals {
local_obj = {
collection_local = {
subnet_local = {
other_key = "some-value"
region-1 = "cidr-for-region-1-for-local-obj"
# region-2 = "cidr-for-region-2-for-local-obj"
}
}
}
}
# var.var_obj is a map(map(object())) data structure, outter map is the collection of subnets,
# inner map is the subnets within a collection, object is the subnet config
variable "var_obj" {
type = map(
map (
object ({
other_key = string
region-1 = optional(string)
region-2 = optional(string)
})
)
)
default = {
collection_var = {
subnet_var = {
other_key = "something-other-value"
region-1 = "cidr-for-region-1-for-var-obj"
# region-2 = "cidr-for-region-2-for-var-obj"
}
}
}
}
# local.transform-local and local.transform-var are two transforming locals to suite subnet resource needs
locals {
transform-local = flatten([
for c_k,c_v in local.local_obj : [
for s_k, s_v in c_v : [
for rg in setintersection(local.regions, keys(s_v)) : {
name = "${rg}-${s_k}"
region = rg
ip_cidr_range = s_v[rg]
}
]
]
])
transform-var = flatten([
for c_k,c_v in var.var_obj : [
for s_k, s_v in c_v : [
for rg in setintersection(local.regions, keys(s_v)) : {
name = "${rg}-${s_k}"
region = rg
ip_cidr_range = s_v[rg]
}
]
]
])
}
# as you can see, the transform-local and transform-var are doing the exact same thing: filtering a subset of the keys (when they are either region-1 or region-2, but not other_key). and when a local, or var value has only one of the region, then I want only that existing region's record to be produced by the transformation result.
# output.contrast is to show the different behavior of setintersection() and keys() on local and var
# as commenting out the region-2 in local and var has different behavior,
# local behaves correctly, not producing region-2 record at all,
# but var transformer produced an incomplete region-2 record without ip_cidr_range, which will break the resource code execution
output "contrast" {
value = {
transform-local = local.transform-local
transform-var = local.transform-var
}
}
if uncommenting the region-2 line, setintersection() and keys() behave exactly the same on local and var:
output:
contrast : {
transform-local : [
{
name : "region-1-subnet_local"
ip_cidr_range : "cidr-for-region-1-for-local-obj"
region : "region-1"
}
{
name : "region-2-subnet_local"
ip_cidr_range : "cidr-for-region-2-for-local-obj"
region : "region-2"
}
]
transform-var : [
{
name : "region-1-subnet_var"
ip_cidr_range : "cidr-for-region-1-for-var-obj"
region : "region-1"
}
{
name : "region-2-subnet_var"
ip_cidr_range : "cidr-for-region-2-for-var-obj"
region : "region-2"
}
]
}
but if I comment out the region-2 line (as shown in code at the top), transform-var output is not desirable as it produces something that will cause malfunction
output:
contrast : {
transform-local : [
{
name : "region-1-subnet_local"
ip_cidr_range : "cidr-for-region-1-for-local-obj"
region : "region-1"
}
]
transform-var : [
{
name : "region-1-subnet_var"
ip_cidr_range : "cidr-for-region-1-for-var-obj"
region : "region-1"
}
{
name : "region-2-subnet_var"
region : "region-2"
}
]
}
a Hashicorp developer was trying to explain to me this should be expected behavior, but
- I don’t understand the explanation, as the default of var.var_obj has the region-2 commented out as well, same as in local.local_obj, the values are the same…
- how can I filter out the missing region-2 so no incomplete record will be created?
the explanation given:
the value of var.var_obj
has a region-2
attribute and therefor shows region-2
values in the output. The difference between the var and local output is because the values are different. If you have more questions, please reference the community forums where there are many more user who may offer assistance.
Thanks for helping.