Skip to main content

Terraform Loop Iteration

Terraform provides the ability to manage multiple similar resourcesExternal LinkThis link leads to an external website and will open in a new tab by iterating through defined data structures. This enables you to reuse your Terraform code and ensures that similar resources are managed consistently.

In this article, we will use the Terraform for_each Meta-ArgumentExternal LinkThis link leads to an external website and will open in a new tab to demonstrate managing multiple similar Files.com resources.

Example Use Case

In this example, we will use a fictional healthcare scenario to demonstrate processing Medicare claims.

My healthcare business needs to onboard multiple client customers, such as the healthcare providers which my business provides services to.

Each client will require a home folder within the Medicare clients' folder structure. Each client home folder needs to be provided with subfolders named Eligibility and Prescription Drug Event for that client.

Each client will need to have 2 user access groups assigned to their home folder. There will be 1 group that only has permission to upload and 1 group that only has permission to download. The customer client will be placed into the upload group while my internal systems will be placed into the download group. This ensures that only my clients can submit data to me and that my internal systems can only collect the submitted data.

For compliance reasons, I also need to allow each subfolder to be accessed by the relevant teams. The Eligibility subfolder needs to be accessed (read only) by another of my internal systems as well as accessed (write only) by the Customer Eligibility Support Team whenever eligibility records need to be updated or changed. There will need to be 2 new user access groups assigned to the Eligibility subfolder to meet these access needs.

The Prescription Drug Event subfolder has similar requirements to the Eligibility subfolder. There need to be 2 user access groups for this subfolder, 1 to upload (write only) and 1 to download (read only).

All new clients will need the above requirements to be similarly applied to their folders.

for_each Usage Example

The for_each Meta-Argument can be used to iterate through a variable when managing resources, like this:

# Variable Containing List of Clients

variable "clients" {
  type = set(string)
  default = [
    "Client A",
    "Client B",
    "Client C"
  ]
}

# Create User Accounts for each Client by using a loop

resource "files_user" "user_account" {
  for_each = var.clients
  authentication_method        = "password"
  name                         = each.value
  company                      = each.value
  password                     = "S0meRea11yLongP@ssw0rd"
  self_managed                 = "true"
  username                     = replace("${lower(each.value)}", " ", "_")
}

The above code defines a variable containing a list of client names, and uses the for_each meta-argument to iterate through the list and create corresponding user accounts in your Files.com site. The value for each client in the variable is used for the name, company, and username of the user account. For the username, the value is converted to lower case and any spaces are replaced with an underscore.

Implementing Our Example Use Case

To implement our example use case, we'll use for_each loops to perform these steps for each client:

Create Client Folder

We want our client folders to be placed within the /Medicare/Clients/ folder of our site. A best practice in Terraform is to ensure that all dependencies, including the existence of parent folders in the hierarchy, are managed by Terraform. This helps mitigate later issues when Terraform is used to modify or remove existing resources.

We need to configure Terraform to manage both the /Medicare/ and the /Medicare/Clients/ folders. We also need to make sure that the latter folder is dependent on the former existing. Here is some code to achieve this:

# Create top level folder for Medicare

resource "files_folder" "top_medicare_folder" {
  path = "Medicare"
}

# Create Clients folder within the Medicare folder

resource "files_folder" "medicare_clients_folder" {
  path = "${files_folder.top_medicare_folder.path}/Clients"
  depends_on = [ files_folder.top_medicare_folder ]
}

We can now implement a for_each loop to create and manage the client folders:

# Create home folders for each client

resource "files_folder" "client_folder" {
  for_each = var.clients
  path = "${files_folder.medicare_clients_folder.path}/${each.value}"
  depends_on = [ files_folder.medicare_clients_folder ]
}

Create Groups for the Client Home Folder

We can use similar for_each loops to create and manage the groups that will be assigned upload (write only) and download (read only) access permissions.

The following code will create the 2 groups:

# Create group to upload to client home folder

resource "files_group" "client_upload_group" {
  for_each = var.clients
  notes              = "Upload Group for ${each.value}."
  ftp_permission     = true
  sftp_permission    = true
  dav_permission     = true
  restapi_permission = true
  name               = "${each.value} Upload Group"
}

# Create group to retrieve (download only) from client home folder

resource "files_group" "client_download_group" {
  for_each = var.clients
  notes              = "Download Group for ${each.value}."
  ftp_permission     = true
  sftp_permission    = true
  dav_permission     = true
  restapi_permission = true
  name               = "${each.value} Download Group"
}

Assign Access Permissions to the Home Folder Groups

To assign access permissions to the 2 home folder groups, use the following code:

# Assign upload access permission to upload group

resource "files_permission" "client_group_upload_permission" {
  for_each = var.clients
  path = "${files_folder.medicare_clients_folder.path}/${each.value}"
  group_name = "${each.value} Upload Group"
  permission = "writeonly"
  depends_on = [files_group.client_upload_group, files_folder.client_folder]
}

# Assign download access permission to retrieve group

resource "files_permission" "client_group_download_permission" {
  for_each = var.clients
  path = "${files_folder.medicare_clients_folder.path}/${each.value}"
  group_name = "${each.value} Download Group"
  permission = "readonly"
  depends_on = [files_group.client_download_group, files_folder.client_folder]
}

The above code assigns access permissions to the previously created groups and specifies dependencies to ensure the permissions are only assigned once the groups and their corresponding home folders are successfully created.

Create Client Subfolders

For each subfolder within the client home folder, repeat the following code, adjusting the folder name as needed:

# Create Eligibility subfolder for each client

resource "files_folder" "client_eligibility_folder" {
  for_each = var.clients
  path = "${files_folder.medicare_clients_folder.path}/${each.value}/Eligibility"
  depends_on = [ files_folder.client_folder ]
}

The above code will create an Eligibility subfolder within the client home folder. It also specifies a dependency so that the subfolder will only be created once the home folder has been created.

This step can be duplicated for each required subfolder. For our use case, we would repeat this code but replace all mentions of "eligibility" with "prescription drug event".

Create Groups for the Client Subfolders

Just as before, we can create 2 groups that will be assigned upload (write only) and download (read only) access permissions to the subfolders:

# Create group to upload to client eligibility folder

resource "files_group" "client_eligibility_upload_group" {
  for_each = var.clients
  notes              = "Eligibility Upload Group for ${each.value}."
  ftp_permission     = true
  sftp_permission    = true
  dav_permission     = true
  restapi_permission = true
  name               = "${each.value} Eligibility Upload Group"
}

# Create group to download from client eligibility folder

resource "files_group" "client_eligibility_download_group" {
  for_each = var.clients
  notes              = "Eligibility Download Group for ${each.value}."
  ftp_permission     = true
  sftp_permission    = true
  dav_permission     = true
  restapi_permission = true
  name               = "${each.value} Eligibility Download Group"
}

This step can be duplicated for each required subfolder. For our use case, we would repeat this code but replace all mentions of "eligibility" with "prescription drug event".

Assign Access Permissions to the Subfolder Groups

To assign access permissions to the 2 subfolder groups, use the following code:

# Assign upload access permission to eligibility upload group

resource "files_permission" "client_group_eligibility_upload_permission" {
  for_each = var.clients
  path = "${files_folder.medicare_clients_folder.path}/${each.value}/Eligibility"
  group_name = "${each.value} Eligibility Upload Group"
  permission = "writeonly"
  depends_on = [files_group.client_eligibility_upload_group, files_folder.client_eligibility_folder]
}

# Assign download access permission to eligibility download group

resource "files_permission" "client_group_eligibility_download_permission" {
  for_each = var.clients
  path = "${files_folder.medicare_clients_folder.path}/${each.value}/Eligibility"
  group_name = "${each.value} Eligibility Download Group"
  permission = "readonly"
  depends_on = [files_group.client_eligibility_download_group, files_folder.client_eligibility_folder]
}

The above code will assign access permissions to the groups as well as specifying dependencies so that the permissions are only assigned if the groups, and the corresponding subfolders, were successfully created.

This step can be duplicated for each required subfolder. For our use case, we would repeat this code but replace all mentions of "eligibility" with "prescription drug event".

Execution

When we execute the above code, Terraform will create all these resources and manage any dependencies between them.

Each time we add a client to the variable, Terraform will manage 16 corresponding resources (1 user account, 3 folders, 6 groups, and 6 access permissions) for that client. A single addition to the variable drives all the changes needed to onboard your clients.

In real world scenarios, the client variable would be updated programmatically by an onboarding system so that the entire process is automated, removing delays and human error.

Get Instant Access to Files.com

The button below will take you to our Free Trial signup page. Click on the white "Start My Free Trial" button, then fill out the short form on the next page. Your account will be activated instantly. You can dive in and start yourself or let us help. The choice is yours.