Search code examples
amazon-web-servicesterraformterraform-provider-awsamazon-sagemakeramazon-sagemaker-studio

Terraform count[index] with looping list of variables


I want to create a resource block where my first resource is created based on each value in json. My second resource is dependent on the first resource id, so I am referring with count[index].id but the second resource block need to be looped as per the number of email values. Multiple Second resources will be created for one first resource value.

file.json

[
    {
        "name": "one",
        "env": "dev",
        "org": "IT",
        "email": "[email protected], [email protected]"
    },
    {
        "name": "two",
        "env": "stg",
        "org": "HR",
        "email": "[email protected], [email protected], [email protected]"
    }
]

main.tf

locals {
        data = jsondecode(file("${path.module}/file.json"))
    }

First resource will be created for each value in json

resource "aws_sagemaker_domain" "domain" {
    count = length(local.data)
    domain_name = local.data[count.index].name
}

Second resource has a reference to first resource and need to be looped for each email value. One aws_sagemaker_domain.dmain.id will have one or many aws_sagemaker_user_profile associated based on email value.

I know we cannot use for each and count together in a resource block, I have just shown to explain what I wanted to achieve. Any help is appreciated on how this can be written.

resource "aws_sagemaker_user_profile" "user_profile"
    count = length(local.data)
    domain_id = aws_sagemaker_domain.domain[count.index].id
    for_each = split(",", local.data[count.index].email)
    user_profile_name = each.value
}

error: the count and for_each meta-arguments are mutually-exclusive, only one should be used to ve explicit about the number of resources to be created.


Solution

  • You have to flatten you data:

    locals {
      data_flat = merge([
        for idx, domain in local.data: {
          for email in split(",", domain.email): 
              "${domain.name}-${email}" => {
                    "index": idx 
                    "name": domain.name
                    "env": domain.env
                    "org": domain.org
                    "email": email
              }        
        }
      ]...) # do NOT remove the dots
    }
    

    Then

    resource "aws_sagemaker_user_profile" "user_profile"
        for_each = local.data_flat
        domain_id = aws_sagemaker_domain.domain[each.value.index].id
        user_profile_name = each.value.email
    }