How can you improve the state of your infrastructure automation?

➡️ Take the Self-Assessment

Terraform

Terraform Length Function: Examples For Lists, Maps & Strings

terraform length

Subscribe to our Newsletter

Mission Infrastructure newsletter is a monthly digest of the latest posts from our blog, curated to give you the insights you need to advance your infrastructure game.

Leveraging functions effectively enhances flexibility and streamlines resource management in any Terraform environment. Instead of hardcoding values, functions enable dynamic interactions between different parts of your code, making it more scalable and maintainable.

The length() function in Terraform is a simple yet powerful tool for managing lists, maps, and strings within your configurations. It helps determine the size of these data structures, making it useful for conditionals, loops, and validations. In this article, we’ll break down how length() works, its practical applications, and common scenarios where it enhances Terraform workflows.

What we’ll cover:

  1. What are Terraform functions?
  2. What is the length function in Terraform?
  3. How to use the Terraform length function
  4. Terraform lenght use cases
  5. Advanced methods of using the length function

What are Terraform functions?

Terraform comes packed with built-in functions that let you manipulate data, making your configurations more dynamic, reusable, and tailored to your environment. Whether you need to format strings, transform data types, or apply conditional logic, Terraform functions give you greater control over how data is processed and utilized.

At a high level, these functions let you:

  • Work with strings – Easily concatenate, split, or replace text using join, split, and replace.
  • Handle numbers – Round values up or down and find the max/min with ceil, max, and min.
  • Manage collections – Extract values from lists/maps with length and keys, simplify complex structures using flatten, and merge multiple lists/maps with merge.
  • Process time-based data – Use timeadd and timestamp to handle date/time operations.
  • Convert data formats – Encode data with base64encode or transform it into JSON with jsonencode.

Terraform functions also integrate seamlessly with expressions, loops (for), and constructs like for_each and count, making them a powerful tool for automation. By leveraging these functions, you can build scalable, adaptable configurations that respond dynamically to changing inputs—maximizing efficiency and flexibility in your infrastructure.

Read more: Terraform Functions, Expressions, Loops

What is the length function in Terraform?

The length function in Terraform helps you determine the size of a string, list, or map by returning the number of characters, elements, or keys, respectively. This function is particularly useful when validating input sizes, such as ensuring a list or map contains enough elements before provisioning a resource. It also pairs well with the count construct, allowing you to dynamically create multiple resources based on input size.

A common use case is managing firewall rules, where security groups must be defined based on a specific number of inputs.  

The length function can also help simplify your Terraform workflows and create a more dynamic environment, which we will explore in more detail in this article. 

How to use the Terraform length function

Here is the simple syntax of the length function: 

length(value)

In this case, the value can be a string, list, or map, which can be passed in through a variable. 

1. Using the length function with a string

Let’s demonstrate the behavior of the length function with a simple example:

variable "mystring" {
  default = “helloworld” 
}

The output of the variable using the length function will give you “10”. 

output “number_in_string” {
  value = length(var.mystring)
}

number_in_string = 10

We can also perform some checks on this value and output an alert as the following:

output “is_string_too_long” {
  value = length(var.mystring) > 5 ? “string is too long” : “string is valid”
}

Giving us:

is_string_too_long = "string is too long"

2. Using the length function with a list

You can also use the Terraform length function with a list:

variable "mylist" {
  default = [ “hello”, “world” ] 
}

The output of the variable using the length function against the list will give you “2”. 

output “number_in_list” {
  value = length(var.mylist)
}

number_in_list = 2

You can also perform checks on a list, as we did with strings: 

variable "subnet_ids" {
  default = ["subnet-1"]
}

output "validate_subnet" {
  value = length(var.subnet_ids) >= 2 ? "Valid subnet count" : "Error: At least 2 subnets required"
}

Because we only have one subnet in our list, we will get the following output:

validate_subnet = "Error: At least 2 subnets required"

3. Using the length function with a map

Let’s see an example of using the Terraform length function with a map:

variable "mymap" { 
  default = { 
    Map1 = "value1" 
    Map2 = "value2" 
  } 
}

The output of the variable using the length function against the map will give you “2”. 

output “number_in_map” {
  value = length(var.mymap)
}

number_in_map = 2

With maps, we can use some conditionals to grab the length of a specific key in a map:

variable "users" {
  default = {
    goku   = "admin"
    gohan  = "user"
    vegeta = "admin"
    trunks = "user"
  }
}

output "admin_count" {
  value = length({ for k, v in var.users : k => v if v == "admin" })
}

Giving us the following:

admin_count = 2

These are a few simple examples of how you can use the length function with variable data types. 

In the next section, we will explore how to maximize the length function’s use in real-world scenarios with our cloud providers. 

Terraform length use cases

Now, let’s dive into some real-world examples of how the length function can optimize cloud infrastructure: 

Example 1: Creating a virtual machine for each VM size

In the following example, we want to create an Azure Virtual Machine based on the number of VM Sizes we have listed using the count feature. We can also grab the value of the VM Size in the list by tapping into the index from the count element and placing that value under vm_size as our value for each VM.

In this way, we dynamically create multiple virtual machines in Azure using the count looping feature: 

variable "vm_sizes" {
  type    = list(string)
  default = ["Standard_B1s", "Standard_B2ms", "Standard_B4ms"]
}

resource "azurerm_linux_virtual_machine" "main" {
  count                 = length(var.vm_sizes)
  name                  = "example-vm-${count.index}"
  location              = "East US"
  resource_group_name   = var.rg_name
  network_interface_ids = [azurerm_network_interface.main.id]
  size                  = var.vm_sizes[count.index]
  admin_username        = "adminuser"
  admin_password        = "adminpass"

  source_image_reference {
    publisher = "Canonical"
    offer     = "0001-com-ubuntu-server-jammy"
    sku       = "22_04-lts"
    version   = "latest"
  }

  os_disk {
    caching              = "ReadWrite"
    storage_account_type = "Standard_LRS"
  }
}

Example 2: Creating multiple disks based on the number of disk sizes listed

We can also use the same logic for creating our Azure Managed Disks, properly creating a disk for each disk size listed:

variable "disk_sizes" {
  type    = list(string)
  default = ["Standard_LRS", "Premium_LRS", "StandardSSD_LRS"]
}

resource "azurerm_managed_disk" "my_disk" {
  count                 = length(var.disk_sizes)
  name                  = "example-disk-${count.index}"
  location              = "East US"
  resource_group_name   = var.rg_name
  storage_account_type = var.disk_sizes[count.index]
  disk_size_gb          = 50
}

Example 3: Creating multiple VMs with key/values from a map

We can enhance virtual machine creation by using maps to store all VM configurations. This allows Terraform to dynamically determine the number of VMs based on the number of keys in the map, rather than relying on a predefined variable, making the process more flexible and scalable.

variable "vmconfig" {
  type = map(object({
    size      = string
    admin_username = string
    admin_password = string
  }))
  default = {
    "vm1" = {
      size             = "Standard_DS1_v2"
      admin_username   = "adminuser"
      admin_password   = "adminpass"
    },
    "vm2" = {
      size             = "Standard_DS2_v2"
      admin_username   = "adminuser"
      admin_password   = "adminpass"
    }
  }
}

resource "azurerm_linux_virtual_machine" "linux_vm" {
  count               = length(var.vmconfig)

  name                = "${keys(var.vmconfig)[count.index]}"
  resource_group_name = "rg_name"
  location            = "East US"
  size                = var.vmconfig[values(var.vmconfig)[count.index]].size
  admin_username      = var.vmconfig[values(var.vmconfig)[count.index]].admin_username
  admin_password      = var.vmconfig[values(var.vmconfig)[count.index]].admin_password
  network_interface_ids = [
    azurerm_network_interface.nic[count.index].id
  ]
}

resource "azurerm_network_interface" "nic" {
  count = length(var.vmconfig)

  name                            = "nic-${keys(var.vmconfig)[count.index]}"
  location                        = "East US"
  resource_group_name             = "rg_name"
  ip_configuration {
    name                          = "internal"
    subnet_id                     = azurerm_subnet.subnet.id
    private_ip_address_allocation = "Dynamic"
  }
}

resource "azurerm_subnet" "subnet" {
  name                 = "mysub"
  resource_group_name  = "rg_name"
  virtual_network_name = "mynet"
  address_prefixes     = ["10.0.0.0/24"]
}

Example 4: Dynamically outputting the length of a resource

The length function allows you to accurately determine the number of deployed or existing resources. 

For instance, if you need to check how many virtual machines have been created using your Terraform code, you can use the length function to output the total resource count value.

output "num_of_az_virtual_machines" {
  value = length(azurerm_virtual_machine.myvm)
}

This can also be useful for validating the number of disks created, if we are dealing with a large count of disks:

output "attached_disks_count" { value = length([ azurerm_linux_virtual_machine.example.storage_os_disk, azurerm_virtual_machine_data_disk_attachment.disk1, azurerm_virtual_machine_data_disk_attachment.disk2 ]) }

Giving us the following output:

attached_disks_count = 3

Here are just a few real-world examples of how the length function helps optimize resource deployment in our cloud environment. Next, we’ll explore advanced techniques that incorporate conditional expressions, allowing us to extend its functionality.

Advanced methods of using the length function

In this section, we’ll explore advanced techniques for using Terraform’s length function, including how to combine it with conditional expressions to dynamically create underlying resources.

Conditionally create a network security group

In the following example, we can conditionally create Azure Network Security Groups (NSG) based on the number of Azure subnets we have. Therefore if we have any subnet in our list, we can create an NSG, and if we do not have any, then it will create no NSG in Azure:

variable "subnets" {
  type    = list(string)
  default = ["subnet1", "subnet2"]
}

resource "azurerm_network_security_group" "subnet_example" {
  count = length(var.subnets) > 0 ? 1 : 0 
  name  = "azure-net-nsg"
  location = "East US"
  resource_group_name = var.rg_name
}

Validate the number of CIDR blocks to create a virtual network

If we don’t have any CIDR blocks, we cannot create any virtual networks in Azure. We are performing a conditional check to ensure we have a list of one or more CIDR blocks, and we will assign each CIDR block to a single Azure Virtual Network. 

variable "cidr_blocks" {
  type    = list(string)
  default = ["10.0.0.0/16"]
}

resource "azurerm_virtual_network" "vnet_example" {
  count               = length(var.cidr_blocks) > 0 ? 1 : 0
  name                = "example-vnet"
  location            = "East US"
  resource_group_name = var.rg_name
  address_space       = var.cidr_blocks
}

Count the number of users in an Azure Role Assignment

With the length function, we can also loop through the number of listed users and assign them the proper permissions by deploying the role assignment dynamically against the same number of listed users by accessing the index of the count meta-argument:

variable "users" {
  default = ["darthvader@mycompany.com", "obiwan@mycompany.com"]
}

resource "azurerm_role_assignment" "rbac" {
  count                = length(var.users)
  scope                = "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
  role_definition_name = "Contributor"
  principal_id         = var.users[count.index]
}

Validate the number of secrets for the Azure Key Vault Access Policy

We can also use the same logic when creating access policies for our Azure key vaults. Ensuring there are secrets available before we begin to create an Azure Key Vault Access Policy resource:

variable "secrets" {
  type    = list(string)
  default = ["secret1", "secret2"]
}

resource "azurerm_key_vault" "akv" {
  name                = "example-keyvault"
  location            = "East US"
  resource_group_name = var.rg_name
  sku_name            = "standard"
}

resource "azurerm_key_vault_access_policy" "akv_policy" {
  count               = length(var.secrets) > 0 ? 1 : 0
  key_vault_id        = azurerm_key_vault.akv.id
  tenant_id           = var.tenant_id
  object_id           = var.object_id
  secret_permissions = ["get", "list"]
}

Restrict improper character limit for Azure storage account

Azure enforces specific character requirements for storage account names, including a maximum length of 24 characters and the use of only lowercase letters and numbers. 

In the following example, we utilize the length function to ensure compliance with these rules. Conditional logic is applied to validate the input within the name field. 

  • If the provided name exceeds 24 characters, it is truncated to the first 24 characters and converted to lowercase.
  • If it is within the limit, it is simply converted to lowercase and accepted as is.
variable "storage_account_name_prefix" {
  type    = string
  default = "MyTestStorageAccount1"
}

resource "azurerm_storage_account" "storage-example" {
  name = length(var.storage_account_name_prefix) > 24 ? substr(lower(var.storage_account_name_prefix), 0, 24) : lower(var.storage_account_name_prefix)

  resource_group_name      = "rg_name"
  location                 = "East US"
  account_tier              = "Standard"
  account_replication_type = "LRS"

  tags = {
    Environment = "dev"
  }

  lifecycle {
    ignore_changes = [
      name
    ]
  }
}

Deploying Terraform resources with Spacelift

Terraform is really powerful, but to achieve an end-to-end secure Gitops approach, you need to use a product that can run your Terraform workflows. Spacelift takes managing Terraform to the next level by giving you access to a powerful CI/CD workflow and unlocking features such as:

  • Policies (based on Open Policy Agent) – You can control how many approvals you need for runs, what kind of resources you can create, and what kind of parameters these resources can have, and you can also control the behavior when a pull request is open or merged.
  • Multi-IaC workflows – Combine Terraform with Kubernetes, Ansible, and other infrastructure-as-code (IaC) tools such as OpenTofu, Pulumi, and CloudFormation,  create dependencies among them, and share outputs
  • Build self-service infrastructure – You can use Blueprints to build self-service infrastructure; simply complete a form to provision infrastructure based on Terraform and other supported tools.
  • Integrations with any third-party tools – You can integrate with your favorite third-party tools and even build policies for them. For example, see how to Integrate security tools in your workflows using Custom Inputs.

Spacelift enables you to create private workers inside your infrastructure, which helps you execute Spacelift-related workflows on your end. Read the documentation for more information on configuring private workers.

You can check it for free by creating a trial account or booking a demo with one of our engineers.

Key points

The length function in Terraform is a powerful tool for dynamically managing and validating data. It determines the number of elements in strings, lists, and maps, making it essential for tasks like data validation, resource provisioning, and maintaining deployment consistency. In real-world use cases, it helps automate infrastructure by provisioning virtual machines, disks, and other resources based on list lengths. 

When combined with conditional logic and Terraform’s meta-arguments, it enhances flexibility by enabling dynamic resource creation and validation. Mastering this function improves automation, reduces errors, and optimizes multi-cloud deployments, ensuring infrastructure adapts to changing data.

Note: New versions of Terraform are placed under the BUSL license, but everything created before version 1.5.x stays open-source. OpenTofu is an open-source version of Terraform that expands on Terraform’s existing concepts and offerings. It is a viable alternative to HashiCorp’s Terraform, being forked from Terraform version 1.5.6.

Automate Terraform deployments with Spacelift

Automate your infrastructure provisioning, build more complex workflows based on Terraform using policy as code, programmatic configuration, context sharing, drift detection, resource visualization, and many more.

Learn more

The Practitioner’s Guide to Scaling Infrastructure as Code

Transform your IaC management to scale

securely, efficiently, and productively

into the future.

ebook global banner
Share your data and download the guide