Terraform 101
Tags: iac, webdev, beginners, tutorial
Published: 2022-12-06 14:47:20

Infrastructure as code makes our lives easy by allowing us to deploy our servers by describing the configurations for our infrastructure as code.

When you're setting up your servers you go through a 3-step process i.e

1. Provision your servers: You create your EC2 instances, S3 buckets etc... 

2. Configure your servers: You install docker or some other software that will help you during the application setup.

3. Application setup: You setup your app in production or test mode.


All the above steps are time consuming processes hence we can automate each of the above step by:


![Types-of-iac-tools](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m88apxuwpmovuy940w01.png)



- Provisioning our infrastructure using tools like terraform or cloud formation.
- Managing Configurations using ansible or puppet
- Finally containerizing your application to make sure it runs the same everywhere with docker or vagrant

In this post we'll learn about basics of provisioning tool called terraform.

Terraform is an infrastructure provisioning tool similar to AWS's cloud formation or the serverless framework which allow you to manage resources via code.

# Install Terraform

You can setup terraform by downloading a binary file and adding it to your system PATH from [here](https://developer.hashicorp.com/terraform/downloads).


## Basic Concepts


Terraform has its own language called `HCL` (Hashicorp configuration language) through which you have describe your infrastructure.

you define all your configs in files that have a `.tf` extension.

Terraform supports various cloud providers like AWS, GCP and much more in order to manage infrastructure on these platforms terraform has plugins.

plugins are of 3-types:

- `Official` - These are plugins created and maintained by Hashicorp eg: AWS, Azure, GCP and etc....
- `Verified` - These are plugins created and maintained by Hashicorp's partners like Linode, Digital Ocean and etc....
- `Community` - These are plugins built and maintained by the community.

you can learn more about plugins from [here](https://registry.terraform.io/)

### Basic commands

Once you define your config you can create your resources using 3 basic commands in a sequence:

1. `terraform init`: This command looks at your config and downloads all the plugins that's required to create and manage your resources.

2. `terraform plan`: Before actually creating your resources, you can review the changes that will be made to your infrastructure using this command.

3. `terraform apply`: finally running the apply command will create your resources 


# Creating your first resource with terraform

The first resource we'll be creating will be a file.

So, first create a file with a `.tf` extension and add the code down below.

![terraform local file](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ey5wbwgxtqq9vx82qtwg.png)

In terraform everything is defined as a block and the above image we are using something called a `resource` block the resource block takes 2 arguments first is the `resource type` and second is a logical name for your resource.

In the resource type argument the keyword `before the _` indicates the provider we are using in this case it's an official provider from hashicorp called local and the keyword `after the _` indicates the resource provided by the provider.

another example can be `aws_s3_bucket` where `aws` is the provider and `s3_bucket` symbolizes the S3 feature provided by aws.

Each block expects you to enter a few key value pairs to function,
Here the resource block's key value pair will change depending on the provider and resources being used.

In the above image the `local_file` provider expects us to pass the `filename` key which will create a file in the provided path and the content key specifies what content will be added to the newly created file.

 
No if you run terraform `init`, `plan`, `apply` you'll see a new file created with the name `pet.txt` with the content `hello pets`


# Using variables 

Terraform allows us to define variables and use them in our config file.

you can learn about the variable types supported by terraform [here](https://developer.hashicorp.com/terraform/language/values/variables)

you can create a variable by starting the block with the `variable` keyword,

Each keyword block expects you to enter a default value and if required you can enter a variable type.

if you do not enter a default value terraform will require you to enter a default value when you run the apply command.

you can also set a default value by passing the value while running the apply command using the `-var` flag or you can initialize your variables using a `.tfvar` file.

You can also export the value for variables as an environment variable.

![simple terraform variable](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7gdhqoe2q9xshsg81e98.png)

you can use the variable in your config like this `var.test` 

here's a more complex variable for your reference

![complex terraform variable](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g9gfqv5tpmzrl2prdhvd.png)

let's access the name of the dog and print it in the console.

You can print values from terraform using the `output` block and the output block expects you to provide it a value to print.

![output terraform](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jv75c96qby1tdh454qc9.png)

now when you run the `terraform apply` command you will see the output in your console.

![terraform console](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7sttewsy7il0g017g11u.png)

# Resource Dependency 

There are times where we might want to supply the output of one resource as an input to another resource or we might want a resource B to be created after the creation of resource A we can achieve this with resource dependency.

There are 2 types `implicit` and `explicit`

## Implicit Resource Dependency 

We can use the output of one resource to be the input of another by referencing the resource using the `resource type` followed by the resource's `logical name` and one of the property that's being returned by the resource.

here in our case, we are using the random provider and resource pet that returns and id.

![Implicit Resource Dependency ](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/etoj3bkn7bjqw8t8xurb.png)

Now run apply the changes and see what happens.


## Explicit Resource Dependency 

using references will make your resource implicitly dependent but if you want to explicitly make a resource dependent, we can use the `depends_on` key in the `resource` block like in the image below

![Explicit Resource Dependency](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mpl0nlnhu043rder3wrm.png)

Now if you have a look at the console the resource `time` is created first following the `petz` resource.

![res](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3lbxvlhmsy2oui8ckhao.png)

## Terraform Lifecycle

Generally, in terraform most of the time when you make a change the resource block the resource is completely destroyed and recreated.

For example, say that you change the name of the file the file will first be deleted then a new copy will be created but there are times where you might want the old file to be deleted only when the new one is up and running you can achieve that using the lifecycle block.

there are 3 types `create_before_destroy`, `prevent_destroy` and `ignore_changes`


`create_before_destroy`: when set to true will first create the new resource and then delete the old one.

```
resource "azurerm_resource_group" "example" {
  # ...

  lifecycle {
    create_before_destroy = true
  }
}
```

`prevent_destroy`: when set to true will cause Terraform to reject with an error any plan that would destroy the infrastructure.

`ignore_changes`: Accepts a list of attributes it should ignore when changed.

```
resource "aws_instance" "example" {
  lifecycle {
    ignore_changes = [
      tags,
    ]
  }
}
```

These are the basic concepts of terraform which will help you provision and manage your resources.

If you are looking for resources on how to use terraform with cloud providers stay tuned will soon publish how to setup your linode and digital ocean instances using terraform.

Also checkout [Getting Started With Terraform on AWS](https://spacelift.io/blog/terraform-tutorial).


Thanks for the read.