Terraform is an infrastrucure as code software tool. This is a list of tools, tips and tricks I use when working with Terraform.

1. tfenv

tfenv is a Terraform version manager. The tool makes it super easy to install and manage new versions of Terraform.

tfenv install 1.0.3

Use different version

tfenv use 0.15.3

List installed versions

➜  ~ tfenv list
* 1.0.3 (set by /usr/local/Cellar/tfenv/2.2.2/version)
  1.0.0
  0.15.3
  0.13.5

List available remote versions

$ tfenv list-remote
1.1.0-alpha20210811
1.1.0-alpha20210728
1.1.0-alpha20210714
1.1.0-alpha20210630
1.1.0-alpha20210616
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
0.15.5
0.15.4
0.15.3
0.15.2
...

2. terraform fmt

terraform fmt is a command used to format your code to follow the standard format and style of terraform. It helps with readability and ensures consistency in your configuration files. The command automatically adjusts your code and should be part of your routine when working with Terraform. I usually run this command as a last step before committing code to git.

➜  terraform fmt
main.tf
variables.tf

Adding the -recursive flag also processes files in subdirectories.

➜  terraform fmt -recursive
examples/qa/main.tf
examples/qa/variables.tf

3. terraform-docs

terraform-docs is a utility to generate documentation for Terraform modules. The tool is excellent for generating standarized README.md files for your modules.

➜  terraform-docs markdown .

The command will generate a markdown formatted output:

## Requirements

| Name | Version |
|------|---------|
| aws | ~> 2.20.0 |
| consul | >= 2.4.0 |

## Providers

| Name | Version |
|------|---------|
| aws | ~> 2.20.0 |
| consul | >= 2.4.0 |

## Modules

No Modules.

## Resources

No Resources.

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| instance\_name | Instance name. | `string` | `test` | no |


## Outputs

| Name | Description |
|------|-------------|
| vpc\_id | The id of the VPC |

The output documents required providers and versions to run the module. It also documents required inputs and what outputs are generated after provisioning.

4. TFLint

TFLint is a powerful Terraform linter that analyses Terraform code for programming errors, bugs, style errors, etc. It warns about deprecated syntax and enforces best practices. TFLint can be installed directly but is also published as a container image on GitHub Container Registry. You can run TFLint in a container by running the following command:

docker run --rm -v $(pwd):/data -t ghcr.io/terraform-linters/tflint

Since TFLint is containerized it can be easily integrated into CICD pipelines.

We have defined the following resource in a main.tf file.

resource "aws_instance" "web" {
  ami           = data.aws_ami.web.id
  instance_type = "t1.micro"
}

Running tflint on this code results in:

➜  docker run --rm -v $(pwd):/data -t ghcr.io/terraform-linters/tflint
1 issue(s) found:

Warning: "t1.micro" is previous generation instance type. (aws_instance_previous_type)

  on main.tf line 81:
  81:   instance_type = "t1.micro"

Reference: https://github.com/terraform-linters/tflint-ruleset-aws/blob/v0.6.0/docs/rules/aws_instance_previous_type.md

TFLint throws a warning we should look into.

5. VSCode Terraform Extension

VSCode provide a lot of useful extensions to aid development. HashiCorp publish an official extension for Terraform which adds syntax highlighting and other features.

vscodeterraform

The extension enables code completion functionality and combined with syntax highlighting will increase your productivity and raise code quality. Read more about the extention in this blogpost.

6. Terraform Cloud/Enterprise

HashiCorp provides an API to manage Terraform Cloud/Enterprise features. The API can be used in different operation tasks and automate continuous integration and development. HashiCorp also maintains a Go client for the API. All types and functions are declared in the documentation.

To work with Terraform Cloud/Enterprise endpoints we need to create a new TFE client.

config := &tfe.Config{
  Token: "insert-your-token-here",
  Address:  "insert-your-terraform-address-here",
}

client, err := tfe.NewClient(config)
if err != nil {
  log.Fatal(err)
}

List all organizations. This method requires an admin token. You can also use the API with team tokens or personal tokens with access to a subset of available methods.

orgs, err := client.Organizations.List(context.Background(), tfe.OrganizationListOptions{})
if err != nil {
  log.Fatal(err)
}

Get workspaces by name in organization.

workspace, err := client.Workspaces.Read(context.Background(), org, workspaceName)
if err != nil {
  log.Fatal(err)
}

With a workspace we are able to plan and apply runs, read state, etc.