-
Notifications
You must be signed in to change notification settings - Fork 10.1k
Description
Terraform Version
Terraform v1.11.4
on linux_amd64
Use Cases
I want to store key-value string metadata (i.e. map(string)
) for resources independent of the provider. This metadata would be stored within the state file in the same map as the resource itself (e.g. under a field metadata
next to the other fieldsvalues
, sensitive_values
, etc. if you look at the JSON representation of the state), but would not be used by Terraform itself. The purpose of this metadata is in integrating with other, non-Terraform systems.
For example, let's imagine I'm integrating Terraform with a Developer or IT Portal such as Backstage or ServiceNow. I want to pass information such as the business unit, the charge code, or other metadata to that system, and that metadata can change on a resource-by-resource basis (potentially).
A common problem is that not all providers implement a method to add such metadata to the resources themselves. For example, the AWS provider lets you set tags on the resource, which translate to resource tags in the AWS cloud. But not every provider target supports such a mechanism. In such cases, there's not really a good alternative for storing such metadata.
Attempted Solutions
One possibility to solve this problem is to use something like terraform_data
or null_resource
or some other "non-resource" resource to house the data. But this adds significant amounts of data to the state / resource graph, since to link it to a given resource, you would need to make use of resource dependencies. Ideally, you do not want to store additional "resources" in the state, since that also makes it more expensive for Terraform to generate plans / resource graphs.
This solution also means integration points would be completely custom depending on how you implement the dependencies. It would be preferable if every Terraform integration had a common way to reference this kind of metadata.
Finally, this solution also suffers from being much more verbose than is ideal from a user experience point of view. You need significantly more code.
Proposal
It's difficult to add new resource meta-arguments, since they can conflict with arguments providers are already using. But I'm not sure how else you would implement this.
I suppose one alternative would be to support something like a "pragma" in a comment that gets injected into the resource data in the state. But that seems pretty inelegant.
If we were to design Terraform from scratch, we might declare there to be only one allowed meta-argument: meta
, and everything like depends_on
, lifecycle
, etc. goes underneath that meta
block, e.g.:
resource "foo" "bar" {
meta {
lifecycle {
..snip..
}
}
...provider args...
}
..but this would be a much larger change. Nonetheless, it may be worthwhile (for the sake of future language extensibility) to start with this approach, e.g. this would work:
resource "foo" "bar" {
meta {
data {
"foo" = "bar"
}
lifecycle {
..snip..
}
}
...provider args...
}
And for backwards compatibility, this would also work:
resource "foo" "bar" {
meta {
data {
"foo" = "bar"
}
}
lifecycle {
..snip..
}
...provider args...
}
But this would not work:
resource "foo" "bar" {
data {
"foo" = "bar"
}
lifecycle {
..snip..
}
...provider args...
}
References
No response