# Terraform CLI Tips and Cheatsheets

This article will discuss some very useful Terraform CLI tips and cheatsheets. When you want to use a tool or improve your expertise in a particular technology, it’s good to read many articles and official documentation. However, sometimes having a brief cheat sheet of it, can be very handy.

## **Terraform**

Terraform, a Go-based program released by [Hashicorp](https://www.hashicorp.com/) in 2014, is used to build, change, and version control your infrastructure(IaC). This has an extremely strong and user-friendly Command Line Interface.

## **Prerequisites**

* Basics of [Terraform](https://scanskill.com/lesson/terraform/) – IaC (Terraform CLI)
    
* Command Line basics
    

## **Terraform CLI Tips and Cheatsheets**

### **Installation**

#### **Install through curl**

```bash
$ curl -O <https://releases.hashicorp.com/terraform/1.9.7/terraform_1.9.7_linux_amd64.zip>
$ sudo unzip terraform_1.9.7_linux_amd64.zip -d /usr/local/bin/
$ rm terraform_1.9.7_linux_amd64.zip
```

#### **Install using tfenv (Terraform Version Manager)**

First of all, download the tfenv binary and put it in your PATH.

```bash
$ git clone <https://github.com/tfutils/tfenv.git> ~/.tfenv
$ echo 'export PATH="$HOME/.tfenv/bin:$PATH"' >> $HOME/bashrc
```

Then, you can install the desired version of Terraform:

```bash
$ tfenv install 1.9.7
```

### **Usage**

#### **Version Check**

```bash
$ terraform --version

Terraform v1.9.7
on linux_amd64
```

#### **Terraform init**

The following command is used to initialize the terraform project:

```bash
$ terraform init
```

It’s the first command you need to execute. Unless `terraform plan`, `apply`, `destroy` and `import` will not work. This command `terraform init`  will install the followings:

* Terraform modules
    
* Backend
    
* Provider(s) plugins
    

You can initialize the Terraform without any input prompt. To do this, run the following command:

```bash
$ terraform init -input=false
```

Also, if you want to change the backend configuration during the init command, run the following command:

```bash
$ terraform init -backend-config=proj/s3.dev.tf -reconfigure
```

Here, `reconfigure` is used to tell Terraform to not copy the existing state to the new remote state location.

#### **Terraform Get**

This command is very useful when you have defined some modules. And if you edit modules, you need to get modules content again.

```bash
$ terraform get -update=true
```

When using modules, the first thing you’ll need to do is a `terraform get`. This appends modules to the .terraform directory. Unless you do another `terraform get -update=true`, you’ve effectively vendored those components.

#### **Terraform Plan**

The **plan** step validates the configuration for execution and creates a plan to be applied to the target infrastructure provider.

```bash
$ terraform plan -out plan.out
```

It’s a crucial Terraform tool that lets users know the actions Terraform will do before making any changes, providing confidence that a modification will have the desired effect once deployed.

When you execute `terraform plan`, Terraform will scan all \****.tf*** files in your directory and create the plan.

#### **Terraform Apply**

Now it’s time to execute the plan:

```bash
$ terraform apply plan.out
```

Terraform can guarantee that the execution plan will not change by generating it and applying it in the same command without the need to write it to disk. This decreases the possibility of potentially sensitive data being left behind or being incorrectly checked into version control.

```bash
$ terraform apply
```

* **Apply and Auto Approve**
    

```bash
$ terraform apply -auto-approve
```

* **Apply and Define New Variables Value**
    

```bash
$ terraform apply -auto-approve -var tags-repository_url=${GIT_URL}
```

* **Apply Only One Module**
    

```bash
$ terraform apply -target=module.s3
```

This `-target` option works with *terraform plan* too.

#### **Terraform Destroy**

```bash
$ terraform destroy
```

Delete all the resources!

A deletion plan can be created before:

```bash
$ terraform plan –destroy
```

* `target` option allows to destroy only one resource, for example, an S3 bucket :
    

```bash
$ terraform destroy -target aws_s3_bucket.my_bucket
```

#### **Debugging in Terraform**

In Terraform `terraform console` command is useful for testing interpolations before using them in configurations. Terraform console will read the configured state even if it is remote.

```bash
$ echo "aws_iam_user.sagar.arn" | terraform console
```

```bash
arn:aws:iam::123456789:user/sagar
```

#### **Graph in Terraform**

```bash
$ terraform graph | dot –Tpng > graph.png
```

Visual representation (graph) of Terraform resources.

#### **Terraform Validate**

The validate command is used to validate/check the syntax of the Terraform files. A syntax check is done on all the Terraform files in the directory and will display an error if any of the files don’t validate. The syntax check does not cover every syntax common issue.

```bash
$ terraform validate
```

#### **Providers**

You can use a lot of providers/plugins in your Terraform definition resources, so it can be useful to have a tree of providers used by modules in your project.

```bash
$ terraform providers
.
├── provider.aws ~> 4.49.0
├── module.my_module
│   ├── provider.aws (inherited)
│   ├── provider.null
│   └── provider.template
└── module.elastic
└── provider.aws (inherited)
```

### **State**

#### **Pull Remote State in A Local Copy**

```bash
$ terraform state pull > terraform.tfstate
```

#### **Push State in a Remote Backend storage**

```bash
$ terraform state push
```

This command is useful if, for example, you originally use a local tf state and then you define backend storage, in S3 or Consul…

#### **How to Tell to Terraform You Moved a Resource in A Module?**

If you moved an existing resource in a module, you need to update the state:

```bash
$ terraform state mv aws_iam_role.role1 module.mymodule
```

#### **How to Import Existing Resources in Terraform?**

If you have an existing resource in your infrastructure provider, you can import it in your Terraform state:

```bash
$ terraform import aws_iam_policy.elastic_post
```

```bash
arn:aws:iam::123456789:policy/elastic_post
```

### **Workspaces**

To manage multiple distinct sets of infrastructure resources/environments.

Instead of creating a directory for each environment to manage, we need to just create needed workspace and use them:

#### **Create Workspace**

This command creates a new workspace and then select it

```bash
$ terraform workspace new dev
```

#### **Select a Workspace**

```bash
$ terraform workspace select dev
```

#### **List Workspaces**

```bash
$ terraform workspace list

default
* dev
staging
```

#### **Show Current Workspace**

```bash
$ terraform workspace show

dev
```

### **Tools**

#### **1\. jq**

***jq*** is a command-line JSON processor. It’s very lightweight and it can be used with Terraform output to make Terraform more powerful.

##### **Installation**

**For Linux:**

```bash
$ sudo apt-get install jq
```

or

```bash
$ yum install jq
```

**For OS X:**

```bash
$ brew install jq
```

##### **Usage**

For example, we defined outputs in a module and when we execute *terraform apply* outputs are displayed:

```bash
$ terraform apply

...
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:
elastic_endpoint = vpc-toto-12fgfd4d5f4ds5fngetwe4.ap-south-1.es.amazonaws.com
```

We can extract the value that we want to use in a script for example. With ***jq*** it’s easy:

```bash
$ terraform output -json

{
    "elastic_endpoint": {
        "sensitive": false,
        "type": "string",
        "value": "vpc-toto-12fgfd4d5f4ds5fngetwe4.ap-south-1.es.amazonaws.com"
    }
}
```

```bash
$ terraform output -json | jq '.elastic_endpoint.value'

"vpc-toto-12fgfd4d5f4ds5fngetwe4.ap-south-1.es.amazonaws.com"
```

#### **2\. Terraforming**

If you have an existing AWS account for example with existing components like S3 buckets, SNS, VPC … You can use the Terraforming tool, a tool written in Ruby, which extracts existing AWS resources and converts them to Terraform files!

##### **Installation**

```bash
$ sudo apt install ruby 
# OR 
$ sudo yum install ruby
```

and

```bash
$ gem install terraforming
```

##### **Usage**

###### **Pre-requisites:**

As in Terraform, you need to set AWS credentials:

```bash
$ export AWS_ACCESS_KEY_ID="an_aws_access_key"
$ export AWS_SECRET_ACCESS_KEY="a_aws_secret_key"
$ export AWS_DEFAULT_REGION="eu-central-1"
```

You can also specify the credential profile in *~/.aws/credentials and with –profile* option.

```bash
$ cat ~/.aws/credentials

[sagar]
aws_access_key_id = xxx
aws_secret_access_key = xxx
aws_default_region = eu-central-1
```

```bash
$ terraforming s3 --profile sagar
```

###### **Example**

```bash
$ terraforming --help

Commands:
terraforming alb # ALB
...
terraforming vgw # VPN Gateway
terraforming vpc # VPC
```

```bash
$ terraforming s3 > aws_s3.tf
```

***Note:*** *Terraform can’t extract API gateway resources for the moment so you need to write it manually.*

## **Conclusion**

In this article, I talked about some of the important Terraform CLI tips and cheatsheets. There is still a lot more than this, but you can go and explore them yourself. Thank you!
