Problem
The Terraform plan output shows unexpected resource update, create, or replace.
Common Causes
There are a number of possible causes for planned changes, but they are nearly always avoidable with changes to the Terraform configuration. Here are some possible causes:
Unintended dependency
When a resource or data source references another resource or data source, any planned change in the referenced resource will cause a planned change in the downstream resource.
Here it is clear that example_resource.b
depends on example_resource.a
:
"example_resource" "a" {
argument = "abc"
}
"example_resource" "b" {
argument = example_resource.a.id
}
However, dependencies can also occur without directly referencing another resource. Directory structure:
.
├── modules
│ ├── a
│ │ └── a.tf
│ └── b
│ │ └── b.tf
└── main.tf
main.tf:
module "a" {
source = "./modules/a"
}
module "b" {
source = "./modules/b"
depends_on = [module.a]
}
modules/a/a.tf:
"example_resource" "a" {
argument = "abc"
}
modules/b/b.tf:
data "example_datasource" {
argument = "xyz"
}
"example_resource" "b" {
argument = data.example_datasource.output_value
}
Because of the depends_on = [module.a]
, module.b.example_resource.b
ultimately depends on module.a.example_resource.a
, so any changes to the "a" resource may cause unexpected planned changes to the "b" resource.
Solution: Refactor to remove the depends_on
in the module block. See Best Practice: depends_on Meta-Argument for the recommended pattern.
Use of "apply time" functions like uuid() or timestamp()
Functions like uuid() will be executed every time Terraform executes the configuration, so will always produce planned changes when used in resource or data source arguments, which can be unexpected. Per the timestamp() documentation:
> Due to the constantly changing return value, the result of this function cannot be predicted during Terraform's planning phase, and so the timestamp will be taken only once the plan is being applied.
Solution: avoid using these functions in resource arguments.
Use of incompatible resource configuration
Using certain provider resources at the same time can cause unexpected changes to appear on every Terraform plan. These incompatibilities will typically be documented in a note in the resource documentation.
An example of this are the aws_vpc_security_group_egress_rule
and aws_vpc_security_group_ingress_rule
resources used with the aws_security_group_rule
resource, per documentation note.
Solution: refactor to avoid using the incompatible resources in the same configuration.
Incorrect permissions
There is a common provider API design which will return 404 instead of 403 for incorrectly authorized requests for resource objects. When using Terraform to manage resources that use this design, if the credentials used by Terraform are misconfigured to only allow CREATE but not READ of the resource, Terraform can initially create the resource but be unable to read back the resource to verify a successful create. This causes Terraform to unexpectedly plan to create the resource again on subsequent plans.
Solution: Follow each provider's auth documentation for setting up required permissions to manage resources with that provider, and import resources as needed.
Resource changed outside of Terraform
If a user or automated process external to Terraform modifies a resource managed by Terraform, Terraform will plan to modify the resource to match the configuration when it is next run. Beginning with Terraform 0.15.4, Terraform announces which resources have been found to be changed since the last Terraform run. If these external changes are unexpected, the planned changes may be unexpected.
Solution: review access controls to infrastructure to avoid unplanned changes external to Terraform.
Provider version change
Provider releases can include breaking resource changes which may cause unexpected changes in the plan.
Solution See this KB Article for more details and solution for avoiding provider upgrades. When upgrading, make sure to follow any documented upgrade guides. This AWS Version 5 Upgrade Guide is one example.
Additional Information
If none of the above explain an unexpected change in the Terraform plan, there may be a defect with the Terraform provider plugin being used. Reach out on the provider's GitHub issue page or to HashiCorp Support for enterprise support.