Terraform offers a strong set of features to help optimize your Terraform code. Two really useful features are
- dynamic blocks, which allow you to generate static repeated blocks within resources in Terraform.
You can dynamically construct repeatable nested blocks like ingress
using a special dynamic block type, which is supported inside resource, data, provider, and provisioner blocks
.
A dynamic block acts much like a for expression
, but produces nested blocks instead of a complex typed value. It iterates over a given complex value, and generates a nested block for each element of that complex value.
- built-in functions, which help you manipulate variables and data to suit your needs and help make your Terraform deployments better automated and more fault resilient.
The Terraform language includes a number of built-in functions that you can call from within expressions to transform and combine values.
The general syntax for function calls is a function name followed by comma-separated arguments in parentheses - timestamp()
Please visit my GitHub Repository for Terraform articles on various topics being updated on constant basis.
Let’s get started!
Objectives:
1. Login to AWS Management Console
2. Create infrastructure for application block
3. Under terraform_files
application directory - Create 4 files - main.tf
, apache.sh
, variables.tf
, outputs.tf
4. Initialize Terraform
5. To generate the action plans
6. Create all the resources declared in main.tf configuration file
7. Validate all resources created
Pre-requisites:
- AWS user account with admin access, not a root account.
- Cloud9 IDE with AWS CLI.
Resources Used:
Terraform documentation.
Terraform documentation for AMI.
dynamic Blocks
Built-in Functions
Steps for implementation to this project:
1. Login to AWS Management Console
- Make sure you're in the N. Virginia (us-east-1) region
2. Create infrastructure for application block
- Let’s create the following organizational structure as shown below.
3. Under terraform_files
application directory - Create 4 files - main.tf
, apache.sh
, variables.tf
, outputs.tf
.
Create a directory -
terraform-files
Create 4 files -
main.tf
,apache.sh
,variables.tf
,outputs.tf
.main.tf
Data Source: aws_ssm_parameter
ssm_parameter public endpoint resource is to get the AMI ID of the Amazon Linux 2 image that will spin up the EC2 webserver.
security_group resource uses a dynamic block on the ingress
attribute to dynamically generate as many ingress blocks as we need. The dynamic block includes the var.rules
complex variable configured in the variables.tf
file.
join Function
for_each Meta-Argument
built-in functions like the join
function for the name attribute in the security group resource, and the fileexists
and file
functions for the user_data parameter in the EC2 instance resource and which then installs the Apache webserver and starts up the service.
provider "aws" {
region = "us-east-1"
}
data "aws_ssm_parameter" "ami_id" {
name = "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2"
}
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
name = "my-vpc"
cidr = "10.0.0.0/16"
azs = ["us-east-1a"]
public_subnets = ["10.0.1.0/24"]
}
resource "aws_security_group" "my-sg" {
vpc_id = module.vpc.vpc_id
name = join("_", ["sg", module.vpc.vpc_id])
dynamic "ingress" {
for_each = var.rules
content {
from_port = ingress.value["port"]
to_port = ingress.value["port"]
protocol = ingress.value["protocol"]
cidr_blocks = ingress.value["cidr_blocks"]
}
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "Dynamic-SG"
}
}
resource "aws_instance" "my-instance" {
ami = data.aws_ssm_parameter.ami_id.value
subnet_id = module.vpc.public_subnets[0]
instance_type = "t2.micro"
security_groups = [aws_security_group.my-sg.id]
associate_public_ip_address = true
user_data = fileexists("script.sh") ? file("script.sh") : null
}
- 2.
apache.sh
#!/bin/bash
sudo yum -y install httpd
sudo systemctl start httpd && sudo systemctl enable httpd
- 3.
variables.tf
variable "rules" - Declaring an Input Variable
variable "rules" {
type = list(object({
port = number
protocol = string
cidr_blocks = list(string)
}))
default = [
{
port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
},
{
port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
},
{
port = 3689
protocol = "tcp"
cidr_blocks = ["101.34.81.98/32"]
}
]
}
- 4.
outputs.tf
output "Web-Server-URL" {
description = "Web-Server-URL"
value = join("", ["http://", aws_instance.my-instance.public_ip])
}
output "Time-Date" {
description = "Date/Time of Execution"
value = timestamp()
}
4. Initialize Terraform
cd terraform-files
-
terraform status
terraform version
Since the Terraform version is returned, you have validated that the Terraform binary is installed and functioning properly.
Note:
If you receive a notification that there is a newer version of Terraform available, you can ignore it — it will run safely with the version installed on the VM.
-
terraform init
will check for all the plugin dependencies and download them if required, this will be used for creating a deployment plan.
terraform init
5. To generate the action plans, run the below command:
terraform plan
6. Create all the resources declared in main.tf configuration file
Note:
The --auto-approve flag will prevent Terraform from prompting you to enter yes explicitly before it deploys the code.
terraform apply --auto-approve
terraform state list
- Validate all resources created
- VPC
- EC2
- Security Group and Inbound rules
Cleanup
- terraform destroy
What we have done so far
We have successfuly deployed AWS resources using Terraform Dynamic Blocks ingress
and Built-in Functions join
, fileexists
and file
.
Top comments (0)