Terraform: Transforming code into infrastructure
By: Omkar Birade
Tags: Infrastructure As Code, DevOps, Terraform, AWS, Infrastructure

How does it happen?

If you followed the video you would notice our directory containing the file was no ordinary directory.

It was transformed into a magic directory using the spell terraform init 😝

The terraform init command is used to initialize a working directory containing Terraform configuration files. This is when Terraform searches the configuration for both direct and indirect references to providers(AWS, GCP, Azure, etc) and installs their respective plugin so that Terraform can talk to these providers through their APIs.

terraform init output

After successful installation, Terraform writes information about the selected providers to the dependency lock file.

This is followed by terraform plan command.

2. The terraform plan command is used to create an execution plan. Terraform performs a refresh and then determines what actions are necessary to achieve the desired state specified in the configuration files.

What this means is Terraform talks to the provider and gets the current state of resources in your account and creates a plan to achieve the desired state.

Declarative paradigm based on state

To understand this better you can consider your starting state where there are no resources as state A and the desired state is state B where your resource has been created.

Terraform then formulates a plan to reach from state A to state B. This is called an execution plan. Since it uses a declarative paradigm you don’t have to tell Terraform how to do that.

An execution plan for the above snippet looks like this

An execution plan has been generated and is shown below.

Resource actions are indicated with the following symbols:

+ create Terraform will perform the following actions: # aws_instance.backend will be created

+ resource "aws_instance" "backend" {

+ ami = "ami-0947d2ba12ee1ff75"

+ arn = (known after apply)

+ associate_public_ip_address = (known after apply)

+ availability_zone = (known after apply)

+ cpu_core_count = (known after apply)

+ cpu_threads_per_core = (known after apply)

+ get_password_data = false

+ host_id = (known after apply)

+ id = (known after apply)

+ instance_state = (known after apply)

+ instance_type = "t2.micro"

+ ipv6_address_count = (known after apply)

+ ipv6_addresses = (known after apply)

+ key_name = (known after apply)

+ outpost_arn = (known after apply)

+ password_data = (known after apply)

+ placement_group = (known after apply)

+ primary_network_interface_id = (known after apply)

+ private_dns = (known after apply)

+ private_ip = (known after apply)

+ public_dns = (known after apply)

+ public_ip = (known after apply)

+ secondary_private_ips = (known after apply)

+ security_groups = (known after apply)

+ source_dest_check = true

+ subnet_id = (known after apply)

+ tags = {

+ "Name" = "terraform-server"

}

+ tenancy = (known after apply)

+ volume_tags = (known after apply)

+ vpc_security_group_ids = (known after apply) + ebs_block_device {

+ delete_on_termination = (known after apply)

+ device_name = (known after apply)

+ encrypted = (known after apply)

+ iops = (known after apply)

+ kms_key_id = (known after apply)

+ snapshot_id = (known after apply)

+ volume_id = (known after apply)

+ volume_size = (known after apply)

+ volume_type = (known after apply)

} + ephemeral_block_device {

+ device_name = (known after apply)

+ no_device = (known after apply)

+ virtual_name = (known after apply)

} + metadata_options {

+ http_endpoint = (known after apply)

+ http_put_response_hop_limit = (known after apply)

+ http_tokens = (known after apply)

} + network_interface {

+ delete_on_termination = (known after apply)

+ device_index = (known after apply)

+ network_interface_id = (known after apply)

} + root_block_device {

+ delete_on_termination = (known after apply)

+ device_name = (known after apply)

+ encrypted = (known after apply)

+ iops = (known after apply)

+ kms_key_id = (known after apply)

+ volume_id = (known after apply)

+ volume_size = (known after apply)

+ volume_type = (known after apply)

}

} Plan: 1 to add, 0 to change, 0 to destroy. --------------------------------------------------------------------

You can notice the plan summary as “1 resource to add”. Also, you can see the plan includes all the specs that we mentioned.

But how was the plan calculated? What is the initial state? Where is it maintained? How does Terraform use it? Let’s find that out