terraform-cdk
terraform-cdk copied to clipboard
Resource Refactoring - Moved State
Community Note
- Please vote on this issue by adding a 👍 reaction to the original issue to help the community and maintainers prioritize this request
- Please do not leave "+1" or other comments that do not add relevant new information or questions, they generate extra noise for issue followers and do not help prioritize the request
- If you are interested in working on this issue or have submitted a pull request, please leave a comment
Description
With Terraform v1.1 there will be a new addition targeting refactorings: moved blocks
moved {
from = aws_instance.a
to = aws_instance.b
}
This allows moving the state of resources via configuration. Which means, stateful refactorings can become a part of the development cycle - including testing, reviews and multi stage deployments.
That's generally quite interesting for us, since we're generating our resource names dynamically. For complex stacks with multiple levels of constructs, it will get challenging to identify a resource which gets moved around just by looking at the code. That's where the new move
block could help us to provide a better UX to deal with this.
Once Terraform v1.1. gets released, the moved
block can be used immediately via escape hatches. How exactly moved
might look like as a full feature on our end is yet to be determined.
References
- https://github.com/hashicorp/terraform-cdk/issues/1102
- https://github.com/hashicorp/terraform-cdk/issues/1091
- https://github.com/hashicorp/terraform-cdk/issues/219
- https://github.com/hashicorp/terraform-cdk/issues/1739
For whoever needs it, this is an example in Java:
var movedResources = Map.of(
"fromA", "toB",
"fromX", "toY",
"fromP", "toR"
);
var movedBlocks = movedResources.entrySet().stream()
.map(entry -> Map.of("from", entry.getKey(),"to", entry.getValue()))
.collect(Collectors.toList());
addOverride("moved", movedBlocks);
It creates an array of multiple code blocks which is then added as an override in the TerraformStack class.
Related tool that I stumbled upon this week: https://github.com/padok-team/tfautomv
Is there any update on this? Version 0.15.0
still doesn't seem to support this.
We now have some documentation around how to refactor in cdktf: https://developer.hashicorp.com/terraform/cdktf/examples-and-guides/refactoring
We still have no support for move blocks yet, but we are open to PRs on that topic :)
The Terraform docs contain a list of use-cases that the moved block can be used for: https://developer.hashicorp.com/terraform/language/modules/develop/refactoring
In a first iteration for a moved block primitive, we should focus on supporting changing the ids of resources. One common case in CDKTF projects is moving a resource into a nested construct which will change its id and therefore require a state migration which can be simplified using a move block.
A very rough API would be to introduce a TerraformMoved
that takes two manually specified refs:
new TerraformMoved(this, "my_moved_block", {
from: ref("aws_instance.test"),
to: ref("aws_instance.construct_id_BDA233_test")
})
Note: It is currently hard to figure out the hash ("BDA233") – maybe there are some quick wins we can help the user with by exposing that hashing algorithm somehow (if it only depends on the construct path). Alternatively allowing to pass resource constructs will get rid of the requirement to first run a plan only to find the new resource id.
As future ways to improve this we can support:
- Passing in resource constructs directly (
from: myAwsInstanceResource
) - Support TerraformIterators (Related to the
for_each
case linked in the Terraform docs above) - Support Terraform Modules by passing them directly (Also described in the docs)
This could be a bare minimum primitive for the moved
block on which we could build further layers with nicer UX.
Note: It is currently hard to figure out the hash ("BDA233") – maybe there are some quick wins we can help the user with by exposing that hashing algorithm somehow (if it only depends on the construct path). Alternatively allowing to pass resource constructs will get rid of the requirement to first run a plan only to find the new resource id.
This could be simplified for most (?) cases, when it's possible to assign a reference to the construct to the to
property. My suggestion to the input params of your TerraformMoved
:
interface TerraformMovedInput {
from: string | string[];
to: string | Construct;
}
With an string array in from
, there could be multiple "old" ids be added.
Does this new construct (?), actually need an ID?
As future ways to improve this we can support:
- Passing in resource constructs directly (
from: myAwsInstanceResource
)
Is it hard to add a property on construct level and use this for generating the moved
blocks? That would be the very best solution in my opinion.
To avoid naming collisions, these kind of parameters (there is also import
available now!) should to bundled into a CDKTF "themed" property. This approach would abstract terraform behavior, but would make the developer experience way better.
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've 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.