-
Notifications
You must be signed in to change notification settings - Fork 9.6k
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
resource-instance-scoped named local values #3267
Comments
Implementing something like what you described could potentially be allowed as long as the attribute in question is not computed, which is to say that its value is a known constant at plan time. Variables and interpolation functions applied to variables would fit into that rule, as could Currently the only place where there is special handling for plan-time-available values is in the special A tricky part of this is that it creates dependencies within the attributes of the resource themselves. While it's not true in your example, you could easily create a situation where there is a cycle of dependencies between attributes, which Terraform would then need to detect and report. This would likely require the interpolator or config processor to retain some more state than it does today. |
Maybe having Ain't saying it makes things easier for the actual implementation as I can imagine the amount of changes we'd have to make in the lifecycle & interpolation, but it's just some food 🍔 for thought 💭 . |
This would really be nice. Here's an example with resource "aws_s3_bucket" "example_org" {
bucket = "blog.example.org"
logging {
target_bucket = "logs_bucket"
target_prefix = "logs/${self.bucket}/"
}
}
resource "aws_s3_bucket" "www_example_org" {
bucket = "www.example.org"
website {
redirect_all_requests_to = "${aws_s3_bucket.example_org.bucket}"
}
} |
This is related to #5805 |
This would make a lot of our stuff cleaner - I don't need full-blown Variables only help a little with that, because you can't interpolate resource names either. |
yes, definitely, ${self.tags.Name} would be a common and useful case (in a remote-exec provisioner, for example, to netdom renamecomputer). |
@apparentlymart Are there plans to include this in 0.12 ? It would be quite useful. |
There are no plans to include this in Terraform v0.12. The scope of Terraform v0.12 is now closed, because its release process is already underway. As I described in my earlier comment, there are some design challenges to solve before this could be implemented. So far we've not had time to work on those, so work here is blocked until there is time to think through what restrictions are needed to make this behave in a deterministic way while still being useful, and how best to implement it since today the arguments inside a block can be evaluated in any order while implementing this feature would effectively make the arguments themselves a dependency graph, which is a considerably more complex design. We implemented local values several versions ago to address use-cases like this in a different way, by allowing repeated expressions to be hoisted out into a named symbol that can then be used in various locations: locals {
bucket_name = "blog.example.org"
}
resource "aws_s3_bucket" "example_org" {
bucket = "${local.bucket_name}"
logging {
target_bucket = "logs_bucket"
target_prefix = "logs/${local.bucket_name}/"
}
} The above is the recommended way to address this use-case for now. One thing that we cannot do with local values as currently implemented is instance-specific local values that can refer to resource "aws_s3_bucket" "example_org" {
count = 5
locals {
bucket_name = "example${count.index}"
}
bucket = "${local.bucket_name}"
logging {
target_bucket = "logs_bucket"
target_prefix = "logs/${local.bucket_name}/"
}
} The idea here would be that because this Reserving the |
…to repeat ourselves sadly
Any new news on this one? Let's say you have a bunch of these: resource "google_cloudbuild_trigger" "foo_bar" {
name = "foo-bar"
substitutions = {
_APP_NAME = "foo-bar"
}
} it's not really worth making a separate local var for each reference, but it would be very nice to be able to do |
Hi @wyardley! I think we must have a duplicate of this issue somewhere, because I know I've already posted what I'm about to write somewhere before, but since I can't find it I'll try to summarize it here. With the later addition of the resource "aws_subnet" "foo" {
for_each = {
for az in var.availability_zones : az => {
name = "private-${az}-subnet"
}
}
availability_zone = each.key
tags = {
Name = each.value.name
}
} For comparison, here's a hypothetical example using the unimplemented "local locals" design I mentioned in my earlier comment: # INVALID: This is a hypothetical example of an unimplemented language feature
resource "aws_subnet" "foo" {
for_each = toset(var.availability_zones)
locals {
name = "private-${each.key}-subnet"
}
availability_zone = each.key
tags = {
Name = local.name
}
} When I asked about it in whatever other issue we were discussing this in, the consensus seemed to be that using Of course, this is addressing the original request for local values that vary on a per-instance basis, whereas your example here is a singleton resource and therefore doesn't really need per-instance data, since you can already factor out any data that is either entirely constant or only relies on global objects into a top-level locals {
app_name = "foo-bar"
}
resource "google_cloudbuild_trigger" "foo_bar" {
name = local.app_name
substitutions = {
_APP_NAME = local.app_name
}
} I think then what you have in mind is just that you'd find it stylistically preferable to nest this local value inside its # INVALID: This is a hypothetical example of an unimplemented language feature
resource "google_cloudbuild_trigger" "foo_bar" {
locals {
app_name = "foo-bar"
}
name = local.app_name
substitutions = {
_APP_NAME = local.app_name
}
} The translation of this one to the resource "google_cloudbuild_trigger" "foo_bar" {
for_each = toset(["foo-bar"])
name = each.key
substitutions = {
_APP_NAME = each.key
}
} I'm not suggesting that this last example is desirable or a good idea, but of course the fact that there are already two different ways to write the same thing with existing language features naturally leads to de-prioritizing any new solutions to these problems in relation to other problems that don't have existing solutions. I should of course also address the other design idea that we were discussing in this issue (indeed, perhaps this other approach is why this one remains open even though we alerady have another for local locals) of allowing self-references inside the main body of a # INVALID
resource "aws_subnet" "foo" {
for_each = toset(var.availability_zones)
availability_zone = each.key
tags = {
Name = "private-${self.availability_zone}-subnet"
}
}
resource "google_cloudbuild_trigger" "foo_bar" {
name = "foo-bar"
substitutions = {
_APP_NAME = self.name
}
} Although I can see the appeal of this language design, I don't think it's really practical to implement it because it would effectively require Terraform to build a dependency graph of all of the individual arguments inside a I think the "local locals" design is more likely, because it has a clearer execution model: evaluate the special Terraform Core's design doesn't really make either of these easy today, because it treats |
I think I did probably come across some other threads about this. I guess on an intuitive level, it feels like it should be possible to refer to a (non-computed) attribute of the current object, but I can understand that seeming like it should be easy doesn't make it so, and I think I understand what you're saying about why it would be challenging. So, to me, the self reference reads the cleanest / is the easiest to understand. I like the locally scoped locals approach ok, and would use something like that for this situation if it existed, though I imagine it might be confusing to people who are used to terraform's current implementation of locals, which is maybe too flexible. |
Ok, so my example was intentionally oversimplified, and yes, in that case, So now I don't need resource "google_cloudbuild_trigger" "app1" {
name = "app1"
substitutions = {
_APP_NAME = "app1" // what I'm wanting to use `self.name` or `local.app_name` for
_FOO = "bar"
}
}
resource "google_cloudbuild_trigger" "app2" {
name = "app2"
substitutions = {
_APP_NAME = "app2" // ditto
_QUX = "widget"
}
some_other = true
} If I'm not mistaken, there's no convenient way when not using iteration to use a top level local var to do the thing I'm proposing here, since if I built an array, I'd have to access it by numeric index, and if I built a hash, I'd have to use the name to refer to the name, which wouldn't help. locals {
app_names = {
app1 = "app1"
app2 = "app2"
}
} obviously, this is still an oversimplified and somewhat contrived example, but does that help explain how a scoped local var would be useful in a scenario like this in a way that a top level one wouldn't be? |
Revisiting this much later, I think the other issue I was thinking about when I mentioned a duplicate above was #20672. Although that other one is actually newer than this one, I'm going to close this one as a duplicate of that one just because there's some further discussion in the other one about how the implementation of resource Thanks! |
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. |
Sometimes I find that I repeat myself in resources. For example:
I was thinking it would be great to have self references here, as sometimes these interpolations can be somewhat complex and I end up having to copy and paste. For example:
Not sure if it's possible to do this in a nice manner at the moment?
The text was updated successfully, but these errors were encountered: