-
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 for_each #21922
Resource for_each #21922
Conversation
a77e9a5
to
931302e
Compare
This is great!
I think lists and sets (other than strings) should be supported before this gets released; I'm not as sure about how to implement sets (we'd either need to convert them to lists so we have an index, or have users use the I'm also curious about the errors that aren't being surfaced to the user - I wouldn't mind spending some time looking into that! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good so far! 🎺
How are the resources managed in the state file? Is it still a array like with count or are the created resources actual mapped to their keys in the state file? |
133bbe9
to
43c3329
Compare
@Skaronator Here's a statefile showing instances created with
|
@pselle Ah thats great! So b wouldn't get recreated when I remove a from the map. (Since its now on Index 0 instead of 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me! 🎉
configs/resource.go
Outdated
if r.Count != nil { | ||
diags = append(diags, &hcl.Diagnostic{ | ||
Severity: hcl.DiagError, | ||
Summary: "Invalid config, cannot use count and for_each in same block", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The sentence fragment here made me trip over reading this sentence a bit. 😖
Most of our "modern" error messages try to start with a concise statement of the broad problem as the summary and then elaborate more in the detail. Since this is a situation where it's the combination of two things that is invalid rather than one thing, the usual "Invalid " summary won't work here, but maybe something like this?
Error: Invalid combination of "count" and "for_each"
<source snippet>
The "count" and "for_each" meta-arguments are mutually-exclusive, because each one chooses
a different identifier type for the resource instances.
(This term "meta-arguments" has always felt a little weird to me, but that's what it's called throughout the documentation and so hopefully using that terminology in the error message will help users find further documentation about these features if they are unsure how to proceed.)
Sorry I didn't catch this on the previous review, but it only just occurred to me while I was staring some similar code... I think the terraform/terraform/node_resource_abstract.go Lines 188 to 189 in 1a89165
Without this, Terraform wouldn't notice that a particular object is referenced in the I'm sorry if I missed something somewhere else in this diff that's catching that. This sort of thing unfortunately tends to be quite awkward to test, because without it what we have is a race condition and thus not a deterministic test failure. We have two existing strategies for testing this:
|
@apparentlymart Very good note -- I'll do some digging to check on this/make sure it works/fix it if it doesn't. |
Looking at this again with fresh eyes, I remember there is a third testing strategy out there:
|
Hi, Are we really able to use for_each inside resource. I am using terraform 12.4 but cannot use for_each to create multiple azure network interfaces. Error : on main.tf line 81, in resource "azurerm_network_interface" "vm_instance_nic": The name "for_each" is reserved for use in a future version of Terraform. Thanks, |
@i870495 This feature hasn't been merged yet nor has it been released. |
@Skaronator - Thank you !!! |
@apparentlymart Re: references The following is a simple example demonstrating referencing another resource in the expression passed to
I've added a reference in the testdata used by Context2Plan; I'd be interested in more info on how to introspect there, reading some of the other tests, it's not very clear how to introspect (as when I started using I could of course add to the abstract node ref but without proof that it's necessary, I'm not inclined to do so. |
If the dependency is not present, Terraform will think it can work on both of those resource blocks concurrently, so it would be undefined which order they would resolve in. With resources that resolve essentially instantly, it's quite possible for them to complete in the right order just by accident, unfortunately. One way to verify this without writing any further code would be to
The important part of this is the dependencies for
This shows that (in the quick example configuration I wrote using (You will likely see multiple |
For PR visibility: added the change (and a test) to make sure edges created by references are caught. |
07a65d6
to
a2e9738
Compare
@tmccombs Great changeset! You figured out what I hadn't as yet -- the bits of count that hadn't yet been paralleled in |
3bd0ec3
to
5186f6c
Compare
Yes, please include my changes in this PR, I've signed the CLA. And thanks for catching the panic and extra file I left in there. If you want to update the data-source documentation, that would be great. |
Apologize if it was clarified before but is it planned to add |
@defo89 It was not asked before, so your question is welcome! No, that is not planned (to add |
d520b0f
to
1b25cb7
Compare
Very excited to see this merged! Two questions:
|
And then you can select with
|
I'm not sure what you mean. with count you can access the computed attributes of a resource like
The one reason I can think of is where you actually want to create n copies of a resource, with almost identical config. |
Ah, whoops, my first question was a bit ambiguous. What I meant is that the resource "random_integer" "num_instances" {
min = 1
max = 3
}
resource "aws_instance" "example_3" {
# This is not allowed
count = random_integer.num_instances.result
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
} The example above will fail as I'm trying to reference a computed output in a |
When you apply the Not the best workaround but it works. |
This is exactly the feature I was looking for! What a coincidence that it got merged just now :) Unfortunately it fails if
Implementing the suggestion, I get a different error:
Declaring the map inline, i.e.
results in a slightly different error:
Any suggestions highly appreciated. |
Does self work with a resource with count?
…On Sun, Jul 28, 2019, 15:53 Nick Zavaritsky ***@***.***> wrote:
This is exactly the feature I was looking for! What a coincidence that it
got merged just now :)
Unfortunately it fails if self is used within a resource spawned with
for_each:
variable "do_token" {}
variable "private_key" {}
variable "ssh_fingerprint" {}
provider "digitalocean" { token = var.do_token }
variable "compute_cluster" {
default = [1,2,3,4,5] # makes it possible to destroy specific instances when scaling down
}
resource "digitalocean_droplet" "compute" {
for_each = zipmap(var.compute_cluster, var.compute_cluster)
image = "ubuntu-18-04-x64"
name = "compute-${each.key}"
region = "ams3"
size = "s-1vcpu-1gb"
ssh_keys = [ var.ssh_fingerprint ]
connection {
host = self.ipv4_address
user = "root"
type = "ssh"
private_key = file(var.private_key)
}
provisioner "remote-exec" {
inline = []
}
}
on app.tf line 133, in resource "digitalocean_droplet" "compute":
133: host = self.ipv4_address
Because digitalocean_droplet.compute has "for_each" set, its attributes must
be accessed on specific instances.
For example, to correlate with indices of a referring resource, use:
digitalocean_droplet.compute[each.key]
Implementing the suggestion, I get a different error:
Error: Reference to "each" in context without for_each
on app.tf line 132, in resource "digitalocean_droplet" "compute":
132: host = digitalocean_droplet.compute[each.key].ipv4_address
The "each" object can be used only in "resource" blocks, and only when the
"for_each" argument is set.
Declaring the map inline, i.e.
resource "digitalocean_droplet" "compute" {
for_each = { 1 = 1 }
results in a slightly different error:
Error: Missing resource instance key
on app.tf line 132, in resource "digitalocean_droplet" "compute":
132: host = self.ipv4_address
Because digitalocean_droplet.compute has "for_each" set, its attributes must
be accessed on specific instances.
For example, to correlate with indices of a referring resource, use:
digitalocean_droplet.compute[each.key]
Any suggestions highly appreciated.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#21922?email_source=notifications&email_token=AATMRHSXRRP4BP5SOSFUDKTQBYIMNA5CNFSM4H373Z7KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD27HJHA#issuecomment-515798172>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AATMRHUFHWVCOI773RCNSU3QBYIMNANCNFSM4H373Z7A>
.
|
Yes it does! AFAIK |
Sounds like a bug to me. The logic for self is probably just missing the
foreach support.
…On Sun, Jul 28, 2019, 17:26 Nick Zavaritsky ***@***.***> wrote:
@tmccombs <https://github.com/tmccombs>
Does self work with a resource with count?
Yes it does! AFAIK ‘self’ is the only option if it is necessary to use
(current) resource properties in resource definition. If you attempt
‘resource[count.index]’ instead, a circular dependency is reported, since
terraform is unable to figure out that only the current resource is being
referenced, not the whole set.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#21922?email_source=notifications&email_token=AATMRHV3HDRMXVY6JCLDKGDQBYTJVA5CNFSM4H373Z7KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD27IWMY#issuecomment-515803955>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AATMRHWUUJ67LYFLQROIZSTQBYTJVANCNFSM4H373Z7A>
.
|
I think this should fix it: #22230 |
@tmccombs Thank you for awesome work, Unfortunately, I am hitting further issues. I will give a brief summary below. Later I will provide a minimal terraform file to reproduce.
I tried deploying new compute nodes, and it works. However if I remove one, say
Error message:
Used to work with |
A minimal terraform file to reproduce the issue with inconsistent plan:
To reproduce: If I remove |
Hi @mejedi, thanks for the feedback! Can you please open a new issue with this reproduction case? It's easy to miss comments on closed issues and merged PRs. Thank you. |
Question: what is the equivalent of |
@brikis98 I was wondering the same, found the answer here: #21533 (comment) |
@ilyasotkov Got it, 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. 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. |
Allow instances to be created according to a map or a set of strings. Closes #17179
Things that won't work: