Day 2 - Terraform Configuration Language (HCL)

Fuzail Ahmed
8 min readJun 7, 2023

--

HCL (HashiCorp Configuration Language) is a declarative language used in Terraform to define infrastructure configurations. It provides a clean and readable syntax for expressing resources and their dependencies.

Task 1 - Familiarize yourself with the HCL syntax used in Terraform
Learn about HCL blocks, parameters, and arguments.
Explore the different types of resources and data sources available in Terraform

Task 2 - Understand variables, data types, and expressions in HCL

Task 3 - Practice writing Terraform configurations using HCL syntax

Task 1 — Familiarize yourself with the HCL syntax used in Terraform

1. HCL Blocks:

  • HCL (HashiCorp Configuration Language) is a domain-specific language (DSL) used in Terraform to define and configure infrastructure resources. HCL files typically have a .tf extension and contain the configuration for a Terraform project. HCL uses blocks to define resources. Within each block, you can specify attributes and their corresponding values to configure the desired behavior of the resource.
  • A block is a container for other content. Blocks have a type that can have zero or more required labels followed by { } brackets that contain the block's body. Blocks can be nested inside each other. This a general representation of a block
  • HCL uses blocks to define resources and modules. A block is a collection of parameters and arguments that define a specific resource or module. The basic structure of a block is as follows:
block_type "block_label" {
parameter1 = value1
parameter2 = value2
...
}

For example, a resource block to define an AWS S3 bucket could look like this:

resource "aws_s3_bucket" "my_bucket" {
bucket = "my-bucket"
acl = "private"
}

There are several block types used to define different aspects of infrastructure configuration.

1.Provider Block

  • Specifies the cloud or service provider that Terraform will interact with.
  • Contains configuration settings such as access credentials and API endpoints.

2.Resource Block

  • Defines a specific infrastructure resource that Terraform will manage.
  • Specifies the resource type, such as EC2 instances, S3 buckets, or VPCs. Contains attributes that configure the behavior and properties of the resource.

3.Data Block

  • Retrieves and imports data from an external source into the Terraform configuration.
  • Allows you to query and fetch information to use in resource configurations. Typically used to gather information about existing infrastructure resources.

4.Variable Block

  • Declares input variables that can be passed into the Terraform configuration.
  • Specifies the variable name, type, default value, and other optional properties. Enables parameterization and dynamic configuration of the infrastructure.

5.Output Block

  • Defines values that Terraform will display as outputs after successful resource provisioning.
  • Allows you to expose information from the infrastructure for use by other systems or modules. Specifies the output name and the value to be displayed.

6.Module Block

  • Encapsulates a reusable set of Terraform configurations into a single module.
  • Defines input variables and output values specific to the module. It enables code reuse and modularity by grouping related resources and configurations.

7.Provisioner Block

  • Specifies actions to be taken on a resource after it is created or updated.
  • Allows for running scripts or executing commands on the resource. It is commonly used for tasks like initialization, configuration, or software installation.

8.Locals Block

  • Declares local values or expressions that can be used within the Terraform configuration.
  • Enables the creation of intermediate variables or complex expressions for reuse.

9.Terraform Block

  • Contains global configuration settings for Terraform itself and includes backend configuration, required provider versions, and other global settings.
  • Allows you to configure how Terraform behaves during the execution of the configuration.

2. Parameters and Arguments:

  • Parameters are the predefined attributes that a block accepts, while arguments are the corresponding values assigned to those parameters. Each block type has its own set of parameters and their required or optional arguments. In the above example, “bucket” and “acl” are parameters of the “aws_s3_bucket” resource block, and “my_bucket” and “private” are their respective arguments.
provider "aws" {
region = var.region
access_key = "<your_access_key>"
secret_access_key = "<your_secret_access_key>"
}

provider is the block keyword used to define a provider.

"aws"Provider type

region, access_key, and secret_access_key — Configuration Parameters

<your_access_key> , <your_secret_access_key>Arguments

3. Resource and Data Sources:

  • Terraform provides two primary types of blocks: resource blocks and data blocks.

i. Resource Blocks:

  • Resource blocks define the desired infrastructure resources you want to manage. They represent entities like virtual machines, databases, networks, etc., that Terraform provisions, updates, or destroys. Resource blocks start with the keyword “resource”.
  • Resources are the most important part of Terraform. Resources are defined by resource blocks. A resource can define one or more infrastructure resource objects, such as VPCs, virtual machines, or DNS records, key-value pair data, etc.
resource "aws_instance" "web_server" {
ami = "ami-a1b2c3d4"
instance_type = "t2.micro"
}

🛑 Types of resources

1.Compute Resources:

  • Instances: Virtual machines or server instances, such as AWS EC2 instances, Google Compute Engine instances, or Azure virtual machines.
  • Containers: Container resources, like AWS ECS tasks, Kubernetes pods, or Azure Container Instances.
  • Serverless Functions: Resources for serverless computing, such as AWS Lambda functions, Google Cloud Functions, or Azure Functions.

2.Networking Resources:

  • Virtual Networks: Network components like virtual private clouds (VPCs), subnets, and routing tables, such as AWS VPC, Google VPC, or Azure VNet.
  • Load Balancers: Resources for load balancing traffic, like AWS ELB/ALB/NLB, Google Load Balancer, or Azure Load Balancer.
  • DNS: Domain Name System resources, such as AWS Route 53, Google Cloud DNS, or Azure DNS.

3.Storage Resources:

  • Block Storage: Resources for block-level storage, such as AWS EBS volumes, Google Persistent Disks, or Azure Managed Disks.
  • Object Storage: Resources for object storage, like AWS S3 buckets, Google Cloud Storage buckets, or Azure Blob Storage.
  • File Storage: Resources for file storage, such as AWS EFS, Google Cloud Filestore, or Azure Files.

4.Database Resources:

  • Relational Databases: Managed relational databases, like AWS RDS, Google Cloud SQL, or Azure Database for MySQL/PostgreSQL/SQL Server.
  • NoSQL Databases: Managed NoSQL databases, such as AWS DynamoDB, Google Cloud Firestore, or Azure Cosmos DB.
  • Data Warehouses: Resources for data warehousing, like AWS Redshift, Google BigQuery, or Azure Synapse Analytics.

5.Security Resources:

  • Identity and Access Management: Resources for managing identities, permissions, and access control, such as AWS IAM, Google Cloud IAM, or Azure AD.
  • Encryption and Key Management: Resources for encryption and key management, like AWS KMS, Google Cloud KMS, or Azure Key Vault.
  • Security Groups: Resources for network security groups or firewalls, such as AWS Security Groups, Google VPC Firewall Rules, or Azure Network Security Groups.

ii. Data Sources:

Data blocks retrieve information from an external source, such as an API, configuration file, or existing infrastructure. They allow you to query and reference data within your Terraform configuration. Data blocks start with the keyword “data”.

🔹 Types of Data Sources

1.Infrastructure Data Sources

  • “aws_vpc” — Retrieves information about an existing Amazon VPC.
  • “google_compute_network” — Retrieves information about a Google Cloud VPC network.
  • “azurerm_subnet” — Retrieves information about an Azure subnet.

2.Cloud Service Data Sources

  • “aws_s3_bucket” — Retrieves information about an existing Amazon S3 bucket.
  • “google_storage_bucket” — Retrieves information about a Google Cloud Storage bucket.
  • “azurerm_cosmosdb_account” — Retrieves information about an Azure Cosmos DB account.

3.DNS Data Sources

  • “aws_route53_zone” — Retrieves information about an Amazon Route 53 DNS zone.
  • “google_dns_managed_zone” — Retrieves information about a Google Cloud DNS managed zone.
  • “azurerm_dns_zone” — Retrieves information about an Azure DNS zone.

4.Security Data Sources

  • “aws_iam_policy” — Retrieves information about an AWS IAM policy.
  • “google_service_account” — Retrieves information about a Google Cloud service account.
  • “azurerm_key_vault” — Retrieves information about an Azure Key Vault.

5.Database Data Sources

  • “aws_db_instance” — Retrieves information about an Amazon RDS database instance.
  • “google_sql_database_instance” — Retrieves information about a Google Cloud SQL database instance.
  • “azurerm_mariadb_server” — Retrieves information about an Azure Database for MariaDB server.

Task 2— Variables, Data Types, and Expressions in HCL:

1. Variables:

  • Variables in HCL allow you to parameterize your Terraform configuration and make it more reusable. You can define variables to represent values that may change across environments or need to be dynamic. Variables can have default values or be provided at runtime.
  • Variable declaration example:

Create a variables.tf file and define a variable

The variable declaration can optionally include three arguments:

  • description: briefly explain the purpose of the variable and what kind of value is expected.
  • type: specifies the type of value such as string, number, bool, map, list, etc.
  • default: If present, the variable is considered to be optional and if no value is set, the default value is used.

🔹 Defining Variables

To define a variable, create a variable.tf file and add the following code:

variable "filename" {
type = string
}

In this example, we are defining a variable called filename with a data type of string.

🔹 Using Variables

To use a variable in your Terraform configuration, you can reference it using the ${var.variable_name} syntax. Here is an example of how to use the filename variable in a main.tf file:

resource "local_file" "example" {
filename = "${var.filename}"
content = "Hello, World!"
}

In this example, we are creating a local_file resource and using the filename variable as the name of the file.

2. Data Types:

  • HCL supports various data types, including string, number, boolean, list, and map. You can assign values of different data types to variables or use them directly within resource blocks.

3. Expressions:

  • HCL allows you to use expressions to compute or manipulate values within your Terraform configuration. Expressions can perform operations, use built-in functions, or reference variables and attributes of resources.

Task 3 — Writing Terraform Configurations using HCL Syntax:

STEP 1: Create an Instance

STEP 2: Install Terraform by using the commands given in https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli

STEP 3: Create a working directory and variables.tf , main.tffile.

sudo su
mkdir terraform
cd terraform/
pwd #copy_the_path
variable "filename" {
default = "/home/ubuntu/terraform/devops-automate.txt"

}

variable "aws_ec2_object" {
type = object({
name = string
instances = number
keys = list(string)
ami = string
})
default = {
name = "test_ec2_instance"
instances = 4
keys = ["key1.pem","key2.pem"]
ami = "ubuntu-afed34"
}
}

In main.tf file,

resource "local_file" "sample" {
filename = "/home/ubuntu/terraform/devops-automate.txt"
content = "Sample_Terraform_Code"
}

output "aws_ec2_instances" {
value = var.aws_ec2_object.instances
}
terraform init
terraform validate
terraform plan
terraform apply

Example 2:

variable "region" {
description = "AWS region to deploy resources"
default = "us-west-2"
}

resource "aws_instance" "my_instance" {
ami = "ami-12345678"
instance_type = "t2.micro"
count = 2

tags = {
Name = "my-instance-${count.index + 1}"
}
}

data "aws_vpc" "my_vpc" {
id = "vpc-12345678"
}

output "instance_ip" {
value = aws_instance.my_instance.*.public_ip
}
  • In the above example:
  • A variable named “region” is defined.
  • An AWS EC2 instance resource block is created with attributes such as AMI, instance type, count, and tags.
  • A data block is used to fetch information about an existing AWS VPC.
  • An output block is defined to display the public IP addresses of the instances created.

Example 3:

Add required_providers to your configuration, such as Docker or AWS

  • Open the main.tf file in a text editor.
  • Add the required_providers block at the top of the file to specify the providers you need.

🔹 Checkout GitHub Repository for projects:

🔗 https://github.com/FuzailN

🔗 linkedin: https://www.linkedin.com/in/fuzail_ahmed06/

Thank you, shubhamlondhe , for the wonderful session

#devops #terraweek #terraform #hcl #aws

--

--