-
Notifications
You must be signed in to change notification settings - Fork 4k
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
Simplify or clarify how to refactor an CDK codebase #4733
Comments
Can you elaborate why does it make refactoring impossible? |
I think I need to clarify what I mean by refactoring. In this case I'm just talking about moving your resources into and out of constructs or breaking up a construct into smaller constructs. The end result of this refactoring process should be that In the current situation resources are renamed, thus removed and new ones are created. Think of databases. |
I agree, @abelmokadem has a valid point. Would be great if this was easier. |
Thanks for the clarification. Unfortuntelly, we don't have good solution to this problem that will not require you to explicitly specify absolute logical IDs to all resources that you define, and as you observed, this will dramatically hinder composability and reusability. But we can talk about a few things:
This has been something we have discussed for over a year as we designed the CDK, and possibly the biggest challange we had in designing the programming model. I can't say we have the perfect solution, but we could not come up with a better solution. If anyone has ideas, we would love to hear from you, but we can't compromise compability. It's a key design tenet that makes CDK possible. EDIT: added reference to #2282 |
I have somewhat of an idea. Please let me know if this absolutely can't work. I also managed to get myself confused somewhere down the road, but I still think it could work. It could be a big change for aws-cdk, but for end users it could just be a matter of creating a stack with In short:
When running
When running
|
When will the UUID be generated? It has to be stable across synths, so we can't generate it at runtime. |
@eladb it is generated only when cdk can't find the CDK path in the cloudformation template of the currently deployed stack. cdk deploy
|
How do we know the uuid of a resource from the deployed stack? We need a stable address/identity in order to correlate between the resource in your code and the deployed resource. |
You find the uuid by looking for the cdk metadata field. You can use this field to correlate between the resource that is in your code.
If this path does not exists in both the mapping file and in the deployed stack, it means you are creating a new resource. |
But the problem is that if you refactor your code, this path will change and you "lose" your connection to the actual resource. |
That is what the mapping file is for. If you treat refactor as a separate action, then you can create a mapping.json
This action will simply update the cdk path metadata in cloudformation. That is all it should do if there are no changes to the stack but you moved a resource. |
You could even consider making a part of cdk deploy to make things stateless. I haven't thought of how to do that. You would have to add additional metadata to keep track of which "refactor" was executed and which was not. |
As another CDK user/contributor I think this mapping file really pushes against the grain of CDK and CloudFormation (CFN). In my mind CFN owns the stateful management, I feel like this mapping file starts to be an artifact I might need to preserve. For example, if you make a refactor and you need to promote this from dev to perf to prod, who validates this mapping file in each step and how long do I need to keep it? In VCS or out? Counter proposalIf I take a little inspiration from state file management in other systems (see below for TLDR). I like the direction of a stateful boolean. In my head instead of stateful, I think about this as a "root" namespace where the rule of logical IDs are changed. In this namespace the logical ID is the result of the name/ID provided in the constructor and the hash of the properties that cause destroy/recreate (no longer is CDK path in the logical ID here and we have to manage name length). The user/consumer now owns the responsibility of ensuring unique names for the "root" namespace and if you change a property that causes a destroy/recreate the logical ID will clearly indicate that and diff will detect it. state file management in other systems TLDRIf we look across the landscape this is why Terraform maintains state externally and it's also why if I corrupt my statefile it can be very hard and potentially impossible to restore. However, because the user accepts the responsibility we now have the ability manually manipulate the state file and move resources between modules. |
@abelmokadem are you aware that we already have support for renaming logical IDs globally, exactly for the refactor use case. It's almost exactly like your mapping file, but in code (and of course, if you want you can load a rename map from a file). |
For posterity, people can also completely override how resource logical IDs are allocated by subclassing I am closing this for now. Please reopen if you feel you don't have sufficient tools to be able to control your logical names in a refactor. |
After some refactoring, I have so many Here's a draft of the idea:
const subnet = new PrivateSubnet(this, "Private", { ... });
rename({ element: subnet.node.findChild("NATGateway"), oldId: "FooBarVpcSubnetNATGatewayABCD1234") })
|
@eladb I know this is an old issue, but do you have an example we can reference for how to combine Much appreciated. EDIT
In my case, I did some refactoring which moved the DDB table into its own construct. |
Hmm, I couldn't get that to work. I was attempting to move a table from the stack contstuct into its own construct. Then added:
Where the first param is the logicalid generated by the most recent change, and second param is the historical logicalid. |
This is just to start a discussion, but currently I'm finding it really hard to refactor an AWS CDK codebase because of the CloudFormation resource names. Is it possible to create a separation between the names and the structure of the code. I understand that this is at the core of aws-cdk and it allows us to create reusable constructs, but this also makes refactoring nearly impossible.
The text was updated successfully, but these errors were encountered: