Conditions in locals stanza

Hi Team,

I ran in to this problem and perhaps someone could help out here.

I have object type variables ( eg . test_roles) which is used in a module, at times when the module is called the variable test_role is not passed while calling the TF module.

Since the variable is a complex map of object, I have used locals to flatten it up and then use it various resources.

When the variable passed is empty, the resource fails, I was looking forward to sometime which can help by pass the resource if the variable is empty .

Eg.

variable "test_roles" {
    type = map(object({
      oidc = string
      asls = map(object({
        arns = list(string)
        bucket_name = map(string)
      }))
    }))}

example yaml input, which is converted to TC compatible format of TFVARs for Terraform to consume.

test_roles:
  eks_exmaple_cluster01:
    oidc: "ABC123"
    asls:
      R4-sampl01:
        trusted_role_arns:
          - testuser01
          - testuser02
        bucket_name:
          xxx:bucket01: "abc"
          xxx:bucket02: "bc"
      R4-sampl02:
        trusted_role_arns:
          - testuser01
          - testuser02
        bucket_name:
          xxx:bucket03: "abc"
          xxx:bucket04: "bc"

locals

flat_asl_map = flatten([
    for k, v in var.ads_asl_roles: [
      for k1, v1 in v.asls: {
        eks_name = k
        eks_oidc = v.oidc
        arns_list = distinct(v1.trusted_role_arns)
        asl = k1
        bucket_list = v1.bucket_name
        }]
  ])

Resource

resource  "aws_iam_role" "test_role"{
  for_each                = { for exe in local.flat_asl_map: "${exe.asl}" => exe } : {}
  name                    =  each.value.asl
  path                    = "/"
assume_role_policy      = templatefile("${path.module}/policies/assume-role.tmpl",
                            { account_id  = local.account_id,
                              region      = var.region,
                              asl         = each.value.asl,
                              oidc        = each.value.eks_oidc
                            } )
  tags =  merge({
    "eks_cluster" = each.value.eks_name,
    "Name" = each.value.asl,
    },
    each.value.bucket_list
  )
  lifecycle {
    create_before_destroy = true
  }
}

Error

Iteration over null value

  on locals.tf line 107, in locals:
 106: 
 107:     for k, v in var.test_roles: [
 108: 
 109: 
 110: 
 111: 
 112: 
 113: 
 114: 
 115: 
    |----------------
    | var.test_roles is null

A null value cannot be used as the collection in a 'for' expression.


Error: Invalid function argument

  on locals.tf line 116, in locals:
 116:   eks_name_keys = toset(keys(var.test_roles))
    |----------------
    | var.test_roles is null

Invalid value for "inputMap" parameter: argument must not be null.

@apparentlymart if you did came across such situation before and if you can help, it would be really great.

A for or for_each over an empty map {} or list [] should be a no-op. Why not pass {} instead of null?