terraform How to use conditional if in for_each into map object

Viewed 23621

I have maps of variables like this:

users.tfvars

users = {
  "testterform" = {
    path          = "/"
    force_destroy = true
    email_address = "testterform@example.com"
    group_memberships = [ "test1" ]
    tags = { department : "test" }
    ssh_public_key = "ssh-rsa AAAAB3NzaC1yc2EAAA4l7"
  }

  "testterform2" = {
    path          = "/"
    force_destroy = true
    email_address = "testterform2@example.com"
    group_memberships = [ "test1" ]
    tags = { department : "test" }
    ssh_public_key = ""
  }

I would like to upload ssh key only if ssh_public_key not empty for the user. But don't understand how to check this

#main.tf

resource "aws_iam_user" "this" {
  for_each = var.users

  name                 = each.key
  path                 = each.value["path"]
  force_destroy        = each.value["force_destroy"]

  tags = merge(each.value["tags"], { Provisioner : var.provisioner, EmailAddress : each.value["email_address"] })
}

resource "aws_iam_user_group_membership" "this" {
  for_each = var.users

  user   = each.key
  groups = each.value["group_memberships"]

  depends_on = [ aws_iam_user.this ]
}

resource "aws_iam_user_ssh_key" "this" {

  for_each = var.users

  username = each.key
  encoding = "SSH"
  public_key = each.value["ssh_public_key"]

  depends_on = [ aws_iam_user.this ]
}
2 Answers

It sounds like what you need here is a derived "users that have non-empty SSH keys" map. You can use the if clause of a for expression to derive a new collection from an existing one while filtering out some of the elements:

resource "aws_iam_user_ssh_key" "this" {
  for_each = {
    for name, user in var.users : name => user
    if user.ssh_public_key != ""
  }

  username   = each.key
  encoding   = "SSH"
  public_key = each.value.ssh_public_key

  depends_on = [aws_iam_user.this]
}

The derived map here uses the same keys and values as the original var.users, but is just missing some of them. That means that the each.key results will correlate and so you'll still get the same username value you were expecting, and your instances will have addresses like aws_iam_user_ssh_key.this["testterform"].

You can use a for loop to exclude those blanks.
For example, you can do it on local:

variable "users" {
  default = {
    "testterform" = {
      path           = "/"
      force_destroy  = true
      tags           = { department : "test" }
      ssh_public_key = "ssh-rsa AAAAB3NzaC1yc2EAAA4l7"
    }
    "testterform2" = {
      path           = "/"
      force_destroy  = true
      tags           = { department : "test" }
      ssh_public_key = ""
    }
  }
}

locals {
  public_key = flatten([
    for key, value in var.users : 
      value.ssh_public_key if ! contains([""], value.ssh_public_key)
  ])
}

output "myout" {
  value = local.public_key
}

that will output:

myout = [
  "ssh-rsa AAAAB3NzaC1yc2EAAA4l7",
]

As you can see the empty ones have been removed, and you can add other stuff you want to exclude on that contains array.
Then you can use that local.public_key in the for_each for your ssh keys

Related