Terraform Cert Guide Chapter 5: Every Terraform CLI Command You Need to Know
Chapter 5 is where the book gets hands-on with the Terraform CLI. Up to this point you’ve been learning concepts. Now it’s time to learn what you actually type into the terminal.
The chapter covers two big things: authenticating Terraform to the three major clouds (Azure, AWS, GCP) and then a breakdown of the most important CLI commands. Let me walk through both.
Connecting Terraform to Cloud Providers
Before Terraform can create anything, it needs to talk to your cloud account. The book walks through authentication for Azure, AWS, and GCP. The pattern is the same everywhere: create some credentials, store them as environment variables, then point your provider block at the right source.
Azure
For Azure, you create a Service Principal (basically an app registration in Azure Active Directory). You get four values: client ID, tenant ID, subscription ID, and a client secret. Then you set them as environment variables:
$env:ARM_CLIENT_ID="..."
$env:ARM_CLIENT_SECRET="..."
$env:ARM_SUBSCRIPTION_ID="..."
$env:ARM_TENANT_ID="..."
Your provider block looks like this:
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "=2.55.0"
}
}
}
provider "azurerm" {
features {}
}
Run terraform init and it downloads the Azure provider plugin into a .terraform folder. That’s it. You’re connected.
AWS
Same idea but simpler. Create an access key in the AWS console, then export the values:
export AWS_ACCESS_KEY_ID="your-key-id"
export AWS_SECRET_ACCESS_KEY="your-secret-key"
Provider block:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.0"
}
}
}
provider "aws" {
region = var.aws_region
}
Quick note from the book: use an IAM user account, not your root account. Root access is way too powerful for day-to-day Terraform work.
GCP
For Google Cloud, you create a service account, give it an Editor role, and download the credentials as a JSON file. Then reference that file in your provider:
provider "google" {
credentials = file("terraform-project-xxxx.json")
project = "Terraform-project"
region = "asia-south1"
}
Keep that JSON file safe. It has full access to your GCP project.
The CLI Commands That Actually Matter
Now for the good part. Here’s every Terraform CLI command the book covers, with what you need to know about each one.
terraform init
This is always your first command. It downloads provider plugins, sets up the backend, and prepares your working directory. You can’t do anything else until you run this.
terraform plan
Shows you what Terraform is about to do without actually doing it. Think of it as a dry run. Green means create, yellow means modify, red means destroy. Always run this before apply.
terraform apply
This is the one that actually creates or updates your infrastructure. It runs a plan first, shows you what it’ll do, and asks for confirmation. Type yes and it goes to work.
terraform destroy
Tears down everything that Terraform manages. Same deal as apply: it shows you what it’s going to delete and asks for confirmation. Use this carefully.
terraform console
Opens an interactive shell where you can test Terraform expressions and functions. Super useful when you’re trying to figure out if your function call is doing what you think:
$ terraform console
> max(5, 10, -5)
10
terraform fmt
Reformats your .tf and .tfvars files to follow Terraform’s style conventions. Think of it like a code linter for Terraform. It cleans up spacing, alignment, and indentation.
Some useful flags:
-checkreturns a non-zero exit code if files aren’t formatted (great for CI/CD pipelines)-diffshows you what changed-recursiveprocesses subdirectories too
terraform validate
Checks your configuration for syntax errors. Here’s the thing though: you don’t usually need to run this manually. Both terraform plan and terraform apply run validation automatically before doing anything else.
Still, it’s handy if you just want a quick syntax check without running a full plan.
terraform graph
Generates a visual dependency graph of your resources in DOT format. You can pipe it into Graphviz to get an actual image:
terraform graph | dot -Tpng > graph.png
This is really helpful when you have a complex setup and want to see how resources depend on each other. The graph shows implicit dependencies that Terraform figures out automatically.
terraform output
Prints the output values from your root module. If you defined an output block in your config (like a VM’s IP address), this command shows you the value.
terraform refresh
Compares your state file with the actual infrastructure and updates the state to match reality. It doesn’t change your infrastructure at all. It just updates what Terraform thinks exists.
This is useful for detecting drift. If someone went into the console and manually changed something, terraform refresh updates the state file so Terraform knows about it. Next time you run plan, you’ll see the differences.
terraform show
Prints the contents of your state file in a human-readable format. Good for quickly checking what Terraform currently manages without opening the raw state file.
terraform taint
Marks a specific resource for destruction and recreation on the next apply. The resource isn’t touched immediately. Terraform just flags it in the state file.
terraform taint aws_security_group.rdp_allow
Next time you run terraform apply, that security group gets destroyed and rebuilt from scratch. This is useful when a resource is in a broken state and you need a clean recreation.
terraform import
Brings an existing resource (one that was created outside of Terraform) into your state file. You need the resource’s ID from your cloud provider:
terraform import aws_instance.abc i-acdf10234
This is a big one for teams migrating to Terraform. You don’t have to destroy and recreate everything. You can import what already exists and start managing it with Terraform going forward.
terraform workspace
Lets you manage multiple environments (dev, staging, production) with the same configuration. Each workspace gets its own state file and plugin setup.
Instead of copying your entire Terraform project three times, you create three workspaces and switch between them. The config stays the same, but each workspace tracks its own resources independently.
terraform force-unlock
If your remote state file gets locked (someone ran a plan and it crashed, or a CI job died mid-run), this command lets you manually unlock it:
terraform force-unlock f20d9093-5116-53c5-4037-ab2e8cb8f77d
You need the lock ID, which Terraform shows you when it tells you the state is locked. This only applies to remote backends. Local state files don’t have this problem.
My Take on This Chapter
Chapter 5 is basically a reference chapter. It’s not the most exciting read, but it’s the kind of stuff you’ll come back to constantly when you’re actually working with Terraform.
The cloud authentication sections are useful but pretty straightforward. The real value is in the CLI command breakdown. For the certification exam, make sure you know what each command does, especially the tricky ones like taint, import, and force-unlock. Those come up in exam questions.
One thing I’d add: the book mentions that terraform validate runs automatically during plan and apply. That’s a good detail to remember for the exam. People often overthink when to use validate separately.
The terraform workspace command is also worth extra study. It’s a clean way to manage multiple environments, but it has limitations that the book covers more in later chapters.
Previous: Chapter 4 Part 2: Loops, Functions, and Debugging
Next: Chapter 6: Terraform Workflows
This is part of a series retelling “HashiCorp Infrastructure Automation Certification Guide” by Ravi Mishra (Packt, 2021). For the full text, grab the book - ISBN: 978-1-80056-597-5.