Terraform Cheatsheet

Shandre Dreyer
7 min readSep 30, 2021

--

Use Infrastructure as Code to provision and manage any cloud, infrastructure, or service.

Terraform is a tool for building, changing, and versioning infrastructure safely and efficiently. Terraform can manage existing and popular service providers as well as custom in-house solutions.

Configuration files describe to Terraform the components needed to run a single application or your entire datacenter. Terraform generates an execution plan describing what it will do to reach the desired state, and then executes it to build the described infrastructure. As the configuration changes, Terraform is able to determine what changed and create incremental execution plans which can be applied.

The infrastructure Terraform can manage includes low-level components such as compute instances, storage, and networking, as well as high-level components such as DNS entries, SaaS features, etc.

Note: All our AWS resources are defined and deployed with the help of Terraform.

Link: https://www.terraform.io/docs/providers/aws/index.html

Table Of Content

Visual Studio Plugin

It’s recommended to install the terraform plugin.

Link: https://marketplace.visualstudio.com/items?itemName=hashicorp.terraform

Terraform version

Download link: https://releases.hashicorp.com/terraform/

Note: Make sure you are using the correct version on your local environment! This is very important. If you use the wrong version it can break the remote state compatibility with other components.

Adding version.tf file

Always add a version.tf file to your component and modules.

Component Example:

terraform {
required_version = "0.12.24"
}

Module Example:

terraform {
required_version = "~> 0.12"
}

To see a list of changes in v0.12 and later see the link below.

Link: https://www.terraform.io/docs/configuration/index.html

AWS Provider

The Amazon Web Services (AWS) provider is used to interact with the many resources supported by AWS. The provider needs to be configured with the proper credentials before it can be used.

Example:

provider "aws" {
region = "eu-west-1"
version = "~>2.63.0"
}

Link: https://www.terraform.io/docs/providers/aws/index.html

State

Terraform must store state about your managed infrastructure and configuration. This state is used by Terraform to map real world resources to your configuration, keep track of metadata, and to improve performance for large infrastructures.

This state is stored by default in a local file named “terraform.tfstate”, but it can also be stored remotely, which works better in a team environment.

Terraform uses this local state to create plans and make changes to your infrastructure. Prior to any operation, Terraform does a refresh to update the state with the real infrastructure.

Link: https://www.terraform.io/docs/state/index.html

Backends

A “backend” in Terraform determines how state is loaded and how an operation such as apply is executed. This abstraction enables non-local file state storage, remote execution, etc.

Example:

terraform {
backend "s3" {
bucket = "state-provisioning"
dynamodb_table = "state-provisioning"
key = "terraform/non-prod/s3-buckets"
region = "eu-west-1"
}
}

Link: https://www.terraform.io/docs/backends/index.html

Resources

Resources are the most important element in the Terraform language. Each resource block describes one or more infrastructure objects, such as virtual networks, compute instances, or higher-level components such as DNS records.

Example:

resource "aws_s3_bucket" "b" {
bucket = "my-tf-test-bucket"
acl = "private"

tags = {
Name = "My bucket"
Environment = "Dev"
}
}

Link: https://www.terraform.io/docs/configuration/resources.html

Modules

A module is a container for multiple resources that are used together. Modules can be used to create lightweight abstractions, so that you can describe your infrastructure in terms of its architecture, rather than directly in terms of physical objects.

Example:

module "iam_account" {
source = "terraform-aws-modules/iam/aws//modules/iam-account"
version = "~> 4.3"

account_alias = "awesome-company"

minimum_password_length = 37
require_numbers = false
}

Link: https://www.terraform.io/docs/modules/index.html

Output

Output values are like the return values of a Terraform module, and have several uses:

  • A child module can use outputs to expose a subset of its resource attributes to a parent module.
  • A root module can use outputs to print certain values in the CLI output after running terraform apply.
  • When using remote state, root module outputs can be accessed by other configurations via a terraform_remote_state data source.

Resource instances managed by Terraform each export attributes whose values can be used elsewhere in configuration. Output values are a way to expose some of that information to the user of your module.

Example:

output "lambda_function_arn" {
value = module.edge_lambda.lambda_function_arn
}

Link: https://www.terraform.io/docs/configuration/outputs.html

Input Variables

Input variables serve as parameters for a Terraform module, allowing aspects of the module to be customized without altering the module’s own source code, and allowing modules to be shared between different configurations.

When you declare variables in the root module of your configuration, you can set their values using CLI options and environment variables. When you declare them in child modules, the calling module should pass values in the module block.

Example:

variable "availability_zone_names" {
type = list(string)
default = ["us-west-1a"]
}

Link: https://www.terraform.io/docs/configuration/data-sources.html

Data

Data sources allow data to be fetched or computed for use elsewhere in Terraform configuration. Use of data sources allows a Terraform configuration to make use of information defined outside of Terraform, or defined by another separate Terraform configuration.

Example:

data "terraform_remote_state" "edge_lambda" {
backend = "s3"
config = {
bucket = "state-cloud-provisioning"
key = "terraform/non-prod/origin-request-edge-lambda"
region = "eu-west-1"
}
}

Link: https://www.terraform.io/docs/configuration/data-sources.html

Expression

Expressions are used to 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.

Types and values

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. The number type can represent both whole numbers like 15 and fractional values like 6.283185.
  • bool: either true or false. bool values can be used in conditional logic.
  • list (or tuple): 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 (or object): 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 or module to null, 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.

Link: https://www.terraform.io/docs/configuration/expressions.html

Locals

A local value assigns a name to an expression, allowing it to be used multiple times within a module without repeating it.

Comparing modules to functions in a traditional programming language: if input variables are analogous to function arguments and outputs values are analogous to function return values, then local values are comparable to a function’s local temporary symbols.

Example:

locals {
service_name = "forum"
owner = "Community Team"
}

Link: https://www.terraform.io/docs/configuration/locals.html

Import

Terraform is able to import existing infrastructure. This allows you take resources you’ve created by some other means and bring it under Terraform management.

This is a great way to slowly transition infrastructure to Terraform, or to be able to be confident that you can use Terraform in the future if it potentially doesn’t support every feature you need today.

To see the import format for a resource go to that resource terraform AWS page. It will be at the bottom of the page.

Example:

Link to example: https://www.terraform.io/docs/providers/aws/r/s3_bucket.html

Link: https://www.terraform.io/docs/import/index.html

Useful Terraform commands

Run it from the component directory

command: aws-profile terraform init (After adding a backend.tf file do this first)

description: initialize working directory containing Terraform configuration files.

command: aws-profile terraform plan -out=“tf.plan”

description: Will display the changes between your local state and the current state

command: aws-profile terraform plan -out=”tf.plan” -var-file=”../terraform.tfvars”

description: Will display the changes between your local state and the current state and you specifying the variable configuration file location.

command: aws-profile terraform apply “tf.plan”

description: Will execute/apply the changes

command: aws-profile terraform show -json

description: Will show the state in json format

command: terraform state rm ‘module.foo’

description: Remove module resource from state

command: aws-profile terraform import (will find at the bottom of the resource page in Terraform)

description: Terraform is able to import existing infrastructure.

  • Import the AWS resource for our case
  • Importing something like an API Gateway stage requires the configuration to exist in the module before importing.

Example:

command: terraform plan -destroy -out=”tf.plan”

description: This will generate a plan of destroying the component with all its resources inside of it. If you are satisfied with the output you will need to run terraform apply “tf.plan“ to start destroying your component. Afterwards you can delete the component from your repo.

command: terraform destroy -target=’module.foo’

description: To destroy a specific module

command: terraform fmt <COMPONENT>

description: format your component.

command: aws-profile terraform force-unlock <LOCK_ID>

description: Remove a lock.

# Terraform log settings (Windows)
$env:TF_LOG="DEBUG"
$env:TF_LOG_PATH="terraform.txt"

Help to debug terraform. Run this inside your component before you run another terraform command.

Debugging

See https://www.terraform.io/docs/internals/debugging.html

windows

Add the following system environment variable

Note: The environment variable will only be picked up if you restart your VS code or open a new terminal.

Linux

Run the following command:

export TF_LOG=DEBUG

Past Presentation

See the attached presentation for more information regarding Terraform.

--

--