Terraform Tutorial — Resource Block Anatomy

1 minute read

Every resource block follows the same pattern. Understanding its anatomy lets you read and write any Terraform resource — even ones you’ve never seen before.


The Resource Block

resource "aws_s3_bucket" "my_bucket" {
  bucket = "my-unique-bucket-name-2024"

  tags = {
    Name        = "My Bucket"
    Environment = "dev"
  }
}

Breaking It Down

Part Value Purpose
Block type resource Tells Terraform this creates infrastructure
Resource type "aws_s3_bucket" What kind of resource (provider prefix + resource)
Local name "my_bucket" How you reference it in YOUR config
Body { ... } Configuration arguments

Resource Type Format

The resource type is always <provider>_<resource>:

Resource Type Provider Resource
aws_s3_bucket AWS S3 Bucket
aws_instance AWS EC2 Instance
aws_vpc AWS Virtual Private Cloud
azurerm_resource_group Azure Resource Group
google_compute_instance GCP Compute Instance

Arguments vs Attributes

Arguments are what you SET (inputs). Attributes are what Terraform RETURNS (outputs).

Arguments (You Write These)

resource "aws_s3_bucket" "my_bucket" {
  bucket = "my-unique-bucket-name"    # argument: you set this
}

Attributes (Terraform Computes These)

After terraform apply, the resource has attributes you can reference:

# Reference computed attributes
output "bucket_arn" {
  value = aws_s3_bucket.my_bucket.arn          # computed by AWS
}

output "bucket_domain" {
  value = aws_s3_bucket.my_bucket.bucket_regional_domain_name
}

The full reference syntax is: <resource_type>.<local_name>.<attribute>


Required vs Optional Arguments

Every resource has a mix of required and optional arguments:

resource "aws_instance" "web" {
  # Required arguments
  ami           = "ami-0c55b159cbfafe1f0"    # Must specify
  instance_type = "t3.micro"                  # Must specify

  # Optional arguments
  monitoring                = true            # Default: false
  associate_public_ip_address = true          # Default: depends on subnet
  key_name                  = "my-key-pair"   # Default: none

  tags = {
    Name = "web-server"
  }
}

💡 Tip: Always check the provider documentation to know which arguments are required and which are optional for each resource type.


Resource Addresses

Every resource has a unique address in your configuration:

aws_s3_bucket.my_bucket          # Simple resource
aws_instance.web[0]              # Resource with count (index 0)
aws_s3_bucket.buckets["logs"]    # Resource with for_each (key "logs")
module.vpc.aws_subnet.private[0] # Resource inside a module

You’ll see these addresses in terraform plan output, state commands, and error messages.


What’s Next?

Let’s put this into practice by creating your first real resource — an S3 bucket on AWS.


← Resources Hub Creating an S3 Bucket →