Skip to content

For / If Expressions

Carina supports for and if expressions to dynamically generate resources. This guide shows you how to iterate over collections and conditionally create resources.

For expressions

A for expression creates multiple resources by iterating over a list or map.

Iterating over a list

The simplest form iterates over a list of values:

provider awscc {
region = awscc.Region.ap_northeast_1
}
let vpcs = for env in ['dev', 'stg'] {
awscc.ec2.vpc {
cidr_block = '10.0.0.0/16'
tags = {
Name = "vpc-${env}"
Environment = env
}
}
}

This creates two VPCs, one for each environment.

Indexed iteration

Use the (index, value) form to access the iteration index:

let vpcs = for (i, env) in ['dev', 'stg'] {
awscc.ec2.vpc {
cidr_block = cidr_subnet('10.0.0.0/8', 8, i)
tags = {
Name = "vpc-${env}"
Environment = env
}
}
}

The index i starts at 0. Here it is used with cidr_subnet to assign different CIDR blocks to each VPC.

Iterating over a map

Use key, value binding to iterate over map entries:

let cidrs = {
dev = '10.0.0.0/16'
stg = '10.1.0.0/16'
}
let vpcs = for name, cidr in cidrs {
awscc.ec2.vpc {
cidr_block = cidr
tags = {
Name = "vpc-${name}"
Environment = name
}
}
}

Accessing for expression results

The result of a for expression is a list. You can access individual elements with index syntax:

let vpcs = for env in ['dev', 'stg'] {
awscc.ec2.vpc {
cidr_block = '10.0.0.0/16'
tags = {
Name = "vpc-${env}"
}
}
}
# Reference the first VPC's attributes
awscc.ec2.subnet {
vpc_id = vpcs[0].vpc_id
cidr_block = '10.0.1.0/24'
availability_zone = 'ap-northeast-1a'
tags = {
Name = 'dev-subnet'
}
}

Local variables in for body

You can define local let bindings inside a for body:

let vpc = awscc.ec2.vpc {
cidr_block = '10.0.0.0/16'
}
let subnets = for (i, az) in ['ap-northeast-1a', 'ap-northeast-1c'] {
let cidr = cidr_subnet('10.0.0.0/16', 8, i)
awscc.ec2.subnet {
vpc_id = vpc.vpc_id
cidr_block = cidr
availability_zone = az
tags = {
Name = "subnet-${az}"
}
}
}

For with modules

You can call modules inside for expressions to create multiple instances of a module. See the Using Modules guide for a full example.

If expressions

An if expression conditionally creates a resource or selects a value.

Conditional resources

Create a resource only when a condition is true:

let enabled = true
let vpc = if enabled {
awscc.ec2.vpc {
cidr_block = '10.0.0.0/16'
tags = {
Name = 'conditional-vpc'
}
}
}

When enabled is false, no VPC is created and the let binding is empty.

Conditional values with if/else

Use if/else as a value expression to choose between two values:

let is_production = true
awscc.ec2.vpc {
cidr_block = if is_production { '10.0.0.0/16' } else { '172.16.0.0/16' }
tags = {
Name = if is_production { 'prod-vpc' } else { 'dev-vpc' }
}
}

This creates a single VPC but uses different CIDR blocks and names depending on the condition.

Combining for and if

You can use if expressions inside for bodies and vice versa:

let environments = {
dev = '10.0.0.0/16'
stg = '10.1.0.0/16'
prd = '10.2.0.0/16'
}
let vpcs = for name, cidr in environments {
awscc.ec2.vpc {
cidr_block = cidr
enable_dns_hostnames = if name == 'prd' { true } else { false }
tags = {
Name = "vpc-${name}"
Environment = name
}
}
}