Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

terraform How to use conditional if in for_each into map object

Tags:

terraform

I have maps of variables like this:

users.tfvars

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

  "testterform2" = {
    path          = "/"
    force_destroy = true
    email_address = "[email protected]"
    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 ]
}
like image 566
llias Avatar asked Dec 03 '22 09:12

llias


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"].

like image 168
Martin Atkins Avatar answered May 28 '23 12:05

Martin Atkins


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

like image 24
Helder Sepulveda Avatar answered May 28 '23 13:05

Helder Sepulveda