Terraform Fundamentals · Module 02 of 12

HCL, providers, resources and addresses

Read Terraform configuration fluently, understand provider responsibilities, and reason about resource addresses without confusing names, types and remote object identifiers.

Learning objectives

By the end of this module, you should be able to:

  • Read blocks, arguments and expressions in HCL.
  • Explain required_providers and provider configuration.
  • Identify resource addresses and distinguish them from provider-side IDs.

HCL is structured configuration

Terraform configuration is made of blocks, arguments and expressions. Block labels such as resource type and local name form addresses used throughout plans, state and references.

Providers translate Terraform operations

Providers implement resource and data-source behavior for external APIs. required_providers declares source addresses and version constraints; provider blocks configure instances of those providers.

Addresses are Terraform identities

An address such as aws_instance.web or terraform_data.example["api"] identifies a managed instance in Terraform. A cloud-side ID such as an instance ID is a different concept and is typically stored as an attribute.

Worked examples

See the idea in practice.

Provider constraint pattern

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 6.0"
    }
  }
}
  • Version constraints belong in configuration.
  • .terraform.lock.hcl records concrete provider selections for repeatability.

Resource address

terraform_data.service["api"]
  • The type is terraform_data, the local name is service, and api is the for_each key.
Hands-on lab

Lab — Read HCL and resource addresses

Goal: Create multiple built-in resources and inspect their stable addresses.

Before you start

  • Terraform CLI only.
STEP 1

Create resources

mkdir -p ~/gnu-terraform-labs/module02 && cd ~/gnu-terraform-labs/module02
cat > main.tf <<'EOF'
resource "terraform_data" "service" {
  for_each = toset(["api", "worker"])
  input    = each.key
}
EOF
STEP 2

Initialize and apply

terraform init
terraform apply -auto-approve
STEP 3

List state addresses

terraform state list
STEP 4

Inspect one instance

terraform state show 'terraform_data.service["api"]'

Verify

  • State contains service["api"] and service["worker"].
  • state show displays the selected object attributes.

Expected outcome

  • You can parse a Terraform resource address without confusing it with a remote provider ID.

If it fails

  • Quote addresses containing brackets so the shell does not interpret them.
  • If state is empty, confirm apply completed successfully.
Real-world connection

Accurate addressing is essential for imports, state operations, moved blocks and targeted diagnostics.

Avoid these traps

Common mistakes

  • Using unconstrained provider versions in long-lived production modules.
  • Confusing a resource local name with its remote ID.
  • Editing .terraform provider plugin files manually.
Knowledge check

Can you explain it without looking back?

Open each answer only after you have tried to answer the question yourself.

1What does required_providers declare?

Provider source addresses and acceptable version constraints.

2What is terraform_data.service["api"]?

A Terraform resource instance address.

3Where is the selected provider version recorded?

In .terraform.lock.hcl after initialization.

My Learning

Record your progress for this module.

Progress is saved in this browser immediately. When you sign in to My Learning, it can also sync across devices.

Not started

Attempt the core lab and knowledge checks before marking the module complete.