-
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
Nested stacks template will not be republished when a reference is added/updated #7059
Labels
@aws-cdk/core
Related to core CDK functionality
bug
This issue is a bug.
in-progress
This issue is being actively worked on.
p1
Comments
Nice catch! |
2 tasks
eladb
pushed a commit
that referenced
this issue
Apr 10, 2020
#7187) Fixes #6473 by centralizing all the logic to resolve cross-references into `App.prepare()`. This allows reasoning about the entire application once from a single code flow, dramatically simplified the algorithm and solved the issue at hand (and probably a handful of other issues). This logic is implemented in a function called `prepareApp` which is normally called from `App.prepare()` but if a `Stack` is created as a root (normally in unit tests, we invoke this logic from there to retain current behavior). This algorithm takes care of both resolving cross references and add template assets for nested stacks. This is because assets are currently addressed using CFN parameters, which means that when we adding them to the parent of a nested stack, the parent is mutated, so we need to rectify references again. To make sure this is done correctly, we always create assets in DFS order. Fixes #7059 Fixes #5888
mergify bot
pushed a commit
that referenced
this issue
Apr 16, 2020
#7187) Fixes #6473 by centralizing the logic to resolve cross-references and prepare nested stack template assets in `App.prepare`, which has a global view of the app and is the last prepare to execute before synthesis. This dramatically simplified reference resolution and allows dealing with nested stack assets only after all cross references have been resolved (the root cause for #7059). This logic is implemented in a function called `prepareApp` which is normally called from `App.prepare()` but if a `Stack` is created as a root (normally in unit tests, we invoke this logic from there to retain current behavior). This algorithm takes care of both resolving cross references and add template assets for nested stacks. This is because assets are currently addressed using CFN parameters, which means that when we adding them to the parent of a nested stack, the parent is mutated, so we need to rectify references again. To make sure this is done correctly, we always create assets in DFS order. All changes to the test snapshots stem from new asset IDs of nested stack templates, not the template themselves. The change is a result of the fact that the refactor caused the "Parameters" section to appear in a different place in the template, but the template itself is identical. Fixes #7059 by first resolving all references in the app and only then calculating the hash of the nested stack templates for their assets. Fixes #5888 but this was not verified.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
@aws-cdk/core
Related to core CDK functionality
bug
This issue is a bug.
in-progress
This issue is being actively worked on.
p1
When a user creates a NestedStack that reference a property in a sibling NestedStack, e.g:
The CDK will create an output of the property, the Topic in the picture, on the producer stack. And the corresponding parameter on the consumer stack.
The outputs and parameters are created in the
prepare
phase of the CDK. In this phase,prepare
is called on every construct in the tree, from leaves to root, ensuring that when a construct is being "prepared" it has all the knowledge it needs since all of its children have already been "prepared".Since sibling nested stacks does not have a parent-child dependency it is not guaranteed that the consumer stack will be prepared before the producer stack, the order is dependent on the order in which the children array is processed.
Nested stack templates are uploaded to S3 using the CDK assets mechanism. In order to avoid uploading an unchanged assets, a hash is calculate for each asset and is used as the object key in S3. The hash is calculated differently for every type of assets. For CloudFormation templates, the hash is calculated based on all the template elements, including outputs and parameters, ensuring that every change to the template will result in a new file uploaded to S3.
The nested stack template file hash is calculated in the stack
prepare
method:In the consumer producer example, the outputs and parameters on the respective stacks will be created when
prepare
is called on the consumer stack (the consumer stack is the one that needs the reference). This means that if the producer stack is prepared before the consumer stack, when the hash of the producer template file is calculated, it will not include the output, which means that the updated template will not be uploaded to S3, resulting in deployment failure.Simply put, the hash is not calculated on the final template.
Why didn't our integration tests catch this?
To traverse the tree from leaves to root in the prepare phase we create the topological sorting of the tree using:
Which means that the children in each level of the tree are processed from right to left.
Given the way the children are stored on the parent node and
get children()
implementation, the right to left order of the children array is opposite to the order in which the children were added to the node(1), which means that this code:Will result in the consumer stack being "prepared" before the producer stack.
Luckily, although not required, in most cases when referencing a property between resources, the producer resource will be created (and added to the children array) before the consumer resource. When the producer is created before the consumer the current logic works.
So how did this suddenly break?
As apart of the fix in aws/constructs#23, the topological sorting was changed from:
To:
Resulting in the children array processing order to change from right->left to left->right, causing the producer to be prepared before the consumer, breaking(2) the nested stacks integ test.
Since this change in the constructs module broke the CDK integ test we reverted the change and kept the original order.
(1) We store the children in a map based on their id (string), and retrieve the actual constructs using
Object.values(children)
which returns string keys in the order in which they were added to the object (see reference)(2) The integration test only fail because it was run as part of an integration test suite. The test suite that includes a test which produces the same template as the one produced by the test that fail, minus the outputs element. This resulted in the template with the outputs not being uploaded, failing the deployment. If the test was run independently, it would have passed :/ (AI, more extensive integ test for assets?)
The text was updated successfully, but these errors were encountered: