Terraform Function - Part 1 [Collection functions] - with examples

Terraform Function - Part 1 [Collection functions] - with examples

Terraform Functions

Let's look at some practical examples using these Terraform functions:

1. concat()

Scenario: You have two lists of AWS availability zones, and you want to create a single list combining them.

Terraform Code:

locals {
  azs_region1 = ["us-east-1a", "us-east-1b"]
  azs_region2 = ["us-east-1c", "us-east-1d"]
  combined_azs = concat(local.azs_region1, local.azs_region2)
}

output "combined_availability_zones" {
  value = local.combined_azs
}

Explanation: This code combines two lists of availability zones (azs_region1 and azs_region2) into a single list combined_azs using the concat() function.


2. contains(list, value)

Scenario: You have a list of instance types and you want to check if a specific instance type is included in that list.

Terraform Code:

locals {
  instance_types = ["t2.micro", "t2.small", "t2.medium"]
  check_instance = contains(local.instance_types, "t2.small")
}

output "is_t2_small_present" {
  value = local.check_instance
}

Explanation: This code checks if the instance type "t2.small" is present in the list instance_types. The contains() function returns true or false based on the presence of the value in the list.


3. distinct(list)

Scenario: You have a list with duplicate values and you need a list with unique values.

Terraform Code:

locals {
  repeated_values = ["apple", "banana", "apple", "orange", "banana"]
  unique_values = distinct(local.repeated_values)
}

output "unique_fruits" {
  value = local.unique_values
}

Explanation: This code removes duplicate entries from the list repeated_values. The distinct() function creates a new list unique_values containing only unique elements.

Let's explore real-world examples using these Terraform functions in the context of AWS infrastructure.


Let's explore real-world examples using these Terraform functions in the context of AWS infrastructure.


1. concat()

Scenario: Combining two sets of AWS subnets for a larger network configuration.

Terraform Code:

resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"
}

resource "aws_subnet" "subnet_a" {
  count = 2
  vpc_id     = aws_vpc.main.id
  cidr_block = "10.0.1.${count.index}/24"
}

resource "aws_subnet" "subnet_b" {
  count = 2
  vpc_id     = aws_vpc.main.id
  cidr_block = "10.0.2.${count.index}/24"
}

output "combined_subnets" {
  value = concat(aws_subnet.subnet_a[*].id, aws_subnet.subnet_b[*].id)
}

Explanation: This code creates a VPC and two sets of subnets (subnet_a and subnet_b). The concat() function is used to combine the subnet IDs into a single list.


2. contains(list, value)

Scenario: Conditionally creating an AWS resource based on the presence of a specific AWS region in a list.

Terraform Code:

variable "preferred_regions" {
  type = list(string)
  default = ["us-east-1", "us-west-2"]
}

resource "aws_s3_bucket" "example" {
  count  = contains(var.preferred_regions, "us-east-1") ? 1 : 0
  bucket = "my-s3-bucket"
  region = "us-east-1"
}

output "s3_bucket_created" {
  value = contains(var.preferred_regions, "us-east-1") ? "Yes" : "No"
}

Explanation: This checks if "us-east-1" is in the preferred_regions list. If it is, an S3 bucket is created in that region.


3. distinct(list)

Scenario: Ensuring unique AWS security group IDs are assigned to an EC2 instance.

Terraform Code:

resource "aws_security_group" "example" {
  # ... other configuration ...
}

resource "aws_instance" "web" {
  ami           = "ami-123456"
  instance_type = "t2.micro"

  vpc_security_group_ids = distinct([
    aws_security_group.example.id, 
    "sg-12345", 
    aws_security_group.example.id  # duplicate for illustration
  ])
}

Explanation: This creates an EC2 instance with a list of security group IDs. The distinct() function ensures that the list of security group IDs assigned to the EC2 instance is unique, even if duplicates are provided.


let's delve into more complex scenarios involving these Terraform functions in an AWS context.


1. Complex Use of concat()

Scenario: Creating a network configuration that spans multiple AWS regions, combining subnet IDs from different regions into a single list for a multi-region application deployment.

Terraform Code:

provider "aws" {
  alias  = "east"
  region = "us-east-1"
}

provider "aws" {
  alias  = "west"
  region = "us-west-2"
}

resource "aws_vpc" "east_vpc" {
  provider = aws.east
  cidr_block = "10.0.0.0/16"
}

resource "aws_vpc" "west_vpc" {
  provider = aws.west
  cidr_block = "10.1.0.0/16"
}

resource "aws_subnet" "east_subnet" {
  provider = aws.east
  count    = 3
  vpc_id     = aws_vpc.east_vpc.id
  cidr_block = "10.0.${count.index}.0/24"
}

resource "aws_subnet" "west_subnet" {
  provider = aws.west
  count    = 3
  vpc_id     = aws_vpc.west_vpc.id
  cidr_block = "10.1.${count.index}.0/24"
}

output "combined_subnets_across_regions" {
  value = concat(aws_subnet.east_subnet[*].id, aws_subnet.west_subnet[*].id)
}

Explanation: This example spans two AWS regions (us-east-1 and us-west-2). It creates a VPC in each region with multiple subnets, and then combines these subnet IDs using concat() for a multi-region setup.


2. Advanced Use of contains()

Scenario: Dynamically adjusting AWS resource configurations based on the presence of a specific tag in a list.

Terraform Code:

variable "resource_tags" {
  type = map(string)
}

resource "aws_instance" "example" {
  ami           = "ami-123456"
  instance_type = "t2.micro"

  tags = var.resource_tags

  volume_tags = {
    Name = "MyVolume"
    Encrypted = contains(keys(var.resource_tags), "EncryptVolumes") ? "true" : "false"
  }
}

output "volume_encryption_status" {
  value = contains(keys(var.resource_tags), "EncryptVolumes") ? "Enabled" : "Disabled"
}

Explanation: In this scenario, the instance volume's encryption is dynamically set based on whether the tag EncryptVolumes is present in the resource_tags. The contains() function checks the keys of the resource_tags map.


3. Sophisticated Use of distinct()

Scenario: Managing a complex AWS network configuration with potential overlapping security group rules.

Terraform Code:

resource "aws_security_group" "main" {
  name        = "main-group"
  description = "Main security group"
  vpc_id      = aws_vpc.main.id
}

resource "aws_security_group_rule" "ingress" {
  count = length(distinct(var.ingress_cidr_blocks))

  type        = "ingress"
  from_port   = 80
  to_port     = 80
  protocol    = "tcp"
  cidr_blocks = [element(distinct(var.ingress_cidr_blocks), count.index)]
  security_group_id = aws_security_group.main.id
}

variable "ingress_cidr_blocks" {
  type = list(string)
  default = ["10.0.0.0/16", "10.0.0.0/16", "172.16.0.0/12"]
}

output "unique_ingress_cidr_blocks" {
  value = distinct(var.ingress_cidr_blocks)
}

Explanation: This script creates security group rules with distinct CIDR blocks for ingress traffic, avoiding duplicates. The distinct() function is used to ensure each CIDR block in var.ingress_cidr_blocks is unique, preventing redundant rules.