-
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
fix(core): cross-stack references to NestedStack list values produces invalid outputs #32575
fix(core): cross-stack references to NestedStack list values produces invalid outputs #32575
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly nits about coverage, LGTM overall though 👍
packages/@aws-cdk-testing/framework-integ/test/core/test/integ.nested-stack-references.ts
Outdated
Show resolved
Hide resolved
packages/@aws-cdk-testing/framework-integ/test/core/test/integ.nested-stack-references.ts
Outdated
Show resolved
Hide resolved
… invalid outputs Referencing a list attribute of a resource defined within a NestedStack synthesizes successfully but the nested stack will fail deployment with the error: ``` Template format error: Every Value member must be a string. ``` This prevents deploying resources such into NestedStack instances if a reference to that resource's list attribute needs to be referenced in a cross-stack context. For example, deploying a `InterfaceVpcEndpoint` instance in a nested stack and attempting to reference its `vpcEndpointDnsEntries` property within a different stack will cause this error. To fix this issue, a similar strategy to `exportStringListValue` is used to join the reference's values into a string and expose that value as the output from the nested stack. The reference to the serialized value is then re-exported as normally needed to hoist it to the top-level parent stack. The final reference that imports the value is then re-written to also deserialize the imported string back to the original list. fixes aws#27233 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
8219bff
to
28721e3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks for the changes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry for the super late review @brandondahler. my main concern is the change between Reference
and Intrinsic
. Let's figure that out, and then I'm happy to send this one into main!
@@ -321,17 +334,23 @@ function createNestedStackOutput(producer: Stack, reference: Reference): CfnRefe | |||
* | |||
* Will create Outputs along the chain of Nested Stacks, and return the final `{ Fn::GetAtt }`. | |||
*/ | |||
export function referenceNestedStackValueInParent(reference: Reference, targetStack: Stack) { | |||
export function referenceNestedStackValueInParent(reference: Reference, targetStack: Stack): Intrinsic { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why are we returning an Intrinsic
here? it should be a Reference
right.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have to use Intrinsic
here because we're reversing the tokenized list via Fn.split
(line 354). We're having to use Fn.split
because we're having to do a join when creating the output within the nested stack since the output cannot be a list.
Prior to this update, the values returned from here were only able to reference strings and therefore were just outer stack Reference
's to the nested stack's resource attribute. After this update, the values returned from here may either reference a string or a list. In the list case, it is an implementation detail of this method that we're having to re-split the Reference
on the nested stack's resource out to its list representation again (and therefore are returning an Intrinsic
instead).
Ultimately the choice from a type perspective was either returning an Intrinsic
or an IResolvable
, either would be correct per the type hierarchies involved.
@@ -260,7 +269,7 @@ function generateExportName(importStack: Stack, reference: Reference, id: string | |||
return prefix + localPart.slice(Math.max(0, localPart.length - maxLength + prefix.length)); | |||
} | |||
|
|||
export function getExportable(stack: Stack, reference: Reference): Reference { | |||
export function getExportable(stack: Stack, reference: Reference): Intrinsic { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i understand that this is a private function but I am concerned about the downgrade from returning a Reference
to an Intrinsic
. i want to learn more about why thats something you've deemed necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This ultimately changed because referenceNestedStackValueInParent
changed, see that comment for more details. TL;DR Fn.split
returns an Intrinsic (not a Reference
) when untokenized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @brandondahler!
Thank you for contributing! Your pull request will be updated from main and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork). |
This pull request has been removed from the queue for the following reason: The pull request can't be updated You should look at the reason for the failure and decide if the pull request needs to be fixed or if you want to requeue it. If you want to requeue this pull request, you need to post a comment with the text: |
Thank you for contributing! Your pull request will be updated from main and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork). |
@Mergifyio requeue |
❌ Command disallowed due to command restrictions in the Mergify configuration.
|
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
Thank you for contributing! Your pull request will be updated from main and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork). |
Comments on closed issues and PRs are hard for our team to see. |
Issue
Closes #27233.
Reason for this change
Referencing a list attribute of a resource defined within a
NestedStack
synthesizes successfully but the nested stack will fail deployment with the error:This prevents deploying resources into a
NestedStack
instance if a reference to one of that resource's list attribute exists within a cross-stack context. For example, deploying aInterfaceVpcEndpoint
instance in a nested stack and attempting to reference itsvpcEndpointDnsEntries
property within a different stack will cause this error.See new integration test at
packages/@aws-cdk-testing/framework-integ/test/core/test/integ.nested-stack-references.ts
for minimal reproduction.Description of changes
A similar strategy to
exportStringListValue
is used to serialized the reference's values into a string and expose that value as the output from the nested stack. The reference to the serialized value is then made exportable as normally needed to hoist it to the top-level parent stack. The final reference that imports the value is then re-written to also deserialize the imported string back to the original list.The return types of some internal methods were modified to handle the fact that core/lib/private/refs.ts's
getExportable
no longer necessarily returns a Reference. This was needed because an exportable may now be a value derived from a reference instead of only a direct reference.Describe any new or updated permissions being added
N/A
Description of how you validated changes
Checklist
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license