Resource targeting limits a Terraform plan to selected resources while retaining changes required by their dependencies. For example, targeting a load balancer can still include changes to resources it depends on, but excludes unrelated infrastructure. section 5.3.3
Use it only for exceptional troubleshooting, not normal operations. Manual changes made outside Terraform can leave state or configuration in a condition where Terraform cannot calculate a valid plan; targeting the affected resources may restore a workable state. Batching long-running changes is possible, but recurring use suggests that the project should be split into smaller components. section 5.3.3
Keep these operational boundaries in mind:
- Do not design Terraform modules that require targeting; doing so adds bootstrapping and maintenance complexity. section 5.3.3 section 5.7.5
- Review the resulting plan before applying it. The same planning options, including resource targeting, can be passed when apply creates its plan directly. section 5.5.1
- Prefer refactoring computed values instead of targeting prerequisite resources to make count or for_each calculable. section 5.7.5
Listing 5.13 Accidental use of computed value for count
variable "domain" {
description = "The base domain to use for DNS records."
type = string
}
locals { #1
use_eip = endswith("example.com", aws_route53_record.name) #2
ip_address = local.use_eip ? aws_eip.example[0].public_ip :
aws_instance.example.public_ip #3
}
data "aws_ami" "ubuntu" { #4
most_recent = true
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
owners = ["099720109477"]
}
resource "aws_instance" "example" { #5
ami = data.aws_ami.ubuntu.id
instance_type = "t3.micro"
}
resource "aws_eip" "example" {
count = local.use_eip ? 1 : 0 #6
domain = "vpc"
}
resource "aws_eip_association" "eip_assoc" {
count = local.use_eip ? 1 : 0 #7
instance_id = aws_instance.example.id
allocation_id = aws_eip.example[0].id
}
data "aws_route53_zone" "example" {
name = var.domain
private_zone = true
}
resource "aws_route53_record" "example" {
zone_id = data.aws_route53_zone.example.id
name = "instance.${data.aws_route53_zone.example.id}"
type = "A"
records = [local.ip_address]
}
#1 We’re referencing resources that are defined below, but that’s okay because Terraform doesn’t care about the order.
#2 If the domain is example.com, then use an EIP. Note that it’s pulling the value from the DNS record resource, which introduces a dependency.
#3 If we are using an EIP, then use it’s IP address; otherwise use the machine’s IP address.
#4 As a reminder, this is how we look up the AMI for an instance type.
#5 Here we create our instance.
#6 This is where we run into problems. The use_eip local uses the domain from the DNS record, which isn’t available during planning.
#7 The error is also going to show up here.
Compare an accidental computed-value dependency with a configuration that derives count from an input variable, avoiding resource targeting as a bootstrap step. section 5.7.5
