====== Lists ======
In Terraform, lists are one of the fundamental data types used to store an ordered collection of values. They are particularly useful when you need to manage multiple items of the same type, such as a list of IP addresses, server names, or AWS availability zones.
* Ordered: Elements are stored in the sequence they are defined.
* Index-based Access: You can access elements using zero-based indices.
====== Defining Lists ======
Lists can be defined using square brackets [] and separating elements with commas.
variable "server_names" {
type = list(string)
default = ["web01", "web02", "db01"]
}
* Type Declaration: Specifying list(string) ensures that the list contains strings.
* Default Value: The list of server names.
====== Accessing List Elements ======
You can access elements using their index.
output "first_server" {
value = var.server_names[0] # Outputs "web01"
}
====== Iterating Over Lists ======
Lists are often used with loops to create multiple resources.
===== Using the count Parameter =====
resource "aws_instance" "servers" {
count = length(var.server_names)
instance_type = "t2.micro"
ami = "ami-0c55b159cbfafe1f0"
tags = {
Name = var.server_names[count.index]
}
}
* count: Creates one instance per element in the list.
* count.index: The current index in the loop.
===== for_each =====
See also: [[terraform:list#Dynamic Blocks with Lists|Dynamic Blocks with Lists]]
====== List Functions ======
Terraform provides built-in functions to manipulate lists.
===== length(list) =====
Returns the number of elements in a list.
locals {
num_servers = length(var.server_names)
}
===== concat(list1, list2, ...) =====
Concatenates two or more lists.
locals {
all_servers = concat(var.web_servers, var.db_servers)
}
===== element(list, index) =====
Safely retrieves an element at a given index.
locals {
server = element(var.server_names, 1) # "web02"
}
===== slice(list, start, end) =====
Extracts a sublist.
locals {
first_two_servers = slice(var.server_names, 0, 2)
}
====== Using Lists with for Expressions ======
You can transform lists using for expressions.
locals {
uppercased_servers = [for name in var.server_names : upper(name)]
}
* Result: ["WEB01", "WEB02", "DB01"]
====== Dynamic Blocks with Lists ======
Dynamic blocks can generate nested configurations based on lists.
resource "aws_security_group" "example" {
name = "example-sg"
dynamic "ingress" {
for_each = var.allowed_ports
content {
from_port = ingress.value
to_port = ingress.value
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
}
* var.allowed_ports: A list of ports.
* Dynamic Ingress Rules: Creates an ingress rule for each port.
====== Best Practices ======
===== Type Constraints =====
Always specify the type of variables to avoid unexpected behavior.
variable "ip_addresses" {
type = list(string)
}
===== Use Descriptive Variable Names =====
Names should reflect the content or purpose of the list.
* Good: allowed_ips, server_names
* Bad: list1, my_list
===== Avoid Hardcoding Indices =====
Instead of accessing elements by index, use loops or functions to handle lists dynamically.
===== Validate Inputs =====
Use validation blocks to ensure lists meet certain criteria.
variable "subnets" {
type = list(string)
validation {
condition = length(var.subnets) >= 2
error_message = "At least two subnets are required."
}
}
====== Common Use Cases ======
===== Managing Multiple Resources =====
Creating multiple resources based on a list of inputs.
resource "aws_subnet" "example" {
count = length(var.availability_zones)
vpc_id = var.vpc_id
cidr_block = cidrsubnet(var.vpc_cidr_block, 8, count.index)
availability_zone = var.availability_zones[count.index]
}
===== Passing Lists to Modules =====
Modules can accept lists to configure resources.
module "network" {
source = "./modules/network"
subnets = var.subnets
}
====== Advanced List Manipulation ======
===== Flattening Nested Lists =====
locals {
nested_list = [["a", "b"], ["c", "d"]]
flat_list = flatten(local.nested_list) # ["a", "b", "c", "d"]
}
===== Filtering Lists =====
locals {
numbers = [1, 2, 3, 4, 5]
even_numbers = [for num in local.numbers : num if num % 2 == 0]
}
Result: [2, 4]
====== Debugging Lists ======
Use output blocks or the terraform console for debugging.
output "server_list" {
value = var.server_names
}