terraform-cdk icon indicating copy to clipboard operation
terraform-cdk copied to clipboard

Resource Refactoring - Moved State

Open skorfmann opened this issue 2 years ago • 2 comments

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

skorfmann avatar Nov 11 '21 21:11 skorfmann

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.

mirsilstan avatar May 31 '22 11:05 mirsilstan

Related tool that I stumbled upon this week: https://github.com/padok-team/tfautomv

ansgarm avatar Sep 23 '22 14:09 ansgarm

Is there any update on this? Version 0.15.0 still doesn't seem to support this.

sbkg0002 avatar Jan 19 '23 11:01 sbkg0002

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 :)

DanielMSchmidt avatar Jan 19 '23 14:01 DanielMSchmidt

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:

  1. Passing in resource constructs directly (from: myAwsInstanceResource)
  2. Support TerraformIterators (Related to the for_each case linked in the Terraform docs above)
  3. 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.

ansgarm avatar Sep 05 '23 08:09 ansgarm

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:

  1. 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.

DJAlPee avatar Sep 07 '23 08:09 DJAlPee

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.

github-actions[bot] avatar Nov 13 '23 01:11 github-actions[bot]