Skip to content
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

feat(core): stack.exportValue() can be used to solve "deadly embrace" #12778

Merged
merged 7 commits into from
Feb 1, 2021

Conversation

rix0rrr
Copy link
Contributor

@rix0rrr rix0rrr commented Jan 29, 2021

Deadly embrace (<3 who came up with this term) is an issue where a consumer
stack depends on a producer stack via CloudFormation Exports, and you want to
remove the use from the consumer.

Removal of the resource sharing implicitly removes the CloudFormation Export,
but now CloudFormation won't let you deploy that because the deployment order
is always forced to be (1st) producer (2nd) consumer, and when the producer deploys
and tries to remove the Export, the consumer is still using it.

The best way to work around it is to manually ensure the CloudFormation Export
exists while you remove the consuming relationship. @skinny85 has a blog
post
about this, but the mechanism can be more smooth.

Add a method, stack.exportValue(...) which can be used to
create the Export for the duration of the deployment that breaks
the relationship, and add an explanation of how to use it.

Genericize the method a bit so it also solves a long-standing issue about no L2 support for exports.

Fixes #7602, fixes #2036.


By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license

"Deadly embrace" is a great term but an annoying problem. The best
way to work around it is to manually ensure the CloudFormation Export
exists while you remove the consuming relationship. Adam has a blog
post about this, but the mechanism can be more smooth.

Add a method, `stack.exportAttribute(...)` which can be used to
create the Export for the duration of the deployment that breaks
the relationship, and add an explanation of how to use it.

Fixes #7602.
@rix0rrr rix0rrr requested a review from a team January 29, 2021 17:26
@rix0rrr rix0rrr self-assigned this Jan 29, 2021
@gitpod-io
Copy link

gitpod-io bot commented Jan 29, 2021

@github-actions github-actions bot added the @aws-cdk/core Related to core CDK functionality label Jan 29, 2021
@mergify mergify bot added the contribution/core This is a PR that came from AWS. label Jan 29, 2021
@rix0rrr rix0rrr changed the title feat(core): manually control exports to solve "deadly embrace" feat(core): manual control of Exports solves "deadly embrace" Jan 29, 2021
packages/@aws-cdk/core/README.md Outdated Show resolved Hide resolved
packages/@aws-cdk/core/README.md Show resolved Hide resolved
packages/@aws-cdk/core/README.md Outdated Show resolved Hide resolved
packages/@aws-cdk/core/lib/stack.ts Outdated Show resolved Hide resolved
*
* In case of a string, the string must not be a concatenation.
*/
public static reverse(x: any): IResolvable | undefined {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not 100% sure this has tons of value as a public API. Can we make it internal for now?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really. If we want to use it in other modules, it needs to be public (Adam's needed this when implementing a guard that reverses Tokens in CodeBuild, but ended up reimplementing himself).

Plus, it seems only fair that if the API to encode a token to a literal is public, the API to reverse that encoding should also be public.

@@ -92,6 +92,36 @@ nested stack and referenced using `Fn::GetAtt "Outputs.Xxx"` from the parent.

Nested stacks also support the use of Docker image and file assets.

### Breaking automatic references
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feels like this should be part of the section that describes cross references in the dev guide.

Maybe we can copy the contents from the dev guide to here and just add this as a subsection? And then also duplicate this to the dev guide?

rix0rrr and others added 4 commits February 1, 2021 09:28
Co-authored-by: Elad Ben-Israel <benisrae@amazon.com>
Co-authored-by: Elad Ben-Israel <benisrae@amazon.com>
Co-authored-by: Elad Ben-Israel <benisrae@amazon.com>
* - Don't forget to remove the `exportAttribute()` call as well.
* - Deploy again (this time only the `producerStack` will be changed -- the bucket will be deleted).
*/
public exportAttribute(exportedAttribute: any) {
Copy link
Contributor

@eladb eladb Feb 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed, I am wondering if we can make this slightly more generic and resolve #2036 along the way:

const importValue = stack.exportValue(attribute); // auto-name
const importValue = stack.exportValue(1234, { name: 'my-export-name' }); // since the value is not an attribute `name` is required

@eladb eladb added the pr/do-not-merge This PR should not be merged at this time. label Feb 1, 2021
@rix0rrr rix0rrr changed the title feat(core): manual control of Exports solves "deadly embrace" feat(core): stack.exportValue() can be used to solve "deadly embrace" Feb 1, 2021
@rix0rrr rix0rrr removed the pr/do-not-merge This PR should not be merged at this time. label Feb 1, 2021
@mergify
Copy link
Contributor

mergify bot commented Feb 1, 2021

Thank you for contributing! Your pull request will be updated from master and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork).

@mergify
Copy link
Contributor

mergify bot commented Feb 1, 2021

Thank you for contributing! Your pull request will be updated from master and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork).

@mergify mergify bot merged commit 3b66088 into master Feb 1, 2021
@mergify mergify bot deleted the huijbers/deadly-embrace branch February 1, 2021 14:17
@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: 3cbcf66
  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

- Make sure `stack2` no longer references `bucket.bucketName` (maybe the consumer
stack now uses its own bucket, or it writes to an AWS DynamoDB table, or maybe you just
remove the Lambda Function altogether).
- In the `stack1` class, call `this.exportAttribute(this.bucket.bucketName)`. This
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems the duplicate docs (readme + tsdoc) got out-of-sync during review/changes, e.g. this should be exportValue

@ghost ghost self-assigned this Feb 1, 2021
NovakGu pushed a commit to NovakGu/aws-cdk that referenced this pull request Feb 18, 2021
…e" (aws#12778)

Deadly embrace (<3 who came up with this term) is an issue where a consumer
stack depends on a producer stack via CloudFormation Exports, and you want to
remove the use from the consumer.

Removal of the resource sharing implicitly removes the CloudFormation Export,
but now CloudFormation won't let you deploy that because the deployment order
is always forced to be (1st) producer (2nd) consumer, and when the producer deploys
and tries to remove the Export, the consumer is still using it.

The best way to work around it is to manually ensure the CloudFormation Export
exists while you remove the consuming relationship. @skinny85 has a [blog
post] about this, but the mechanism can be more smooth.

Add a method, `stack.exportValue(...)` which can be used to
create the Export for the duration of the deployment that breaks
the relationship, and add an explanation of how to use it.

Genericize the method a bit so it also solves a long-standing issue about no L2 support for exports.

Fixes aws#7602, fixes aws#2036.

[blog post]: https://www.endoflineblog.com/cdk-tips-03-how-to-unblock-cross-stack-references


----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
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 contribution/core This is a PR that came from AWS.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

No longer accessing another stack's resource causes deadly embrace High level API for outputs?
4 participants