Hashicorp Terraform Associate (003) Exam Guide
A complete study guide for Hashicorp Terraform Associate Certification Exam (003).
About Exam
- Terraform Associate certification is a specialty certification in Terraform conducted by Hashicorp.
- This exam is recommended for Cloud, DevOps, and SRE engineers.
- The Terraform Associate 003 exam detail is available here
- You have to answer 57 questions within 60 minutes from your laptop under the supervision of an online proctor.
- You need to get “around” 70% to pass the exam so you can afford to get 17 questions wrong.
- The exam costs you 70 USD and there is no free retake.
- The exam can be taken in English language only.
- You should expect different types of question formats such as Multiple Choice, Multiple Answers, True or false, and Text Match where you have to type the answer to fill in the blank.
- You get the exam result instantly and receive an email with the same result.
- This certification is valid for 2 years.
- This exam is targeted for Terraform version 1.0 and higher.
- Recommended studying for 1-2 hours a day for 2-4 weeks depending upon your daily commitment.
- You can register for the exam here
Exam Preparation
To be honest, their documentation is more than enough for this exam. They have a very good Exam study guide and exam review guide. I would suggest you go through these links in order and would highly recommend you practice while going through these materials.
Free study material:-
- HashiCorp Terraform Associate Certification Course - Pass the Exam!
- https://www.examtopics.com/exams/hashicorp/terraform-associate/view/
- https://www.itexams.com/exam/Terraform-Associate
- https://www.whizlabs.com/blog/terraform-certification-exam-questions/
- https://www.pass4success.com/hashicorp/discussions
Paid study materials:-
- HashiCorp Certified: Terraform Associate 2023 by Zeal Vora on Udemy
- HashiCorp Certified: Terraform Associate Practice Exam 2023 by Bryan Krausen on Udemy
Exam Questions
• Read 200+ Hashicorp Terraform Associate (003) Exam Questions for free
• Buy 200+ Hashicorp Terraform Associate (003) Exam Questions with Answers and Explainations at very reasonable price
Exam Notes
Infrastructure as Code
- Terraform is an Infrastructure as Code (IaC) tool that is Declarative and Cloud Agnostic
- Infrastructure lifecycle:-
- “Day 0” code provisions and configures your initial infrastructure.
- “Day 1” refers to OS and application configurations you apply after you’ve initially built your infrastructure.
- IaC enhances the Infrasture lifecycle:
- Reliability: IaC makes changes idempotent, consistent, repeatable, and predictable
- Manageability
- Sensibility
- Popular Infrastructure as Code (IaC) tools:
Tool Supports ARM Templates, Azure Blueprints only Microsoft Azure CloudFormation only Amazon AWS Cloud Deployment Manager only Google Cloud Platform GCP Terraform AWS, Azure, GCP, and on-prem - Terraform is written in HashiCorp Configuration Language (HCL). HCL is designed to strike a balance between human-readable and machine-parsable
Terraform Workflow
The core Terraform workflow consists of these stages:-
- Write: Define infrastructure in a configuration file e.g.
main.tf
- Initialize: Prepares the working directory so Terraform can run the configuration using
terraform init
command - Plan: Review the changes Terraform will make to your infrastructure using
terraform plan
command - Apply: Terraform provisions your infrastructure and updates the state file using
terraform apply
command
Terraform Provider
- Provider is a plugin that allows Terraform to interact with a specific cloud provider or service
- Provider provides abstraction above the upstream API and is responsible for understanding API interactions and exposing resources.
- Major cloud vendors and non-cloud vendors can write, maintain, or collaborate on Terraform providers
- At least one provider block is required in terraform configuration.
- Supports multiple provider instances using
alias
e.g. multiple aws provides with a different region
Input Variables
- The name of a variable can be any valid identifier except the following:- source, version, providers, count, for_each, lifecycle, depends_on, locals.
- The type of a variable can be string, number, bool, list, set, map, object, and tuple.
- The
nullable
argument in variable block can be set to false to not allow null values. default is true. - The
validation
argument in variable block can be used to apply custom validation on the value - The
sensitive
argument in variable block can be set to true to prevent from showing its value in theplan
andapply
output
variable "image_id" {
type = string
description = "The id of the machine image (AMI) to use for the server."
default = ami-abc123
nullable = false
sensitive = false
validation {
condition = length(var.image_id) > 4 && substr(var.image_id, 0, 4) == "ami-"
error_message = "The image_id value must be a valid AMI id, starting with \"ami-\"."
}
}
The loading of a variable goes from highest precedence (1) to lowest (5):-
- Command line flag - specify in command using
-var
e.g.terraform plan -var=environment="prod"
- Configuration file - set in your
terraform.tfvars
file - Environment variable - part of your shell environment e.g.
TF_VAR_environment=prod
- Default Config - default value in
variables.tf
- User manual entry - if not specified, prompt the user for entry
Terraform Backend
- A backend defines where Terraform stores its state data files. There are two backend types: local and remote.
- By default, Terraform uses a backend called local, which stores state as a local file on disk.
- Terraform v1.4.x supports the following backend types:- local, remote, azurerm, consul, cos, gcs, http, kubernetes, oss, pg, s3
- Terraform v1.2.x also supports following backend types:- artifactory, etcd, etcdv3, manta, swift
- Backend types support state locking:- local, remote, azurerm, consul, cos, gcs, http, kubernetes, oss, pg, s3, etcdv3, manta, swift
- Backend types doesn’t support state locking:- artifactory, etcd
- A terraform configuration
terraform
block can only have onebackend
block.terraform { backend "remote" { organization = "example_corp" workspaces { name = "my-app-prod" } } }
- Terraform Cloud automatically manages state in the workspaces. If your configuration includes a
cloud
block, it cannot include abackend
block.terraform { cloud { organization = "example_corp" ## Required for Terraform Enterprise; Defaults to app.terraform.io for Terraform Cloud hostname = "app.terraform.io" workspaces { tags = ["app"] } } }
- It is recommended to provide credentials and sensitive data using the credential file or environment variable supported by the remote backend type.
- You must run
terraform init
when you change backend configuration or backend type. Terraform auto-detects the changes and can migrate from existing state to new configuration.
Terraform Type Constraints
Category | Type | Example | Reference Value |
---|---|---|---|
Primitive | string | variable "image_id" { type=string default="ami-abc123"} |
var.image_id |
Primitive | number | variable "threads" { type=number default=10 } |
var.threads |
Primitive | bool | variable "set_password" { type=bool default=false } |
var.set_password |
Collection | list | variable "az_names" { type=list(string) default=["us-west-1a", "us-west-2a"]} |
var.az_names[0] |
Collection | set | variable "az_names" { type=set(string) default=["us-west-1a", "us-west-2a"]} |
var.az_names[0] |
Collection | map | variable "amis" { type="map" default={ "us-east-1"="ami-b374d5a5" "us-west-2"="ami-4b32be2b" }} |
var.amis["us-east-1"] |
Structural | object | variable "user_info" { type=object({ name=string address=string })} |
var.user_info.name |
Structural | tuple | variable "var1" { type=tuple([string, number, bool]) default=["a", 15, true] } |
var.var1[0] |
Source: https://developer.hashicorp.com/terraform/language/expressions/type-constraints
References to Named Values
Type | Expression | Example |
---|---|---|
Input Variable | var.<NAME> |
var.ami |
Local Values | local.<NAME> |
local.ami |
Resources | <RESOURCE TYPE>.<NAME>.<ATTRIBUTE> |
aws_instance.example.ami |
Data Sources | data.<DATA TYPE>.<NAME>.<ATTRIBUTE> |
data.aws_ami.ubuntu.id |
Child Module Outputs | module.<MODULE NAME>.<OUTPUT NAME> |
module.prod_subnet.subnet_id |
Source: https://developer.hashicorp.com/terraform/language/expressions/references
Environment Variables
Environment Variable | Example |
---|---|
TF_LOG | TF_LOG=trace|debug|info|warn|error to enable logs at different log level TF_LOG=off to disable logs TF_LOG=json to generate logs in JSON format |
TF_LOG_CORE | to enable/disable logging separately for terraform core, values same as TF_LOG |
TF_LOG_PROVIDER | to enable/disable logging separately for terraform providers, values same as TF_LOG |
TF_LOG_PATH | to specify where the log should persist its output to e.g. TF_LOG_PATH=./terraform.log , by default logs appear on stderr |
TF_VAR_name | to set the variables e.g. region variable TF_VAR_region=us-east1 |
Terraform Commands
Command ▼ | Description |
---|---|
terraform init |
1. First command to run. Safe to run it multiple times2. Initialize a working directory that contains terraform configuration files:- - create hidden .terraform directory - configure backend, download and install provider plugins into .terraform/providers - download modules into .terraform/modules - create dependency lock file .terraform.lock.hcl 3. Use terraform init -from-module=MODULE-SOURCE to check out the configuration from VCS and initialize the current working directory.4. Use terraform init -backend-config=PATH for partial backend configuration, in situations where the backend settings are dynamic or sensitive and so cannot be statically specified in the configuration file. |
terraform get |
Use to download and update modules mentioned into a .terraform subdirectory of the current working directory. |
terraform plan |
1. Creates an execution plan, which lets you preview the changes that Terraform plans to make to your infrastructure 2. Reads the current state of any already-existing remote objects to make sure that the Terraform state is up-to-date. 3. Compares the current configuration to the prior state and noting any differences. 4. Proposes a set of change actions that should, if applied, make the remote objects match the configuration. 5. You can use the optional -out=FILE option to save the generated plan to a file on disk6. Terraform has two alernative planning modes: -destroy and -refresh-only 7. Terraform has following planning options:- -refresh=false , -replace=ADDRESS , -target=ADDRESS , -var 'NAME=VALUE' , and -var-file=FILENAME 8. Terraform planning mode and planning options are available for both terraform plan and terraform apply |
terraform apply |
1. Apply the execution plan to provision the resources 2. You can pass the -auto-approve option to instruct Terraform to apply the plan without asking for confirmation. |
terraform destroy |
1. Destroy all remote objects managed by a particular Terraform configuration. 2. This command is effectively an alias for terraform apply -destroy |
terraform login |
1. terraform login [hostname] is used to automatically obtain and save an API token for Terraform Cloud, Terraform Enterprise, or any other host that offers Terraform services.2. If you don’t provide an explicit hostname, Terraform will assume you want to log in to Terraform Cloud at app.terraform.io |
terraform logout |
1. terraform logout [hostname] is used to remove credentials stored by terraform login . These credentials are API tokens for Terraform Cloud, Terraform Enterprise, or any other host that offers Terraform services.2. If you don’t provide an explicit hostname, Terraform will assume you want to log out of Terraform Cloud at app.terraform.io |
terraform console |
Provides an interactive command-line console for evaluating and experimenting with expressions. |
terraform fmt |
1. Format code in terrform style convention 2. Indent two space for each nesting level and align equals signs at same nesting level 3. terraform fmt -diff displays diff of formatting changes |
terraform validate |
1. Validates the configuration files in a directory, referring only to the configuration and not accessing any remote services such as remote state, provider APIs, etc. 2. Verify whether a configuration is syntactically valid and internally consistent, regardless of any provided variables or existing state 3. terraform validate -json produce validation result in JSON format |
terraform graph |
1. Used to generate a visual representation of either a configuration or execution plan. The output is in the DOT format, which can be used by GraphViz to generate image or charts e.g. terraform graph | dot -Tsvg > graph.svg 2. Use optional -plan tfplan option to render graph using specified plan file |
terraform output |
1. Used to extract the value of an output variable from the state file. 2. Use optional -json and -raw option for output to formatted as JSON and String format. Any sensitive values in Terraform state will be displayed in plain text. |
terraform show |
1. Used to provide human-readable output from a state or plan file 2. Use optional -json option for JSON representation of plan, configuration, and current state |
terraform state |
1. The terraform state command and its subcommands can be used for various tasks related to the Terraform state.2. The terraform state pull and terraform state push subcommands can be used to retrieve and upload the Terraform state from and to a remote backend, respectively. This is useful when multiple users or systems are working with the same Terraform configuration. |
terraform state mv |
Used in the less common situation where you wish to retain an existing remote object but track it as a different resource instance address in Terraform, such as if you have renamed a resource block or you have moved it into a different module in your configuration. |
terraform state rm |
Used in the less common situation where you wish to remove a binding to an existing remote object without first destroying it, which will effectively make Terraform “forget” the object while it continues to exist in the remote system. |
terraform state replace-provider |
Used to replace the provider for resources in a Terraform state e.g. terraform state replace-provider hashicorp/aws registry.acme.corp/acme/aws replaces the hashicorp/aws provider by achme |
terraform state list |
Used to list resources within a Terraform state. |
terraform state show |
Used to show attributes of a single resource in the terraform state e.g. terraform state show aws_instance.foo |
terraform refresh |
1. This command read the remote infrastructure and update the terraform state file to match with remote objects. 2. This won’t modify your real remote objects, but it will modify the terraform state file. 3. This command is here primarily for backward compatibility, but we don’t recommend using it because it provides no opportunity to review the effects of the operation before updating the state. 4. Equivalent command in Terraform v0.15.4 or later is terraform apply -refresh-only -auto-approve 5. It is recommended to use terraform apply -refresh-only or terraform plan -refresh-only instead, which gives an opportunity to review the changes. |
terraform taint |
1. Informs Terraform that a particular object has become degraded or damaged. Terraform represents this by marking the object as “tainted” in the Terraform state, and Terraform will propose to replace it in the next plan you create. 2. Use the -replace option with terraform apply For Terraform v0.15.2 and later |
terraform force-unlock |
1. Manually unlock the state for the defined configuration. 2. This command removes the lock on the state for the current configuration. The behavior of this lock is dependent on the backend being used |
terraform workspace |
1. Terraform workspace command is used to manage worsspaces 2. State files for each workspace are stored in the directory terraform.tfstate.d 3. terraform workspace list to list all existing workspaces4. terraform workspace select prod to switch to existing workspace with name prod5. terraform workspace new uat to create and switch to new workspace with name uat6. terraform workspace delete dev to delete existing workspace with name dev and it must not be your current workspace7. terraform workspace show to show current workspace |
terraform import |
Used to import the existing remote resources into the Terraform state file. This allows Terraform to manage resources that were created outside of Terraform. |
terraform import
command used using below three steps:-
//1. first write empty resource block in config *.tf* file
resource "aws_instance" "example" {
# ...instance configuration...
}
//2. then run command to import existing remote aws instance with id i-abcd1234 to state *.tfstate* file
$ terraform import aws_instance.example i-abcd1234
//3. copy the required configuration manually from state .tfstate file to config *.tf* file
Source: https://developer.hashicorp.com/terraform/cli
Terraform Functions
Function Type | Function Name |
---|---|
Numeric | abs(-12.4) = 12.4 ceil(5.1) = 6 floor(4.9) = 4 log(16, 2) = 4 max(12, 54, 3) = 54 min(12, 54, 3) = 3 parseint("100", 10) = 100 and parseint("FF", 16) = 255 pow(3, 2) = 9 signum(-13) = -1 , signum(0) = 0 , and signum(344) = 1 |
String | chomp("hello\r\n") = hello startswith("hello world", "hello") = true endswith("hello world", "world") = true format("There are %d lights", 4) = There are 4 lights formatlist("Hello, %s!", ["Olivia", "Sam"]) = ["Hello, Olivia!", "Hello, Sam!"] indent(5, "hello") = ・・・・・"hello" join("-", ["foo", "bar", "baz"]) = foo-bar-baz lower("HELLO") = hello upper("hello") = HELLO regex("[a-z]+", "53453453.345345aaabbbccc23454") = aaabbbccc regexall("[a-z]+", "1234abcd5678efgh9") = ["abcd", "efgh"] replace("1 + 2 + 3", "+", "-") = 1-2-3 split(",", "foo,bar,baz") = ["foo","bar","baz"] strrev("hello") = olleh substr("hello world", 1, 4) = ello title("hello world") = Hello World trim("foobar", "far") = oob trimprefix("helloworld", "hello") = world trimsuffix("helloworld", "world") = hello trimspace(" hello\n\n") = hello |
Collection | alltrue(["true", true]) = true anytrue([true, false]) = true chunklist coalesce("a", "b") = a and coalesce("", "b") = b coalescelist(["a", "b"], ["c", "d"]) = ["a", "b"] and coalescelist([], ["c", "d"]) = ["c", "d"] compact(["a", "", "b", "c"]) = ["a", "b", "c"] concat(["a", ""], ["b", "c"]) = ["a", "", "b", "c"] contains(["a", "b", "c"], "a") = true distinct(["a", "b", "a", "c", "d", "b"]) = ["a", "b", "c", "d"] element(["a", "b", "c"], 1) = b flatten([["a", "b"], [], ["c"]]) = ["a", "b", "c"] index(["a", "b", "c"], "b") = 1 keys({a=1, c=2, d=3}) = ["a", "b", "d"] length(["a", "b"]) = 2 tolist([a, b, c]) converts to list lookup tomap({a = "b" c = "d"}) converts to map matchkeys merge one range(3) = [0, 1, 2] and range(1, 4) = [1, 2, 3] reverse([1, 2, 3]) = [3, 2, 1] setintersection(["a", "b"], ["b", "c"], ["b", "d"]) = ["b"] setproduct setsubtract(["a", "b", "c"], ["a", "c"]) = ["b"] setunion(["a", "b"], ["b", "c"], ["d"]) = ["d", "b", "c", "a"] slice(["a", "b", "c", "d"], 1, 3) = ["b", "c"] sort(["e", "d", "a", "x"]) = ["a", "b", "e", "x"] sum([10, 13, 6, 4.5]) = 33.5 transpose values({a=3, c=2, d=1}) = [3, 2, 1] zipmap(["a", "b"], [1, 2]) = {"a"=1 "b"=2} |
Encoding | base64encode("Hello World") = SGVsbG8gV29ybGQ= base64decode("SGVsbG8gV29ybGQ=") = Hello World base64gzip textencodebase64("Hello World", "UTF-16LE") = SABlAGwAbABvACAAVwBvAHIAbABkAA== textdecodebase64("SABlAGwAbABvACAAVwBvAHIAbABkAA==", "UTF-16LE") = Hello World csvdecode jsondecode jsonencode urlencode("Hello World!") = Hello+World%21 yamldecode yamlencode |
Filesystem | abspath(path.root) = /home/user/some/terraform/root dirname("foo/bar/baz.txt") = foo/bar pathexpand("~/.ssh/id_rsa") = /home/steve/.ssh/id_rsa basename("foo/bar/baz.txt") = baz.txt file("${path.module}/hello.txt") = Hello World fileexists("${path.module}/hello.txt") = true fileset(path.module, "files/*.txt") = ["files/hello.txt", "files/world.txt"] filebase64("${path.module}/hello.txt") = SGVsbG8gV29ybGQ= templatefile(path, vars) |
Date and Time | formatdate("DD MMM YYYY hh:mm ZZZ", "2018-01-02T23:12:01Z") = 02 Jan 2018 23:12 UTC timeadd("2017-11-22T00:00:00Z", "10m") = 2017-11-22T00:10:00Z timecmp("2017-11-22T00:00:00Z", "2017-11-22T01:00:00Z") = -1 timestamp() = 2023-05-13T07:44:12Z |
Hash and Crypto | base64sha256("hello world") = uU0nuZNNPgilLlLX2n2r+sSE7+N6U4DukIj3rOLvzek= filebase64sha256() base64sha512("hello world") = MJ7MSJwS1utMxA9QyQLytNDtd+5RGnx6m808qG1M2G+YndNbxf9JlnDaNCVbRbDP2DDoH2Bdz33FVC6TrpzXbw== filebase64sha512() md5("hello world") = 5eb63bbbe01eeed093cb22bb8f5acdc3 filemd5() sha1("hello world") = 2aae6c35c94fcfb415dbe95f408b9ce91ee846ed filesha1() sha256("hello world") = b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9 filesha256() sha512("hello world") = 309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca86d4cd86f989dd35bc5ff499670da34255b45b0cfd830e81f60 filesha512() bcrypt("hello world") = $2a$10$D5grTTzcsqyvAeIAnY/mYOIqliCoG7eAMX0/oFcuD.iErkksEbcAa rsadecrypt(filebase64("${path.module}/ciphertext"), file("privatekey.pem")) = hello world uuid() = b5ee72a3-54dd-c4b8-551c-4bdc0204cedb uuidv5("dns", "www.terraform.io") = a5008fae-b28c-5ba5-96cd-82b4c53552d6 |
IP Network | cidrhost, cidrnetmask, cidrsubnet, cidrsubnets |
Type Conversion | can, nonsensitive, sensitive, tobool, tolist, tomap, tonumber, toset, tostring, try, type |
Source: https://developer.hashicorp.com/terraform/language/functions
Terraform Tiers
Feature ▼ | OSS (Open Source) | Cloud Free | Cloud Team & Governance | Cloud Business | Enterprise |
---|---|---|---|---|---|
Infrastructure as code (HCL) | ✅ | ✅ | ✅ | ✅ | ✅ |
Workspaces | ✅ | ✅ | ✅ | ✅ | ✅ |
Variables | ✅ | ✅ | ✅ | ✅ | ✅ |
Runs (separate plan and apply) | ✅ | ✅ | ✅ | ✅ | ✅ |
Resource graph | ✅ | ✅ | ✅ | ✅ | ✅ |
Providers | ✅ | ✅ | ✅ | ✅ | ✅ |
Modules | ✅ | ✅ | ✅ | ✅ | ✅ |
Public registry | ✅ | ✅ | ✅ | ✅ | ✅ |
Remote state storage | ⬜ | ✅ | ✅ | ✅ | ✅ |
Secure variable storage | ⬜ | ✅ | ✅ | ✅ | ✅ |
Remote runs (plan & apply) | ⬜ | ✅ | ✅ | ✅ | ✅ |
Private registry | ⬜ | ✅ | ✅ | ✅ | ✅ |
Projects | ⬜ | ✅ | ✅ | ✅ | ✅ |
Dynamic provider credentials | ⬜ | ✅ | ✅ | ✅ | ✅ |
Run triggers | ⬜ | ✅ | ✅ | ✅ | ✅ |
VCS connection | ⬜ | ✅ | ✅ | ✅ | ✅ |
Workspace management | ⬜ | ✅ | ✅ | ✅ | ✅ |
Team management | ⬜ | ⬜ | ✅ | ✅ | ✅ |
Cost estimation | ⬜ | ⬜ | ✅ | ✅ | ✅ |
Policy as code (Sentinel) | ⬜ | ⬜ | ✅ | ✅ | ✅ |
Policy as code (OPA) | ⬜ | ⬜ | ✅ | ✅ | ✅ |
Run tasks: Advisory enforcement | ⬜ | ⬜ | ✅ | ✅ | ✅ |
Run tasks: Hard enforcement | ⬜ | ⬜ | ✅ | ✅ | ✅ |
Policy enforcement level: Advisory | ⬜ | ⬜ | ✅ | ✅ | ✅ |
Policy enforcement level: Soft/hard mandatory | ⬜ | ⬜ | ✅ | ✅ | ✅ |
No-code provisioning | ⬜ | ⬜ | ⬜ | ✅ | ⬜ |
Configuration designer | ⬜ | ⬜ | ⬜ | ✅ | ✅ |
SSO (Single Sign On) | ⬜ | ⬜ | ⬜ | ✅ | ✅ |
Support for ServiceNow integration | ⬜ | ⬜ | ⬜ | ✅ | ✅ |
Drift detection | ⬜ | ⬜ | ⬜ | ✅ | ✅ |
Audit logging | ⬜ | ⬜ | ⬜ | ✅ | ✅ |
Concurrent Runs | ⬜ | 1 | 2(Add-on) | Pay to customize | ✅ |
Self-hosted agents | ⬜ | ⬜ | ⬜ | Pay to customize | ✅ |
Cross-organization registry sharing | ⬜ | ⬜ | ⬜ | ⬜ | ✅ |
Runtime metrics (Prometheus) | ⬜ | ⬜ | ⬜ | ⬜ | ✅ |
Air gap network deployment | ⬜ | ⬜ | ⬜ | ⬜ | ✅ |
Application-level logging | ⬜ | ⬜ | ⬜ | ⬜ | ✅ |
Log forwarding | ⬜ | ⬜ | ⬜ | ⬜ | ✅ |
Clustered Horizontal Scaling | ⬜ | ⬜ | ⬜ | ⬜ | ✅ |
Source: https://www.hashicorp.com/products/terraform/pricing