Target resources
When you apply changes to your Terraform projects, Terraform generates a plan that includes all of the differences between your configuration and the resources currently managed by your project, if any. When you apply the plan, Terraform will add, remove, and modify resources as proposed by the plan.
In a typical Terraform workflow, you apply the entire plan at once. Occasionally you may want to apply only part of a plan, such as when Terraform's state has become out of sync with your resources due to a network failure, a problem with the upstream cloud platform, or a bug in Terraform or its providers. To support this, Terraform lets you target specific resources when you plan, apply, or destroy your infrastructure. Targeting individual resources can be useful for troubleshooting errors, but should not be part of your normal workflow.
You can use Terraform's -target
option to target specific resources, modules,
or collections of resources. In this tutorial, you will provision an S3 bucket
with some objects in it, then apply changes incrementally with -target
.
Prerequisites
You can complete this tutorial using the same workflow with either Terraform Community Edition or HCP Terraform. HCP Terraform is a platform that you can use to manage and execute your Terraform projects. It includes features like remote state and execution, structured plan output, workspace resource summaries, and more.
Select the HCP Terraform tab to complete this tutorial using HCP Terraform.
This tutorial assumes that you are familiar with the Terraform workflow. If you are new to Terraform, complete the Get Started collection first.
In order to complete this tutorial, you will need the following:
- Terraform v1.2+ installed locally.
- An AWS account with local credentials configured for use with Terraform.
Note
Some of the infrastructure in this tutorial may not qualify for the AWS free tier. Destroy the infrastructure at the end of the tutorial to avoid unnecessary charges. We are not responsible for any charges that you incur.
Create infrastructure
Clone the example configuration for this tutorial, which defines an S3 bucket with a randomized name, and four S3 bucket objects.
Navigate to the repository directory.
Initialize this configuration.
Apply this configuration to create your S3 bucket and objects. Confirm the operation by typing yes
at the prompt.
Tip
This tutorial shows the output for Terraform commands run with Terraform Community Edition. If you are following the HCP Terraform workflow, the output may differ slightly but the results will be the same.
Target the S3 bucket name
In main.tf
, find the random_pet.bucket_name
resource. The bucket module uses this resource to assign a randomized name to the S3 bucket. Update the value of length
to 5
.
Plan this change.
Notice how Terraform plans to change the random_pet
resource along with any
resources dependent on it.
Tip
To change the bucket's name, Terraform must replace the bucket. AWS does not support renaming buckets in place. The AWS provider understands this, and Terraform creates a plan that will replace or update your resources as needed.
Plan the change again, but target only the random_pet.bucket_name
resource.
Terraform will plan to replace only the targeted resource.
Now create a plan that targets the module, which will apply to all resources within the module.
Terraform determines that module.s3_bucket
depends on
random_pet.bucket_name
, and that the bucket name configuration has changed.
Because of this dependency, Terraform will update both the upstream bucket name
and the module you targeted for this operation. Resource targeting updates
resources that the target depends on, but not resources that depend
on it.
Note
Terraform creates a dependency graph to determine the correct order in which to apply changes. You can read more about how it works in the Terraform documentation.
Apply the change to only the bucket name. Respond to the confirmation prompt
with yes
.
Notice that the bucket_name
output changes, and no longer matches the bucket
ARN. Open outputs.tf
and note that the bucket name output value references the
random pet resource, instead of the bucket itself.
When using Terraform's normal workflow and applying changes to the entire working directory, the bucket name modification would apply to all downstream dependencies as well. Because you targeted the random pet resource, Terraform updated the output value for the bucket name but not the bucket itself. Targeting resources can introduce inconsistencies, so you should only use it in troubleshooting scenarios.
Update the bucket_name
output to refer to the actual bucket name.
Because you targeted only part of your configuration in the last operation,
your existing resources do not match either the original configuration or the
new configuration. Apply changes to the entire working directory to make Terraform update your infrastructure to match the current configuration, including the change you made to the bucket_name
output. Confirm the operation by typing yes
at the prompt.
After using resource targeting to fix problems with a Terraform project, be sure
to apply changes to the entire configuration to ensure consistency across all resources. Remember that you
can use terraform plan
to see any remaining proposed changes.
Target specific bucket objects
Open main.tf
and update the contents of the bucket objects. The example
configuration uses a single line of example text to represent objects with
useful data in them. Change the object contents as shown below.
You can pass multiple -target
options to target several resources at
once. Apply this change to two of the bucket object and confirm with a yes
.
Terraform updated the selected bucket objects and notified you that the changes to your infrastructure may be incomplete.
Target bucket object names
As shown above, you can target individual instances of a collection created
using the count
or for_each
meta-arguments. However, Terraform calculates
resource dependencies for the entire resource. In some cases, this can lead to
surprising results.
Remove the prefix
argument from the random_pet.object_names
resource in
main.tf
.
Attempt to apply this change to a single bucket object.
Notice that Terraform updated all five of the random_pet.object_name
resources, not just the name of the
object you targeted. Both random_pet.object_name
and aws_s3_object.object
use count
to provision multiple resources, and each bucket object refers to the name of the same index. However, because the
entire aws_s3_bucket_objects.objects
resource depends on the entire
random_pet.object_names
resource, Terraform updated all the names.
Accept the change with a yes
.
Destroy your infrastructure
Terraform's destroy command also accepts resource targeting. In the examples
above, you referred to individual bucket objects with their index in square brackets, such as
aws_s3_bucket_object.objects[2]
. You can also refer to the entire collection
of resources at once. Destroy the bucket objects, and respond to the
confirmation prompt with a yes
.
Now destroy the rest of your infrastructure. Respond to the confirmation prompt
with yes
.
If you used HCP Terraform for this tutorial, after destroying your resources, delete the learn-terraform-resource-targeting
workspace from your HCP Terraform organization.
Next steps
In this tutorial, you used Terraform's resource targeting to specify which resources to apply a given change to. Resource targeting is a useful tool in some contexts, but you should avoid using it in day to day operations, as it can cause your infrastructure to become inconsistent.
- Read the Terraform documentation for resource targeting.
- Follow the tutorial on how to manage resource drift.
- Learn how to troubleshoot common inssues in Terraform.
- Follow our Manage Resources in Terraform State tutorial to learn about other ways to manipulate Terraform state.