Terraweek#Day02-Terraform Configuration language(HCL)understanding and Syntax writing
#Terraweekchallenge#day02
Table of contents
- <mark>What is HCL?</mark>
- <mark>The HCL language and features</mark>
- <mark>Editing HCL configurations easily</mark>
- <mark>How to Create an EC2 Instance on AWS</mark>
- <mark>Variables in Terraform:</mark>
- <mark>Expressions in Terraform:</mark>
- <mark>Types and Values</mark>
- Data Types in Terraform e.g.list/map/object:
- <mark>Type M</mark><mark>ap</mark>
- <mark>Datatype:List</mark>
- <mark>Type:Object</mark>
- <mark>Practice writing Terraform configurations using HCL sytax:</mark>
What is HCL?
HashiCorp Configuration Language (HCL) is a unique configuration language. It was designed to be used with HashiCorp tools, notably Terraform, but HCL has expanded as a more general configuration language. It’s visually similar to JSON with additional data structures and capabilities built-in.
HCL consists of three sub-languages:
Structural
Expression
Templates
When combined, the sub-languages form a well structured HCL configuration file. This structure helps accurately and easily describe environmental configurations necessary for the Terraform tool.
The HCL language and features
HCL is a JSON compatible language that adds features to help you use the Terraform tool to its highest potential. These features make HCL a powerful configuration language and address some of JSON's shortcomings.
Comments are available as single line or multi-line:
Single Line:
#
or//
.Multi-Line:
/* */
(no nesting of block comments).
Variable assignments use the
key = value
construction where whitespace does not matter and the value can be a primitive such as a string, number, boolean, object, or a list.Strings are quoted and can contain any UTF-8 characters.
Numbers can be written and parsed in a number of different ways:
Base 10 numbers are the default.
Hexadecimal: Prefix a number with
0x
.Octal: Prefix a number with a
0
.Scientific numbers: Use the notation such as
1e10
.
Arrays and lists of objects are easy to create using
[]
for arrays and{ key = value }
for lists.
This overview only scratches the surface of what HCL can do. It’s easier to see how HCL works by exploring an example configuration file and analyzing how it works.
Editing HCL configurations easily
Visual Studio Code (VS Code) is currently one of the most popular editors and it’s offered for free by Microsoft. VS Code has extensions that add additional functionality to the base editor. These include:
An HCL extension to offer proper language colorization.
The Terraform extension that also adds HCL support, despite being named for one of the HashiCorp tools. This extension offers syntax highlighting and basic validation.
The Atom editor is an alternative editor to VS Code and is also popular. It offers an HCL syntax highlighting package as well.
Syntax:Arguments and Blocks in Terraform
The first example below creates an EC2 instance:
provider “aws” {
region = “us-west-1”
}
resource “aws_instance” “myec2” {
ami = “ami-053b0d53c279acc90t”
instance_type = “t2.micro”
}
The code consists of two blocks wrapped in curly braces ( {} ), and each of these blocks has certain arguments defined.
Just like in most programming languages, you use arguments to assign values to variables. In Terraform, these variables are attributes associated with a particular type of block.
The provider “aws” block has one argument – region = “us-west-1”
, where the region is an attribute associated with the block, and it is assigned a value “us-west-1”. The value is a string type, so it is enclosed in a pair of double quotes ( “” ).
Similarly, the resource block has two arguments that set the values of associated attributes.
Terraform uses various types of blocks. Based on the type, blocks represent and enclose a set of attributes and functions. In the given example, we have a block of type provider and another of type resource, and each block has an identifier and a set of input labels.
The provider block takes one input label – the name of the provider. In this case “aws”. It also tells Terraform to install the AWS provider plugin, during the init phase.
The resource block takes 2 inputs labels – the type of resource and the name of the resource. In this case, the type is “aws_instance” and the name is “myec2”. What follows is the block body enclosed in curly braces.
How to Create an EC2 Instance on AWS
So, how do we start expressing our infrastructure as code and make use of it? Let’s take an example of creating a simple EC2 instance on AWS.
Start by creating a directory of your choice where you would place all the configuration code required to create an EC2 instance.
By default, Terraform assumes that all the files with .tf*
extensions in a directory are part of the configuration, irrespective of the file names. Create a file named main.tf
in this directory.
The first thing we need to decide is which providers we are going to use. Since we are going to spin up an EC2 instance on AWS, we need to declare the required providers as you can see in the snippet below:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.0"
}
}
}
provider "aws" {
region = “us-west-1”
}
We have declared two blocks – terraform
and provider
. terraform
is a top-most block, but it is optional as well. It is a good practice to specify this, especially when you're working with remote state management.
The terraform
block has a nested block that specifies required_providers
. We require the aws
provider. aws
within required_providers is a map, which specifies the source
and version
of the provider.
Next, we have a provider block for aws
, which specifies the desired region
.
Generally, this is how every Terraform code starts. Of course, there could be some variations, and the best way to be sure about it is to refer to the Terraform registry for specific versions of Terraform as well as the provider plugin itself.
Below is the example by using AWS provider.
"aws_instance" is a block type.
"example" is block label.
ami and instance_type,key_name,subnet_id etc are the parameters, and "ami-053b0d53c279acc90" , "t2.micro","my_newkey" etc are the arguments.
resource "aws_instance" "example" {
ami = "ami-053b0d53c279acc90"
instance_type = "t2.micro"
key_name = "my_newkey"
subnet_id = aws_subnet.public.id
associate_public_ip_address = true
security_groups = [
aws_security_group.web_server.id
]
Terraform commands you should know before we start:
terraform init:
is a command used in Terraform to initialize a new or existing Terraform working directory. .When you run terraform init
, Terraform will download and install any required providers and modules specified in your configuration files. The command will also initialize a backend, which is responsible for storing Terraform state information.
terraform init -upgrade:
Terraform will check for any outdated or missing providers and modules specified in your configuration files, and download and install the latest versions of these providers and modules. The command will also update the backend, which is responsible for storing Terraform state information
terraform plan:
Terraform will examine your configuration files and create a detailed execution plan that shows what changes will be made to your infrastructure. The plan includes a list of all resources that will be created, modified, or deleted, as well as any changes to resource dependencies or attributes.
terraform apply:
is a command used in Terraform to apply the changes defined in your configuration files to your infrastructure.
terraform validate:
is a command used in Terraform to validate the syntax and configuration of your Terraform files. This command is used to check for errors in your configuration files before applying them.
terraform destroy :
is a command used in the Terraform infrastructure as code (IaC) tool to remove all the resources that were created by a Terraform configuration. It is the opposite of the terraform apply
command
Variables in Terraform:
variables in Terraform are quite important, as you need to hold values of names of instance, configs , etc.
We can create a variables.tf file which will hold all the variables.
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.
variable "filename" {
default = "/home/ubuntu/terrform-tutorials/terraform-variables/demo-var.txt"
}
variable "content" {
default = "This is coming from a variable which was updated"
}
These variables can be accessed by var object in main.tf
Local file creation with variables:
Expressions in Terraform:
Expressions refer to or compute values within a configuration. The simplest expressions are just literal values, like "hello"
or 5
, but the Terraform language also allows more complex expressions such as references to data exported by resources, arithmetic, conditional evaluation, and a number of built-in functions.
Expressions can be used in a number of places in the Terraform language, but some contexts limit which expression constructs are allowed, such as requiring a literal value of a particular type or forbidding references to resource attributes. Each language feature's documentation describes any restrictions it places on expressions.
Types and Values documents the data types that Terraform expressions can resolve to, and the literal syntaxes for values of those types.
Strings and Templates documents the syntaxes for string literals, including interpolation sequences and template directives.
References to Values documents how to refer to named values like variables and resource attributes.
Operators documents the arithmetic, comparison, and logical operators.
Function Calls documents the syntax for calling Terraform's built-in functions.
Conditional Expressions documents the
<CONDITION> ? <TRUE VAL> : <FALSE VAL>
expression, which chooses between two values based on a bool condition.For Expressions documents expressions like
[for s in var.list : upper(s)]
, which can transform a complex type value into another complex type value.Splat Expressions documents expressions like
var.list[*].id
, which can extract simpler collections from more complicated expressions.Dynamic Blocks documents a way to create multiple repeatable nested blocks within a resource or other construct.
Type Constraints documents the syntax for referring to a type, rather than a value of that type. Input variables expect this syntax in their
type
argument.Version Constraints documents the syntax of special strings that define a set of allowed software versions. Terraform uses version constraints in several places.
Types and Values
The result of an expression is a value. All values have a type, which dictates where that value can be used and what transformations can be applied to it.
Types:
The Terraform language uses the following types for its values:
string
: a sequence of Unicode characters representing some text, like"hello"
.number
: a numeric value. Thenumber
type can represent both whole numbers like15
and fractional values like6.283185
.bool
: a boolean value, eithertrue
orfalse
.bool
values can be used in conditional logic.list
(ortuple
): a sequence of values, like["us-west-1a", "us-west-1c"]
. Elements in a list or tuple are identified by consecutive whole numbers, starting with zero.map
(orobject
): a group of values identified by named labels, like{name = "Mabel", age = 52}
.
Strings, numbers, and bools are sometimes called primitive types. Lists/tuples and maps/objects are sometimes called complex types, structural types, or collection types.
Finally, there is one special value that has no type:
null
: a value that represents absence or omission. If you set an argument of a resource tonull
, Terraform behaves as though you had completely omitted it — it will use the argument's default value if it has one, or raise an error if the argument is mandatory.null
is most useful in conditional expressions, so you can dynamically omit an argument if a condition isn't met.
Literal Expressions:
A literal expression is an expression that directly represents a particular constant value. Terraform has a literal expression syntax for each of the value types described above.
Strings
Strings are usually represented by a double-quoted sequence of Unicode characters,
"like this"
. There is also a "heredoc" syntax for more complex strings.String literals are the most complex kind of literal expression in Terraform, and have their own page of documentation. See Strings for information about escape sequences, the heredoc syntax, interpolation, and template directives.
Numbers
Numbers are represented by unquoted sequences of digits with or without a decimal point, like
15
or6.283185
.Bools
Bools are represented by the unquoted symbols
true
andfalse
.Null
The null value is represented by the unquoted symbol
null
.Lists/Tuples
Lists/tuples are represented by a pair of square brackets containing a comma-separated sequence of values, like
["a", 15, true]
.List literals can be split into multiple lines for readability, but always require a comma between values. A comma after the final value is allowed, but not required. Values in a list can be arbitrary expressions.
Maps/Objects
Maps/objects are represented by a pair of curly braces containing a series of
<KEY> = <VALUE>
pairs:{ name = "John" age = 52 }
Data Types in Terraform e.g.list/map/object:
Map: A map is a collection of values where each value is identified by a string label.
In the example below is a map variable named managed_disk_type to define the type of storage we want to use based on the region in Azure. In the default block, there are two string values, “Premium_LRS” and “Standard_LRS” with a named label to identify each one westus2 and eastus.Type Map
variable "file_contents" {
type = map
default = {
"statement1" = "this is cool"
"statement2" = "this is cooler"
}
}
Datatype:List
List: A Terraform list variable is a sequence of similar values indexed by numbers (starting with 0). It accepts any type of value as long as they are all of the same types. Lists can be defined either implicitly or explicitly.
-
Type:Object
Object: An object is a structural type that can contain different types of values, unlike map, list. It is a collection of named attributes that each have their own type.
In the below example, we have declared an object type variable os for the os image that can be used to deploy a VM.Objects, similar to maps, can represent key-value pairs. Objects have additional functionality that allow them to be used as a data structure. Objects are defined using curly braces
{}
and the.
operator is used to access object properties.
Practice writing Terraform configurations using HCL sytax:
Best practices to write Terraform configurations:
Structuring.
Naming Convention
Use Shared Modules
Latest Version
Backup System State
Lock State File
Use self Variable
Minimize Blast Radius
Use var-file
User Docker
Few examples:
Terraform Providers
Terraform Providers are essentially plugins that Terraform installs to interact with the remote systems i.e. Azure/AWS/Google Cloud/ VMware and a lot of other vendors devices.
here is the e.g.by using AWS provider.
ubuntu@ip-172-31-89-245:~/day66b$ cat provider.tf # Configure the AWS Provider provider "aws" { region = "us-east-1" }
Vpc creation:
Resource:
In Terraform, 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, Consul key-value pair data, etc.resource "aws_vpc" "main" { cidr_block = "10.0.0.0/16" tags = { Name = "main" } }
Subnet creation:
#subnet.tf resource "aws_subnet" "private" { vpc_id = aws_vpc.main.id cidr_block = "10.0.32.0/20" availability_zone = "us-east-1a" tags = { Name = "private" } } resource "aws_subnet" "public" { vpc_id = aws_vpc.main.id cidr_block = "10.0.16.0/20" availability_zone = "us-east-1a" tags = { Name = "public" } }
linkdin:https://www.linkedin.com/in/gajanan-barure-7351a4140
github:https://github.com/gsbarure/Terraform.git
Happy Learning :)
Thank you for reading!! Hope you find this helpful.
Terraweekday02#challenge90daysofdevops