Terraform: Allow ${self.resource_name} exception to refer to resource name

Created on 19 Oct 2017  ·  7Comments  ·  Source: hashicorp/terraform

Using self in resource to reuse its name is currently impossible

resource "digitalocean_record" "mars" {
  domain     = "cyber.fund"
  type       = "A"
  name       = "${self.resource_name}"
  value      = "93.125.26.210"
}

Gives this error

* resource 'digitalocean_record.mars' config: cannot contain self-reference self.resource_name

Previous issues were closed without solution, of which self.resource_name seems to be logical for everyone https://github.com/hashicorp/terraform/issues/925#issuecomment-237582442

Self reference for fields inside resource definition is hard, because it may produce infinite loop - https://github.com/hashicorp/terraform/commit/ae6bf241ec10b6d6eb01bb85a88b241855c19ffe#diff-2437af93acd4d73bd3a7a3fb1d4a38b6R9

But self.resource_name is safe from infinite loops. Fixing it requires setting it somewhere, and lifting limitation on self reference for this specific case in https://github.com/hashicorp/terraform/blob/bbf9725134a75cc11661f5e2b316e8d81c1e05e4/config/config.go#L774 The updating the docs to include exceptional case https://www.terraform.io/docs/configuration/interpolation.html#attributes-of-your-own-resource

Terraform Version

v0.10.7

References

  • #5412
  • #925
  • #5805
config enhancement

Most helpful comment

Did anything change in 0.12 to allow referencing resource name inside its block?

All 7 comments

As per current state of affairs , Is there a way to access the the in-line resource name from the plugin code , rather than defining a new "Name" attribute ?

It shouldn't be just the resource name. All non-dynamic attributes should be referenceable.

Example:

resource "aws_s3_bucket" "example_com" {
    bucket = "example.com"
    logging {
        target_bucket = "logs.example.com"
        target_prefix = "logs/${self.bucket}"
    }
}

Thanks for this feature request @abitrolly, and sorry for the delay in responding.

We've discussed in some other issues the idea of adding a new meta object that can be used to access metadata about various objects, like meta.aws_s3_bucket.example.created_time or meta.self.created_time, which would then avoid potential collisions with the actual data attributes of the resources. If we decided to implement this here then I think that's how we'd do it.

However, in general we are concerned about exposing the resource name in this way because there is a significant difference in scope between the resource name and the resource attributes: the resource's name is local to the current module, while the resource attributes are (in the normal case of a resource managing a remote object in some API) global.

While I can see some legitimate use-cases for it, like your example here of making the resource name match the DNS record name, ultimately I think that the extra complexity of having this feature and having to explain to users when it is and is not appropriate to use it outweighs the marginal benefit of matching the resource name with some attribute, especially once #17179 is implemented and it'd then be possible to use the _map key_ in expressions:

# not yet implemented, and details may change before release

locals {
  dns_a_records = {
    mars = "93.125.26.210"
  }
}

resource "digitalocean_record" "a" {
  for_each = local.dns_a_records

  domain     = "cyber.fund"
  type       = "A"
  name       = each.key
  value      = each.value
}

So with that said, unfortunately I think I'll have to say no to this request for now. I think the solution to #17179 will provide a way to reach a similar goal of avoiding repetition, but in a way which fits better within the language. For DNS in particular, I have a side project which is aiming to make use of both for_each and other planned Terraform features to create modules that abstract over different DNS providers.

Thanks for sharing this suggestion and use-case. We're hoping that #17179 will be possible in the not-too-distant future because we're laying some groundwork for it as part of current work on the configuration language.


@jleclanche the idea of allowing self. to reference resource attributes that are set explicitly in the config is a good one, and I agree that it'd be a useful addition. It's not currently compatible with how Terraform resolves expressions internally, but we may be able to add special handing for that situation in future. I think that's the same idea from the older issue #3267, so if you'd like to vote for that using the :+1: reaction on the initial comment we can use that as a signal in our planning process. I don't expect we'll be able to work on it in the very near future because there's already lots of other configuration-related work in progress for the next major release, but I agree it'd be very useful and would like to support it eventually.

Ref #8706 which wants more-or-less the same thing, and 💯 #17179 cannot come fast enough.

Even with a for_each construct this feature would make sense, since it would let you do things like

for_each ${var.buckets} as ${bukkit} {
  module "mah_bukkit" ${bukkit.value} {}
}

Refactoring that to use the module content directly in the for_each would probably be better long-term, but it would be a much simpler transition if this feature were part of the existing module constructs.

Did anything change in 0.12 to allow referencing resource name inside its block?

I know, commenting on a closed issue has little value but I just wanted to add another use-case, per https://github.com/hashicorp/terraform/issues/16394#issuecomment-399210195, that I haven't seen mentioned: Tagging

resource provider_service_name resource_name {
  ...
  tags = {
    terraform_resource = meta.resource_address
  }
  ...
}

where meta.resource_address evaluates to provider_service_name.resource_name.

Providing a set of standard tags has proven to be incredibly valuable for purposes of auditing, billing, and diagnostics, especially automated/computed values based on details not readily accessible in the deployed infrastructure.

I'm going to lock this issue because it has been closed for _30 days_ ⏳. This helps our maintainers find and focus on the active issues.

If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

Was this page helpful?
0 / 5 - 0 ratings