Hi @jimsnab,
Without seeing some more specific information I can only really guess what’s going on here, but my best guess is that because you have resources that are no longer present in the configuration Terraform is instead using information from the state to recover the original dependency information. I can imagine some trickier cases where the configuration has changed a lot where the partial information in the configuration combines with the partial information in the state to produce an invalid dependency graph.
The Terraform team at HashiCorp is currently working on a forthcoming new feature for documenting historical moves/renames of resources and modules, one motivation for which is to help Terraform understand the historical context when making a plan. This is similar in principle to your idea of referring to historical .tf
files, but with the information recorded in the current .tf
files instead (because Terraform typically doesn’t have access to a historical configuration.)
# NOT YET RELEASED
moved {
from = aws_instance.a
to = aws_instance.b
}
When making a plan for a configuration containing a statement like the above, Terraform would first check to see if there’s an aws_instance.a
recorded in the state, and if so pretend that it had originally been created as aws_instance.b
instead. The main motivation for this is to avoid replacing the object when moving it, but it can also help with the situation you encountered because Terraform wiill be able to see that it should use the current configuration of aws_instance.b
in order to understand the dependencies for what was formerly recorded as aws_instance.a
.
Although out of scope for the initial work we’re currently doing, we’re also considering some similar annotations for other sorts of changes that Terraform might need to take into account when planning. One candidate is a removed
block which records that a resource used to exist and gives a place to capture some metadata about it that can help Terraform understand how that object was originally declared:
# NOT YET IMPLEMENTED: Final design might look different
removed {
from = aws_instance.a
depends_on = [aws_instance.c]
}
For the initial release Terraform will require writing moved
blocks manually in order to get the benefit from them, but we’re also considering later additions of new commands to help coordinate changes to the current module:
-
terraform move aws_instance.a aws_instance.b
might potentially relabel the resource "aws_instance" "a"
as resource "aws_instance" "b"
and generate the moved
block shown above in a single action.
-
terraform remove aws_instance.a
might potentially remove the resource "aws_instance" "a"
block and generate a removed
block including a depends_on
that covers the same dependencies that the resource configuration previously implied, along with any other information that can help Terraform plan to destroy that object.
(Again, these are just hypothetical examples to show what I mean, and the final design might be quite different.)
Do you think that the functionality I’ve described above might’ve helped with the problem you encountered?
It would also be interesting to think about, as you suggested, having a way to provide a historical version of the configuration so that Terraform can potentially infer information like what might appear in a removed
block, though that’d be a very significant change to Terraform’s model which I’m sure will have various implications to consider while designing it. Therefore I think implementing something like this removed
block I showed above, potentially accompanied by a command to automate generating it, is the more practical solution in the medium term, and it seems likely that the functionality it implies would end up being part of any automatic solution based on analyzing an old configuration anyway.