Skip to main content

Using Meta-Arguments

1. Using depends_on Meta-Argument

Property Description Usage
depends_on Ensures that a resource is created or destroyed before another resource. depends_on = [aws_instance.web, aws_instance.db]

Example: Using depends_on to enforce resource order

resource "aws_instance" "web" {
  ami           = "ami-12345678"
  instance_type = "t2.micro"

  depends_on = [aws_instance.db]
}

resource "aws_instance" "db" {
  ami           = "ami-87654321"
  instance_type = "t2.micro"
}
Note: depends_on is not recommended for most use cases as it can lead to complex dependency graphs and reduce Terraform's ability to safely execute operations in parallel.

2. Using count Meta-Argument

The count meta-argument is used to create multiple instances of a resource or module based on a numeric value.

Property Description Values
count Defines the number of instances to create number

Example: Creating Multiple Instances

resource "aws_instance" "web" {
  count = 3
  ami           = "ami-12345678"
  instance_type = "t2.micro"
}

Example: Using count with a Variable

variable "instance_count" {
  type    = number
  default = 2
}

resource "aws_instance" "web" {
  count = var.instance_count
  ami           = "ami-12345678"
  instance_type = "t2.micro"
}
Note: When using count, each instance has a unique index starting from 0, accessible via count.index.
Warning: Changing the value of count will cause Terraform to destroy and recreate resources, potentially leading to data loss.

Key Points

  • count creates multiple instances of a resource or module.
  • Each instance is accessible via count.index.
  • Changing the value of count triggers a full recreation of resources.

3. Using for_each Meta-Argument

The for_each meta-argument allows you to create multiple instances of a resource or module based on a map or set of strings. It's particularly useful for creating multiple similar resources with different configurations.

Property Description Example
for_each Map or set of strings to iterate over. Each key-value pair creates a new instance. for_each = { env1 = "prod", env2 = "staging" }

Example: Creating Multiple S3 Buckets

resource "aws_s3_bucket" "bucket" {
  for_each = {
    prod   = "production"
    staging = "staging"
  }

  bucket = "my-app-${each.key}"
  tags = {
    Environment = each.value
  }
}
Note: When using for_each, the resource instances are created in the order of keys in the map. If you're using a set, the order is not guaranteed.

Example: Using for_each with Modules

module "web_server" {
  for_each = {
    us_west = { region = "us-west-2", instance_type = "t3.micro" }
    us_east = { region = "us-east-1", instance_type = "t3.small" }
  }

  source = "./web_server_module"
  region = each.value.region
  instance_type = each.value.instance_type
}

Key Points

  • for_each creates multiple instances of a resource or module.
  • It accepts a map or set of strings as input.
  • Each instance can be accessed using each.key and each.value.
  • Resources created with for_each are managed as a list, not a single resource.

4. Using provider Meta-Argument

Property Description Values Notes
provider Specifies the provider to use for a resource or data source aws, google, azurerm, etc. Required for all resources and data sources
version Specifies the version of the provider to use >= 3.0.0, = 4.0.0 Ensures consistent provider behavior across environments
alias Allows multiple instances of the same provider with different configurations alias = "us_west" Useful for managing multiple regions or accounts

Example: Using provider alias

provider "aws" {
  alias = "us_west"
  region = "us-west-2"
}

resource "aws_instance" "web" {
  provider = aws.us_west
  ami = "ami-12345678"
  instance_type = "t2.micro"
}
Note: The provider meta-argument is used to associate a resource or data source with a specific provider configuration. When using aliases, the provider attribute must reference the alias name.

5. Using lifecycle Meta-Argument

Property Description Values Notes
create_before_destroy Controls the order of operations during updates true or false If true, creates new resource before destroying old one. Default is false.
prevent_destroy Prevents destruction of the resource true or false If true, Terraform will block destruction of the resource. Useful for critical resources like databases.
ignore_changes Specifies attributes to ignore during updates List of attribute paths or [all] Can be used to ignore changes made outside of Terraform. Example: ["tags", "labels"].

Example: Using lifecycle with prevent_destroy

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

  lifecycle {
    prevent_destroy = true
  }
}

Example: Using lifecycle with ignore_changes

resource "aws_instance" "web" {
  ami           = "ami-12345678"
  instance_type = "t2.micro"

  lifecycle {
    ignore_changes = [tags]
  }
}
Note: The ignore_changes option is useful when external tools or manual changes update attributes that you don't want Terraform to manage.

6. Understanding create_before_destroy

Property Description Values Notes
create_before_destroy Controls the lifecycle behavior of a resource during updates true or false When set to true, Terraform will create the new resource before destroying the old one. Default is false.

Example: Using create_before_destroy

resource "aws_instance" "web" {
  create_before_destroy = true
  ami                   = "ami-12345678"
  instance_type         = "t2.micro"
}
Note: Enabling create_before_destroy can cause downtime in some cases, particularly when updating resources that do not support in-place updates.

7. Understanding prevent_destroy

Argument Description Values Notes
prevent_destroy Prevents destruction of the resource during a terraform destroy operation false | true Defaults to false. When set to true, Terraform will block destruction of the resource.

Example: Using prevent_destroy

resource "aws_s3_bucket" "my_bucket" {
  bucket = "my-unique-bucket-name"
  prevent_destroy = true
}
Note: Setting prevent_destroy to true does not prevent the resource from being removed from state, but it prevents Terraform from destroying the resource in the cloud.

8. Understanding ignore_changes

Argument Description Values Notes
ignore_changes Prevents Terraform from managing changes to specified attributes list(string) Useful for external modifications to resources

Example: ignore_changes in a resource block

resource "aws_instance" "web" {
  ami           = "ami-12345678"
  instance_type = "t2.micro"

  lifecycle {
    ignore_changes = [
      tags,
      ami
    ]
  }
}
Note: ignore_changes does not prevent Terraform from detecting changes in the configuration itself, only in the resource state.

9. Using precondition and postcondition

Argument Description Required Example
precondition Defines a condition that must be true before a resource is created or updated. No
precondition {
  condition     = self.enabled
  error_message = "The resource must be enabled to proceed."
}
postcondition Defines a condition that must be true after a resource is created or updated. No
postcondition {
  condition     = self.status == "running"
  error_message = "The resource must be running after creation."
}

Example: Using precondition and postcondition in a resource

resource "aws_instance" "web" {
  ami           = "ami-12345678"
  instance_type = "t2.micro"

  precondition {
    condition     = self.instance_type != "t3.micro"
    error_message = "t3.micro is not allowed for this deployment."
  }

  postcondition {
    condition     = self.private_ip != null
    error_message = "Private IP must be assigned after creation."
  }
}
Note: Precondition and postcondition checks are evaluated during terraform plan and terraform apply. They do not run during terraform destroy.

10. Using replace_triggered_by

Argument Description Usage
replace_triggered_by Triggers replacement of a resource when another resource's attribute changes. replace_triggered_by = [aws_instance.old_instance]

Example: Triggering Resource Replacement

resource "aws_instance" "web" {
  ami           = "ami-12345678"
  instance_type = "t2.micro"

  # Replace this instance when the AMI ID changes
  replace_triggered_by = [aws_ami.example]
}

resource "aws_ami" "example" {
  name                = "custom-ami"
  virtualization_type = "hvm"
  architecture        = "x86_64"
  root_device_type    = "ebs"
}
Note: The replace_triggered_by meta-argument is useful for managing dependencies between resources where a change in one should cause a replacement of another.

Was this article helpful?