Interpolation and Conditionals
Terrform provides a way of interpolating values using ${...}
. We can use simple math functions, refer to other variables, or use conditional logic here. For example,
Variables: ${var.VARIABLE_NAME} refers to a variable.
Resources: ${type.resource-name.attr} refers to a resource declared.
Data source: ${data.type.resource-name.attr} refers to any rendered or dynamic data.
Usage of different variable types with interpolation
Name
Syntax
Example
Strings
var.name
${var.SOMETHING}
Maps
var.MAP["key"]
${var.AMIS["us-east-1"]}
${lookup(var.AMIS, var.AWS_REGION)}
Lists
var.LIST, var.LIST[i]
${var.subnets[i]}
${join(",", var.subnets)}
Usage of some other types of items with interpolation
Name
Syntax
Example
Output of a module
module.NAME.output
${module.aws_vpc.vpcid}
Count information
count.FIELD
When using the attribute count =
number in a resource, we can use ${count.index}
Path information
path.TYPE
path.cwd(current directory)
path.module(module path)
path.root(root module path)
Meta information
terraform.FIELD
terraform.env shows active workspace
In addition to these, interpolation supports Add (+), Subtract (-), and Divide (/) for float types, and additionally Modulo (%) for integer types.
Conditionals
Interpolations may contain conditionals. The syntax looks like below for conditional statements.
CONDITION ? TRUE-VALUE : FALSE-VALUE
For example,
resource "aws_instance" "myinstance" {
...
count = "${var.env == "prod" ? 2 : 1}"
}
I will provision an EC2 instance in the example below.
First let's start creating a file with the name vars.tf
,
variable "AWS_REGION" {
default = "eu-west-1"
}
variable "PATH_TO_PRIVATE_KEY" {
default = "mykey"
}
variable "PATH_TO_PUBLIC_KEY" {
default = "mykey.pub"
}
variable "ENV" {
default = "prod"
}
Then the provider.tf
,
provider "aws" {
region = var.AWS_REGION
}
Next let's create a file for out VPCs; vpc.tf
,
module "vpc-prod" {
source = "terraform-aws-modules/vpc/aws"
version = "2.59.0"
name = "vpc-prod"
cidr = "10.0.0.0/16"
azs = ["${var.AWS_REGION}a", "${var.AWS_REGION}b", "${var.AWS_REGION}c"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]
enable_nat_gateway = false
enable_vpn_gateway = false
tags = {
Terraform = "true"
Environment = "prod"
}
}
module "vpc-dev" {
source = "terraform-aws-modules/vpc/aws"
version = "2.59.0"
name = "vpc-dev"
cidr = "10.0.0.0/16"
azs = ["${var.AWS_REGION}a", "${var.AWS_REGION}b", "${var.AWS_REGION}c"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]
enable_nat_gateway = false
enable_vpn_gateway = false
tags = {
Terraform = "true"
Environment = "dev"
}
}
Two important things to notice in here are that I use interpolation to name availability zones of the VPC, and that I introduce tag with the name Environment for future use.
Next let's create a file with the name securitygroup.tf
,
resource "aws_security_group" "allow-ssh-prod" {
vpc_id = module.vpc-prod.vpc_id
name = "allow-ssh"
description = "security group that allows ssh and all egress traffic"
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "allow-ssh"
}
}
resource "aws_security_group" "allow-ssh-dev" {
vpc_id = module.vpc-dev.vpc_id
name = "allow-ssh"
description = "security group that allows ssh and all egress traffic"
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "allow-ssh"
}
}
To keep out keys a file with the name key.tf
,
resource "aws_key_pair" "mykeypair" {
key_name = "mykeypair"
public_key = file(var.PATH_TO_PUBLIC_KEY)
}
Finally, instance.tf
,
data "aws_ami" "ubuntu" {
most_recent = true
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-trusty-14.04-amd64-server-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
owners = ["099720109477"] # Canonical
}
resource "aws_instance" "example" {
ami = data.aws_ami.ubuntu.id
instance_type = "t2.micro"
# the VPC subnet
subnet_id = var.ENV == "prod" ? module.vpc-prod.public_subnets[0] : module.vpc-dev.public_subnets[0]
# the security group
vpc_security_group_ids = [var.ENV == "prod" ? aws_security_group.allow-ssh-prod.id : aws_security_group.allow-ssh-dev.id]
# the public SSH key
key_name = aws_key_pair.mykeypair.key_name
}
In here you can notice that I'm assigning subnet and security group ids based on the environment type.
Generate ssh keys,
$ ssh-keygen -f mykey
Initialize the providers,
$ terraform init
Apply the changes,
$ terraform apply
Don't forget to clean up once experiments are done,
$ terraform destroy
Last updated
Was this helpful?