Home > Blockchain >  Using Terraform, how can I pass in a list of users from module to module
Using Terraform, how can I pass in a list of users from module to module

Time:12-10

I am trying to use Terraform's public modules and I created a lot of IAM users like so:

module "iam_finance_users" {
  source  = "terraform-aws-modules/iam/aws//modules/iam-user"
  version = "5.9.1"

  for_each = var.finance_users
  name          = each.value
  force_destroy = true
  create_iam_access_key = false
  password_reset_required = true
}

My variables.tf file has the following:

variable "finance_users" {
  type = set(string)
  default = ["[email protected]","[email protected]"....]
}

Now I am trying to add these users to a group like so

module "iam_group_finance" {
  source  = "terraform-aws-modules/iam/aws//modules/iam-group-with-policies"
  version = "5.9.1"

  name = "finance"
  group_users = ["${module.iam_finance_users.iam_user_name}"]

  attach_iam_self_management_policy = true
  custom_group_policy_arns = [
    "${module.iam_read_write_policy.arn}",
  ]
}

But no matter what I try I still keep getting errors. I have a list of users in a variable and I want to add all those users created in that module to the group module. I know I'm close but I can't quite seem to close this.

CodePudding user response:

Since you used for_each in the module, you have to use values to access elements of all instances of the module created:

group_users = values(module.iam_finance_users)[*].iam_user_name

CodePudding user response:

You could try something like below: This is untested, so you might need to tweak a bit. Reference thread: https://discuss.hashicorp.com/t/for-each-objects-to-list/36609/2

module "iam_group_finance" {
  source  = "terraform-aws-modules/iam/aws//modules/iam-group-with-policies"
  version = "5.9.1"
  name = "finance"
  group_users =  [  for o in module.iam_finance_users : o.iam_user_name ]
  attach_iam_self_management_policy = true
  custom_group_policy_arns = [
    module.iam_read_write_policy.arn
  ]
}

CodePudding user response:

It's often helpful to know what the error is. In versions of Terraform v1.0 or newer, the errors become fairly explanatory. The error you were likely getting was something similar to:

│ Error: Unsupported attribute
│ 
│   on main.tf line 14, in output "iam_finance_users":
│   14:   value = module.iam_finance_users.iam_user_name
│     ├────────────────
│     │ module.iam_finance_users is object with 2 attributes
│ 
│ This object does not have an attribute named "iam_user_name".

The solutions, which both work, can be tested using the following example code:

Module 1: modules/iam-user

variable "name" {
  type = string
}

output "iam_user_name" {
  value = "IAM-${var.name}"
}

Module 2: modules/iam-group-with-policies

variable "group_users" {
  type = set(string)
}

output "iam-users" {
  value = var.group_users
}

Root module (your code):

variable "finance_users" {
  type    = set(string)
  default = ["[email protected]", "[email protected]"]
}

module "iam_finance_users" {
  source = "../modules/iam-user"

  for_each = var.finance_users
  name     = each.value
}

module "iam_group_finance" {
  source = "../modules/iam-group-with-policies"

  # This works...
  group_users = values(module.iam_finance_users)[*].iam_user_name

  # This also works...
  group_users = [for o in module.iam_finance_users : o.iam_user_name]
}

output "group_users" {
  value = module.iam_group_finance.iam-users
}

You can easily test each module along the way using terraform console.

E.g.:

terraform console

> module.iam_finance_users
{
  "[email protected]" = {
    "iam_user_name" = "[email protected]"
  }
  "[email protected]" = {
    "iam_user_name" = "[email protected]"
  }
}

Here you can see why it didn't work. The module doesn't spit out a list in that way, so you have to iterate through the module to get your variable. This is why both the for method as well as the values method works.

Look at how differently a single module is handled:

module "iam_finance_users" {
  source = "../modules/iam-user"

  name = tolist(var.finance_users)[1]
}
terraform console

> module.iam_finance_users
{
  "iam_user_name" = "[email protected]"
}

Notice that when not inside a loop (foreach), that the single iam_user_name is accessible.

  • Related