Terraform Variables
Unlocking Terraform's Power: Harnessing the Magic of Input, Output & Local Variables.
Table of contents
Input variables
In Terraform, input variables allow you to parameterize your configurations. This makes your Terraform configurations more flexible and reusable by allowing users to define values externally, without hardcoding them in the configuration files.
Here’s a detailed explanation of how to use input variables in Terraform, including examples:
Defining Input Variables
Creating a
variables.tf
FileYou define input variables in a separate file, commonly named
variables.tf
. Each variable is defined using thevariable
block.variable "vpc_cidr" { description = "The CIDR block for the VPC" type = string default = "10.0.0.0/16" } variable "public_subnet_cidr" { description = "The CIDR block for the public subnet" type = string } variable "private_subnet_cidr" { description = "The CIDR block for the private subnet" type = string } variable "region" { description = "The AWS region to deploy resources in" type = string default = "us-east-2" }
Using Input Variables
Referencing Variables in Configuration Files
Use the defined variables in your resource configurations by referencing them with
var.<variable_name>
.provider "aws" { region = var.region } resource "aws_vpc" "main" { cidr_block = var.vpc_cidr tags = { Name = "main-vpc" } } resource "aws_subnet" "public" { vpc_id = aws_vpc.main.id cidr_block = var.public_subnet_cidr tags = { Name = "public-subnet" } } resource "aws_subnet" "private" { vpc_id = aws_vpc.main.id cidr_block = var.private_subnet_cidr tags = { Name = "private-subnet" } }
Providing Values for Variables
Using a
terraform.tfvars
FileCreate a
terraform.tfvars
file to assign values to your variables.vpc_cidr = "10.0.0.0/16" public_subnet_cidr = "10.0.1.0/24" private_subnet_cidr = "10.0.2.0/24" region = "us-west-2"
Using Command-Line Flags
You can also specify variable values directly when running the
terraform apply
command.terraform apply -var="vpc_cidr=10.0.0.0/16" -var="public_subnet_cidr=10.0.1.0/24" -var="private_subnet_cidr=10.0.2.0/24"
Using Environment Variables
Set environment variables using the
TF_VAR_
prefix.export TF_VAR_vpc_cidr="10.0.0.0/16" export TF_VAR_public_subnet_cidr="10.0.1.0/24" export TF_VAR_private_subnet_cidr="10.0.2.0/24" terraform apply
Example
Here’s a complete example demonstrating the use of input variables in a Terraform configuration:
-
variable "vpc_cidr" { description = "The CIDR block for the VPC" type = string default = "10.0.0.0/16" } variable "public_subnet_cidr" { description = "The CIDR block for the public subnet" type = string } variable "private_subnet_cidr" { description = "The CIDR block for the private subnet" type = string } variable "region" { description = "The AWS region to deploy resources in" type = string default = "us-east-2" }
-
provider "aws" { region = var.region } resource "aws_vpc" "main" { cidr_block = var.vpc_cidr tags = { Name = "main-vpc" } } resource "aws_subnet" "public" { vpc_id = aws_vpc.main.id cidr_block = var.public_subnet_cidr tags = { Name = "public-subnet" } } resource "aws_subnet" "private" { vpc_id = aws_vpc.main.id cidr_block = var.private_subnet_cidr tags = { Name = "private-subnet" } }
terraform.tfvars
public_subnet_cidr = "10.0.1.0/24" private_subnet_cidr = "10.0.2.0/24"
Running Terraform
terraform init
terraform apply
This setup ensures that you can easily manage your Terraform configurations by changing variable values without modifying the configuration files themselves, promoting better modularity and reusability.
Output variables
In Terraform, output variables are used to display information about your infrastructure after it's been applied. These outputs can be useful for retrieving values like instance IDs, IP addresses, or other resource attributes that might be needed for further automation or integration.
Here’s an overview of how to define and use output variables in Terraform:
How to Define an Output Variable
You define an output variable in a separate file (typically outputs.tf
) or at the end of your main.tf
file. Here's the general syntax:
output "output_name" {
value = resource_attribute_or_expression
}
Example of Output Variables
Let's add some output variables to the project we've been working on. We’ll output the VPC ID, public subnet ID, private subnet ID, and the public and private EC2 instance IDs.
outputs.tf
output "vpc_id" {
description = "The ID of the VPC"
value = aws_vpc.dev_vpc.id
}
output "public_subnet_id" {
description = "The ID of the public subnet"
value = aws_subnet.public_subnet.id
}
output "private_subnet_id" {
description = "The ID of the private subnet"
value = aws_subnet.private_subnet.id
}
output "public_instance_id" {
description = "The ID of the public EC2 instance"
value = aws_instance.public_instance.id
}
output "private_instance_id" {
description = "The ID of the private EC2 instance"
value = aws_instance.private_instance.id
}
output "public_instance_ip" {
description = "The public IP address of the public EC2 instance"
value = aws_instance.public_instance.public_ip
}
output "private_instance_ip" {
description = "The private IP address of the private EC2 instance"
value = aws_instance.private_instance.private_ip
}
Explanation of the Outputs
VPC ID:
output "vpc_id" { description = "The ID of the VPC" value = aws_vpc.dev_vpc.id }
- Outputs the ID of the created VPC.
Public Subnet ID:
output "public_subnet_id" { description = "The ID of the public subnet" value = aws_subnet.public_subnet.id }
- Outputs the ID of the public subnet.
Private Subnet ID:
output "private_subnet_id" { description = "The ID of the private subnet" value = aws_subnet.private_subnet.id }
- Outputs the ID of the private subnet.
Public Instance ID:
output "public_instance_id" { description = "The ID of the public EC2 instance" value = aws_instance.public_instance.id }
- Outputs the ID of the public EC2 instance.
Private Instance ID:
output "private_instance_id" { description = "The ID of the private EC2 instance" value = aws_instance.private_instance.id }
- Outputs the ID of the private EC2 instance.
Public Instance IP:
output "public_instance_ip" { description = "The public IP address of the public EC2 instance" value = aws_instance.public_instance.public_ip }
- Outputs the public IP address of the public EC2 instance.
Private Instance IP:
output "private_instance_ip" { description = "The private IP address of the private EC2 instance" value = aws_instance.private_instance.private_ip }
- Outputs the private IP address of the private EC2 instance.
Usage
After you apply your Terraform configuration with terraform apply
, Terraform will output the specified values. This can be very helpful for debugging, integration with other scripts, or just verifying that your infrastructure was created as expected.
Example Output
When you run terraform apply
, the output might look something like this:
Apply complete! Resources: X added, Y changed, Z destroyed.
Outputs:
private_instance_id = "i-0a1b2c3d4e5f6g7h8"
private_instance_ip = "10.0.20.123"
private_subnet_id = "subnet-0a1b2c3d4e5f6g7h8"
public_instance_id = "i-1a2b3c4d5e6f7g8h9"
public_instance_ip = "54.210.123.456"
public_subnet_id = "subnet-1a2b3c4d5e6f7g8h9"
vpc_id = "vpc-0a1b2c3d4e5f6g7h8"
This makes it easy to see the IDs and IP addresses of your resources without having to manually look them up in the AWS Management Console.
Local Variables
Local variables in Terraform provide a way to simplify and manage your configuration by creating reusable values that can be referenced throughout your Terraform files. They help to make your configuration more modular, readable, and maintainable.
Defining Local Variables
Local variables are defined using the locals
block. Here’s a simple example:
locals {
instance_type = "t2.micro"
environment = "dev"
ami_id = "ami-0c55b159cbfafe1f0"
}
Using Local Variables
Once defined, you can reference local variables using the local
keyword followed by the variable name. Here’s how you can use the local variables in your Terraform configuration:
# Using local variables in an aws_instance resource
resource "aws_instance" "example" {
ami = local.ami_id
instance_type = local.instance_type
tags = {
Name = "Example-${local.environment}"
}
}
This example showcasing the use of local variables in a different Terraform configuration. This example will set up an S3 bucket with versioning and server-side encryption enabled, and a DynamoDB table.
Configuration with Local Variables
locals.tf
locals {
region = "us-west-2"
bucket_name = "my-unique-bucket-name"
dynamodb_table = "my-dynamodb-table"
environment = "production"
versioning = true
sse_algorithm = "AES256"
read_capacity = 5
write_capacity = 5
tags = {
Environment = local.environment
ManagedBy = "Terraform"
}
}
provider.tf
provider "aws" {
region = local.region
}
s3.tf
# Create S3 bucket
resource "aws_s3_bucket" "bucket" {
bucket = local.bucket_name
tags = local.tags
}
# Enable versioning on the S3 bucket
resource "aws_s3_bucket_versioning" "versioning" {
bucket = aws_s3_bucket.bucket.id
versioning_configuration {
status = local.versioning ? "Enabled" : "Suspended"
}
}
# Enable server-side encryption on the S3 bucket
resource "aws_s3_bucket_server_side_encryption_configuration" "sse" {
bucket = aws_s3_bucket.bucket.bucket
rule {
apply_server_side_encryption_by_default {
sse_algorithm = local.sse_algorithm
}
}
}
dynamodb.tf
# Create DynamoDB table
resource "aws_dynamodb_table" "table" {
name = local.dynamodb_table
billing_mode = "PROVISIONED"
read_capacity = local.read_capacity
write_capacity = local.write_capacity
hash_key = "ID"
attribute {
name = "ID"
type = "S"
}
tags = local.tags
}
Explanation
-
- Defines various local variables for region, bucket name, DynamoDB table name, environment, versioning, server-side encryption algorithm, read and write capacities, and common tags.
-
- Configures the AWS provider to use the specified region from local variables.
-
Uses local variables to create an S3 bucket with versioning and server-side encryption enabled.
aws_s3_bucket
: Creates the S3 bucket with a name from local variables and tags.aws_s3_bucket_versioning
: Enables or disables versioning on the bucket based on the local variable.aws_s3_bucket_server_side_encryption_configuration
: Sets up server-side encryption using the specified algorithm.
-
Uses local variables to create a DynamoDB table with the specified read and write capacities, and tags.
aws_dynamodb_table
: Defines the table with attributes and capacities based on local variables.
Benefits of Using Local Variables
Consistency: Ensures consistent values across your configuration.
Ease of Updates: Changing a value in one place updates it everywhere it is used.
Readability: Makes your configuration easier to read and understand by abstracting frequently used values.
Local variables are a powerful feature in Terraform that help to keep your configuration DRY (Don't Repeat Yourself), making it more manageable and less error-prone.