Skip to content

Feature Request: Provider-independent, resource metadata/tags/labels #37697

@jcmcken

Description

@jcmcken

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions