-
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
dynamic moved blocks #33236
Comments
Hi @archoversight! Thanks for sharing this use-case. Although you are right that there isn't a generalized mechanism for dynamically transforming instance keys using arbitrary expressions, you mentioned as part of your writeup "just being able to use the top resource name and having terraform figure out that its an array" and I'm not sure I'm understanding what you meant by that but note that the following is valid today: resource "example" "example" {
count = 3
}
moved {
from = example.old
to = example.example
} If neither of the addresses in a Is that what you meant by that part of your writeup, or did I misunderstand? Thanks again! |
I have a
To:
This did not work, terraform complained that it has to be a singular object, so I ended up writing:
For each of the resources. Granted, this was on an older version of terraform, not 1.4.6 (1.3 series), I just didn't get around to writing up the issue. I will try again in the newer versions. Edit: I will note that we have a lot of keys that are computed on the fly using locals/function transforms. That may also be causing issues for the moving of the resources wholesale. |
I think the fact that we're using contrived "example" names is making this a bit harder to follow and so we're talking past each other a little. The example I think the situation you described here is the one explored in Splitting One Module into Multiple, which shows the syntax for declaring that a resource has moved wholesale (with all of its instances unchanged) into a child module. Here's a reduced version of that example: module "x" {
source = "../modules/x"
# ...
}
moved {
from = aws_instance.a
to = module.x.aws_instance.a
} Because neither the What this cannot model is any situation where the instance keys changed in some systematic way at the same time as moving into a child module. For example, if you previously had |
+1 for dynamic moved blocks. 🤦 |
I don't want to put words into @archoversight's mouth, but I think the problem they are trying to solve is moving a # Parent Module
resource "example" "old" {
for_each = toset(var.something)
arg = each.key
}
module "new_module" {
source = "..."
for_each = toset(var.something)
something = each.key
} # New Child Module
resource "example" "new" {
arg = var.something
} and needing to move I don't believe there is currently a way of expressing this with the current moved {
from = example.old["something_a"]
to = module.new_module["something_a"].example.new
}
moved {
from = example.old["something_b"]
to = module.new_module["something_b"].example.new
}
moved {
from = example.old["something_c"]
to = module.new_module["something_c"].example.new
}
# ... If you could use the meta-arguments moved {
for_each = toset(var.something)
from = example.old[each.key]
to = module.new_module[each.key].example.new
} |
Thanks for the additional context! I think at this point we have a good understanding of what use-cases are missing today, and the remaining problem is that we have no known technical design with which to meet those use-cases. Internally a In practice that means that move resolution cannot evaluate arbitrary expressions, because expression evaluation happens during the plan phase and relies on the "planned state", which is what we call the internal-only state snapshot that Terraform gradually builds during planning -- the diff we show is comparing the planned state against the previous state. In practice I think that means that adding more flexibility here would require one of the following:
When we originally worked on this feature we could not find a sufficient design for option 2 that would not amount to essentially a rewrite of the entire runtime with a different design approach. There might still be a more feasible design out there waiting to be discovered, but my hunch is that path 1 is the more likely to succeed. We don't currently have a candidate design for either path though, so I think both are still on the table for someone to research. |
yet another barely useful feature by terraform. how do you think am I supposed to move thousands of resources from one resource to another as an author of internal module used by hundreds of configurations? |
@gleb-boushev-effem Thanks for the feedback. I acknowledge that it can be frustrating when a particular feature implementation does not contain the features you need to implement a solution. Just a reminder to please follow the Community Guidelines when posting. Thanks again! |
I also came here hoping for a better solution but what I'm currently doing is:
This isn't fast, ideal or anything but well it works. |
A bit late to the party, but perhaps for other people stumbling onto this discussion: given the technical architecture limitations, why not approach this from another angle? The If this module has a lot of users across other internal repos, one could consider a tool like mani to run this script as part of a mani |
I have a slightly different dynamic requirement from the moved block, which I believe is much simpler to implement, but absolutely follows the "Move all keys from resource A to resource B" ethos. Merge 2 separate resources doing the same thing into one. (Don't ask... Predecessor)
I get this error:
I know for a fact that the keys for each resources Perhaps it would be reasonable to read resource keys, and permit this behaviour, and for other, more complex state manipulation (where overlapping keys exist) a 2 stage move would work? Alternatively, if moved blocks have an Edit: Based on @apparentlymart 's write up - Op1 works here, assuming tf has access to state, prior to evaluating vars / locals. Apologies for the mention, not sure if allowed |
Hi @deitChi, For that example I suggest thinking of it as two moves along a chain of addresses, rather than as two independent moves to the same final location. moved {
from = aws_subnet.tn_subnet
to = aws_subnet.customer_subnet
}
moved {
from = aws_subnet.customer_subnet
to = aws_subnet.main
} Terraform will understand this as "first we renamed I understand that this chain of moves is not actually an accurate description of how this module historically evolved, but I think from Terraform's perspective this fake history is close enough to what you are really trying to describe that it would get the same effect. (Terraform has this requirement against ambiguity because it needs to be able to decide what to do if two objects try to move to the same address. The above example is using the "chained moves" rule which means that if there were conflicting instance keys between the first two resources then the one on "customer_subnet" would get preserved while the other one would be deleted. But as long as the instance keys are unique across both resources that detail won't matter, since every object can move to a unique new address.) |
It would be great to see something along the lines of Option 1, which would at least support basic conditional statements on variables known prior to plan (i.e. declare a moved block which is only required in some environments but not others) Because |
I've done some more testing, and annoyingly, chaining as described above doesn't seem to work # rt-moved.tf
moved {
from = aws_route_table_association.tn
to = aws_route_table_association.cust
}
moved {
from = aws_route_table_association.cust
to = aws_route_table_association.private
} Plan:
But all the 'cust' moved as expected. I do know the names explicitly, and it would be possible to manually transfer them - but it's not exactly my idea of a good time. |
Hi @deitChi, I'm sorry that didn't work out. Unfortunately I can't speculate as to why it didn't work without some more context. Since others have reported success using it I think we should treat this as a troubleshooting exercise rather than as a bug report for now -- though we can bring it back here as a bug report if we reveal one -- so I'd like to move discussion about that problem into a topic in the community forum where it's easier to get into the details of one person's situation without making this GitHub issue thread very long and creating notification noise for the folks already subscribed to it. If you do choose to open a community forum topic about this, it would help to also include information about where you've placed each of those declarations; my first theory here is that the Thanks! |
For time travellers, I'll include the discussion topic here, just in case it proves useful |
Hi, was there any update on this? I saw it's possible to use E.g.
becomes:
I had hoped to be able to include the following:
Thanks! |
Terraform Version
Use Cases
Moving large arrays of items is difficult and error prone
Attempted Solutions
Proposal
I am moving a large amount of resources with computed names into a new submodule and due to lack of having a dynamic way of calculating the moved blocks or just being able to use the top resource name and having terraform figure out that its an array, I have to manually parse the state file and create the moved blocks which is error prone, and doesn't work well when multiple people are working on the same codebase and new array items may be added between me generating the static moved blocks and the actual move of the resources to a submodule.
References
No response
The text was updated successfully, but these errors were encountered: