Terraform Cheatsheet
Related Posts / Resources
- Terraform Commands
- GitHub - Terraform Examples - Some example Terraform scripts to allow you to quickly get started with various scenarios.
- Use S3 To Store Terraform State
- Use PostgreSQL To Store Terraform State
Table Of Contents
- Installation
- Files
- Commands
- AWS Authentication
- Basic Example
- Variables
- Outputs
- String Substitution
- Functions
- Locals
- Misc
Installation
PPA Install
The following chained commands will install the Hashicorp GPG key, add their PPA, and use that to install Terraform.
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add - \
&& sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main" \
&& sudo apt-get update && sudo apt-get install terraform -y
Snap Install
You can install the the terraform CLI tool con Ubuntu 20.04 by running:
sudo snap install terraform
... however, this will install Terraform v0.11.11 which will not work with some of the examples I provide, which need 0.12+.
Files
File Extension
Terraform files should have the .tf
extension
Gitignore
Terraform will create the following files/folders that you may wish to add to your .gitignore
file.
.terraform
.tfstate
.tfstate.backup
Commands
Please refer here instead.
AWS Authentication
To use terraform with AWS, you will need to provide it with your access key and secret. You can do this by running:
export AWS_ACCESS_KEY_ID=yourKeyId
export AWS_SECRET_ACCESS_KEY=yourKeySecret
Basic Example
The following terraform file will deploy a basic webserver (in London) that runs on port 8080 and will just respond with "Hello World". To "run" it, execute terraform apply
.
provider "aws" {
region = "eu-west-2"
}
# Create security group to allow port 8080
resource "aws_security_group" "instance" {
name = "terraform-example-instance"
ingress {
from_port = 8080
to_port = 8080
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
# Create the ubuntu 20.04 EC2 webserver resource
# that uses the above security group
resource "aws_instance" "example" {
ami = "ami-05c424d59413a2876"
instance_type = "t2.micro"
vpc_security_group_ids = [aws_security_group.instance.id]
user_data = <<-EOF
#!/bin/bash
/usr/bin/sleep 10
/usr/bin/echo "Hello, World" > index.html
/usr/bin/nohup /usr/bin/busybox httpd -f -p 8080 &
EOF
tags = {
Name = "terraform-example"
}
}
After executing that successfully, log into your amazon web console, find the instance to find its IP address and go to that in your browser with :8080
on the end.
You should see "Hello World" in your browser. If it doesn't appear, just wait a bit. It takes quite a while before its ready, especially after I had to put in a sleep to make the script work.
Variables
Variables can be defined like so:
variable "aws_region" {
type = string
description = "The region to deploy to. E.g. eu-west-2 for London."
default = "eu-west-2"
}
default
or description
. They just help when it comes to someone specifying the values.
Types
- string
- number
- bool
- list - 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. - tuple (alias of list)
- map - a group of values identified by named labels. E.g.
{name = "Mabel", age = 52}
- object - alias of map
Set Values In File
To automatically provide the values for the variables, it is good to create a file with the .tfvars
extension, with values for the variables. E.g.
aws_region="eu-west-2"
.tfvars
files to your .gitignore
files.
Multi-line Variable
If you need to provide a multi-line string for a variable, when using a .tfvars
file, one can just make use of heredoc strings like so:
example = <<-EOT
-----BEGIN PUBLIC KEY-----
line1
line2
line3
-----END PUBLIC KEY-----
EOT
If not using a .tfvars
file, then refer to this StackOverflow post.
Outputs
After you create resources using Terraform, you will likely need to know their names/identifiers to then start using them. E.g. you need to know the IP address of the EC2 server you just deployed. You do this by declaring an output block. E.g.
output "my_ec2_ip" {
value = aws_eip.my_elastic_ip.public_ip
}
This will cause them to be printed out out at the end of performing a terraform apply
operation.
Show Outputs
You can run the command:
terraform output
... which will just print out the outputs.
You can also use the command:
terraform show
... which will print out more, with the outputs at the very end.
Sensitive Outputs
You can mark some outputs as sensitive so that they will be hidden from the output.
Some attributes, like AWS IAM credentials have to be marked as sensitive in order to have them as an output, otherwise terraform apply
won't even run.
Retrieval
You may notice that the sensitive outputs are hidden (showing myOutputName = <sensitive>
) when you run the commands to show outputs.
In order to be able to retrieve these sensitive values, you can just add the -json
flag like so:
terraform output -json
or
terraform show -json
That will output a massive JSON from which you would have to find your sensitive values.
If you just want a specific output you can just specify it, and it will not be hidden.
terraform output mySensitiveOutputName
If using terraform show
you can save yourself a lot of effort trying to find the needle with the help of jq
like so:
terraform show -json | jq '.values.outputs.name_of_my_output'
E.g. if the name of your output was my_super_secret_thing, then you would need:
terraform show -json | jq '.values.outputs.my_super_secret_thing'
... or if you just want to see all of the outputs, you can use:
terraform show -json | jq '.values.outputs'
String Substitution
This is best demonstrated with an example. Below, I am creating the value by using both a dynamic resource ID, and an input variable, with fixed/known string content
output "ecr_registry" {
value = "${aws_ecr_repository.compute_engine_ecr.registry_id}.dkr.ecr.${var.aws_region}.amazonaws.com"
}
Functions
The Terraform language doesn't support user-defined functions, but has a number of built-in functions that can be used in expressions to transform and combine values.
For example, the merge
command is very commonly useful:
tags = merge({Name = "NameForMyThing"}, local.common_tags)
To see the full list of functions, refer to the docs functions page, and look to the pane on the left for the various types.
Locals
Refer to: Terraform Locals: What Are They, How to Use Them [Examples]
Misc
Language
The "language" is called HCL (Hashicorp Configuration language).
Packer
Packer is HashiCorp's (the makers of Terraform) open-source tool for creating machine images from source configuration. You can configure Packer images with an operating system and software for your specific use-case.
References
- Terraform Docs - Types and Values
- Terraform Up & Running (Alternative Amazon link)
- Terraform Docs - Install Terraform
- Hashicorp Forum - Error: Error parsing : unexpected token while parsing list: IDENT
- Terraform - Command: taint
- learn.hashicorp.com - Output Data from Terraform
- Stack Overflow - Terraform not accepting AWS credentials from vars/tfvars files
- Stack Overflow - Is there a way where terraform ignores ResourceNotFoundException and destroys the other resources
- Terraform Docs - Use refresh-only mode to sync Terraform state
First published: 24th September 2020