Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Again need a way to refer to computed values within a resource #23966

Open
clerskine opened this issue Jan 28, 2020 · 11 comments
Open

Again need a way to refer to computed values within a resource #23966

clerskine opened this issue Jan 28, 2020 · 11 comments

Comments

@clerskine
Copy link

Current Terraform Version

0.12.19

Use-cases

We need a way to refer to computed values in a resource within a resource. In this case, we are using the aws_instance resource. Our requirement is that we need to create a tag that is assigned to volumes used and defined with with in the resource which contains the instance id.

There are volume tags available where the tag can be created but there is no way to refer to the id of the instance to set as a value for the tag.

Attempted Solutions

volume_tags = {
Name = "${var.baseName}-slave-east-1-${count.index + 1}"
t_instance_id = self.id
}

Error: Invalid "self" reference

on jenkins.tf line 266, in resource "aws_instance" "jenkins_slave_east":
266: t_instance_id = self.id

Proposal

Allow the values of the resource to be accessed using a construct like self.id. Self is a value that is used elsewhere with in HCL but is not valid in this case.

resource "type" "name" {
...
volume_tags = {
Name = "${var.baseName}-slave-east-1-${count.index + 1}"
t_instance_id = self.id
}
}

References

@iamnicoj
Copy link

Is there any update on this issue? It's been open for a year and it would be really helpful

@topolodgy
Copy link

Adding weight to this use case,

I have pretty much the same issue when trying to return ec2 instance inside a root block stanza:

resource "aws_instance" "ec2" {
----snip----
root_block_device {
delete_on_termination = true
encrypted = true
tags = merge(
local.common_tags,
tomap({ t_instance_id = self.id,})

We have automated processes that check for instance ID tags on volumes and this constantly trips our enterprise compliance monitors.

@manan728
Copy link

manan728 commented Jun 18, 2021

One more use case is when converting resource "aws_ebs_volume" "my_vol" to gp3, we want to now update the resource block to specify a new attribute called iops as aws_ebs_volume.my_vol.size * 3. (Also to consider the attribute iops is only used when the attribute type is "io1", "io2" or "gp3" which may be set by null reference https://www.terraform.io/docs/language/expressions/types.html#null).

@timblaktu
Copy link

timblaktu commented Jul 1, 2021

I have same issue/desire. I was wondering if a possible workaround is to create an input variable or local to hold the name of the resource, then refer to the variable in the resource definition as well as inside it, but this is not possible for a variety of reasons:

[tim-black-dev-env-tblack-dev-env-customiza]/home/tim.black/src/terraform-vsphere > cat main.tf
locals {
  jenkins_controller = "jenkins-tim"
.
.
}

resource "vsphere_virtual_machine" "${local.jenkins_controller}" {                                                                                                                                                                                                                          
  name             = local.jenkins_controller                                                                                                                                                                                                                                               
  resource_pool_id = data.vsphere_compute_cluster.R740.resource_pool_id       
.
.
.
}
[tim-black-dev-env-tblack-dev-env-customiza]/home/tim.black/src/terraform-vsphere > terraform validate
│ Error: Invalid resource name                                                                                                                                                                                                                                                            
│                                                                                                                                                                                                                                                                                         
│   on main.tf line 89, in resource "vsphere_virtual_machine" "${ ... }":                                                                                                                                                                                                                 
│   89: resource "vsphere_virtual_machine" "${local.jenkins_controller}" {                                                                                                                                                                                                                
│                                                                                                                                                                                                                                                                                         
│ A name must start with a letter or underscore and may contain only letters, digits,                                                                                                                                                                                                     
│ underscores, and dashes.                                                                                                                                                                                                                                                                
╵                                                                                                                                                                                                                                                                                         
╷                                                                                                                                                                                                                                                                                         
│ Error: Invalid string literal                                                                                                                                                                                                                                                           
│                                                                                                                                                                                                                                                                                         
│   on main.tf line 89, in resource "vsphere_virtual_machine" "${ ... }":                                                                                                                                                                                                                 
│   89: resource "vsphere_virtual_machine" "${local.jenkins_controller}" {                                                                                                                                                                                                                
│                                                                                                                                                                                                                                                                                         
│ Template sequences are not allowed in this string. To include a literal "$", double it (as                                                                                                                                                                                              
│ "$$") to escape it. 

@n-oden
Copy link

n-oden commented Jun 30, 2022

Having found myself here via a long and careful search, I'd like to note for the record that this is a duplicate of:

So for the benefit of the next person to go on this particular snipe hunt: no, you can't do this. No, it is not being worked on by hashicorp. No, it is probably not worth your time to try to implement it yourself in a PR (although if you do please tag me in it as an interested party). Yes, the only workaround is to create a variable or a local that contains the resource name and use that in all of the places where you'd want to refer to it.

@deeptechs
Copy link

deeptechs commented Dec 28, 2022

This will be very useful for applying DRY principle also... We are creating each resource block with an explicit naming then have to create same pattern in tag blocks' name field when using common tags approach. Any mistake on these parts doesn't cause any build failure but causes wrong/miss results in cost explorer calculation etc.. If there are automation solutions based on tags then it is also causing problems..

@heldersepu
Copy link

heldersepu commented Nov 22, 2024

I'm hopping the self can be extended to work outside the connection blocks...

Here is my use case:
I'm using the WiZ terraform provider to create service accounts:
https://docs.wiz.io/wiz-docs/docs/wiz-service-account

resource "wiz_service_account" "sa" {
  name              = var.account_name
  type              = var.sa_type
  ...
}

Next we need to enable secret rotation every 10 days.
They do have boolean argument rotate_secret in that resource that can help:

resource "wiz_service_account" "sa" {
  name              = var.account_name
  type              = var.sa_type
  ...
  rotate_secret     = timecmp(timeadd(timestamp(), "240h"), try(self.last_rotated_at, "3000-10-10...")) > 0
}

Code looks great but it won't work because self is not allowed there

@jbardin
Copy link
Member

jbardin commented Nov 22, 2024

@heldersepu,

I don't think self is going to work for something like this. The self object is intended to represent the final result of the resource after apply, but your case needs to evaluate rotate_secret before the plan is sent to the provider.

Normally given the ability of the resource to have a rotate_secret flag, the provider would implement some method to determine whether to set that or not, like an attribute that accepts a duration where it would trigger the rotation itself during plan.

The other option is to use a secondary resource like time_rotating where you control the interval entirely within terraform, essentially ignoring the last_rotated_at value.

@Clockwork-Muse
Copy link

I'm using the WiZ terraform provider to create service accounts:

Wiz locks their documentation behind an account system, it's not reachable.
(I have no words to express how that makes me feel about them)

Next we need to enable secret rotation every 10 days.
They do have boolean argument rotate_secret in that resource that can help:

This is an absolutely execrable API/resource design, because this means you have to manually re-run your deployment scripts. You don't want to do that, you want to run them once and then have whatever system is holding those keys manage them for you (if possible).

@heldersepu
Copy link

Normally given the ability of the resource to have a rotate_secret flag, the provider would implement some method to determine whether to set that or not, like an attribute that accepts a duration where it would trigger the rotation itself during plan.

Ye, 100% agree there, if this was Open Source I would add rotate_secret_frequency pass one value and all the magic happens internally, but unfortunately it is not the case..>

As far as the self intention to represent the final result of the resource after apply, my hope is that can be extended, I see no need why it needs to be exclusively after apply, it could be the know properties of the object/resource, if we call it at plan we get what we know from the state, if it is used in the connection block yes it gets the information after apply because that is when connections are executed

So the workaround to the limitation to the self is to use terraform_remote_state and code feels like an ugly hack

@heldersepu
Copy link

you have to manually re-run your deployment scripts

@Clockwork-Muse yes as long as you don't have CRON available yes it will need manual intervention
but in Linux/Unix that has been available for a long time:
https://en.wikipedia.org/wiki/Cron#Modern_versions

have whatever system is holding those keys manage them

translation: Pass the hot potato...
Got it, will bring that in my next meeting

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests