Annotating resources with file and line?

It would be helpful sometimes to understand where a resource came from. If, say, I have lots of different Terraform files to describe what’s going on in a cloud account, but I’m new to the team, it might be helpful to be able to do terraform show on a state file and have it mention the path to the source file and maybe the line number in that file where each resource was declared. I’m imagining something like what __FILE__ and __LINE__ do in C.

I realize that the best one could do here would be to capture these details as of the time of the last apply or plan+refresh, and it might become stale if the source files get rearranged, but that might be a lot better than nothing.

The closest thing I can think of right now is to put ${path.module} in a tag for every resource, but I’m imagining something more automatic than that.

Hi @msk,

Terraform does not expose source location information as data you can interact with in the language, because that would mean that normally-harmless code rearrangement would cause changes to the real infrastructure, making it risky to reorganize any code.

If you are starting with the Terraform state and working backwards from there, the unique resource instance addresses in the state should always correlate exactly with resource blocks of the same type and name in the most recently applied, and so you can “walk backwards” from state to configuration by searching for the block matching the resource instance address you are looking for.

With that said, when someone is new to a system I would typically suggest that they start with the configuration rather than with the state, because the configuration hopefully (if it was written with care to future maintainers) better captures information about author intent and about the relationships between objects. Evaluating the configuration to produce the “desired state” is an inherently lossy operation – replacing expression references and other calculations with just their result values – and so there will typically be more information in the source configuration about how the system is put together, whereas in state you would be left to just guess by correlating ids between objects.

In contexts where many different Terraform configurations are all managing different subsets of an overall system it can be helpful to leave some information in the remote system about which overall configuration a particular object or set of objects originated from, but that typically only needs to be a top-level repository name, or similar, that’s just enough to find the root module source code, after which you can read the configuration to find out how that subsystem is built. In that case, you can just put your chosen subsystem name into a local variable in your root module and refer to it in your resource definitions, so that it’s defined just once in each configuration and can be changed in only one place if needed – though hopefully these logical “subsystem names” would not change often.

Yeah, I realize the code rearrangement could make any such annotations incorrect. But 90% of the time, it’s probably right. I’d be happy for this to be something that exists with a caveat that it can be inaccurate for $REASONS.

Most of the mechanisms you describe will work, of course; “grep -r” is very helpful here. But that’s manual; for something programmatic, or for something like “terraform show” to work, these sorts of markers would be very handy, even with understood warnings about accuracy. That is, I’d be content with something that indicated “The definition of this resource was last seen at file X line Y”.

Imagine for example well a program that consumes a JSON dump of a “plan” output looking for anomalies. “There was a bucket defined at file X line Y that’s got some peculiar settings” becomes possible with annotations like these.

One thing that Terraform CLI could do without any changes to the language is to try to find the configuration block corresponding to each item listed in terraform show and mention its source location, if there is one. (Of course the block might’ve been removed already, in which case it would need to be able to say “removed from the configuration” or whatever.)

That’s not done I think largely because not enough people have expressed caring about it for it to seem worth spending the time to implement and maintain it, not because it’s technically challenging: Terraform itself can match the resource instance addresses in the state with the resource addresses in the configuration without any ambiguity.

If you’d find something like that useful, I’d suggest opening an issue about it in the main Terraform GitHub repository, and then we can use the usual consensus and voting methods to see if there are any significant downsides to doing it and see how many people would benefit from it.