Search code examples
amazon-web-servicesterraformterraform-provider-awsterraform-template-file

terraform combine data template file and each.key in a for_each block


Using a module to create multiple IAM roles with a for_each block I am trying to pass into the policy a rendered data output and the key from the for_each loop. The name of this policy will be slightly different for each role

module "sso_roles" {
  source   = "git::ssh://[email protected]/iam/role?ref=1.1.0"
  for_each = local.roles

  policy                 = "${data.template_file}.${each.key}_policy".rendered
  role_name              = each.key
  assume_role_policy_def = data.template_file.testing_role.rendered
  
  
}

These are the locals its looping through:

locals {
  roles = {
    "test_Read_Only" = ["arn:aws:iam::*:role/testReadOnly", "]
    "test_OS_Only" = ["arn:aws:iam::*:role/testSigninOSOnly"]
  }
}

what I need terraform to see when its running are these two:

${data.template_file.test_Read_Only_policy.rendered}
${data.template_file.test_OS_Only_policy.rendered}

But there is something not right with the syntax I have. The error I get says "The "data" object must be followed by two attribute names: the data source type and the resource name."

I don't know how to combine the each.key into the rendered data template file


Solution

  • What I would suggest is:

    1. To use the data source with for_each and use the same variable
    2. To switch to the templatefile built-in function and pass the value as a variable.

    To achieve the first, you would do something like:

    module "sso_roles" {
      source   = "git::ssh://[email protected]/iam/role?ref=1.1.0"
      for_each = local.roles
    
      policy                 = data.template_file.policy[each.key].rendered
      role_name              = each.key
      assume_role_policy_def = data.template_file.testing_role.rendered
      
    }
    
    data "template_file" "policy" {
      for_each = local.roles
      ...
    }
    

    The second one is probably a bit more convenient and it's using a newer and better templatefile function [1]:

    module "sso_roles" {
      source   = "git::ssh://[email protected]/iam/role?ref=1.1.0"
      for_each = local.roles
    
      policy                 = templatefile("${path.module}/path/to/template/file.tpl", {
        iam_role = each.value
      })
      role_name              = each.key
      assume_role_policy_def = data.template_file.testing_role.rendered
      
      
    }
    

    With more information about the template file you are using I would be able to adjust the second example.


    [1] https://www.terraform.io/language/functions/templatefile