-
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
feat(cli): decouple bootstrap stack resource discovery from CF stack name #11952
Conversation
ToolkitInfo served 2 functions: 1. locate CDKToolkit stack and it's parameters. This is used when bootstrapping. 2. locate bootstrapped resources, such as S3 asset bucket and ECR registry. This is used when deploying. This change extracts CDKToolkit stack related function to own ToolkitStackInfo class. This prepares code for a future change to the way deployment locates bootstrapped resources.
…ts and ECR `cdk deploy` needs to know where to put assets and previously was using CDKToolkit stack's outputs to find it. This ties resource discovery to a CloudFormation stack name, which has following disadvantages: - Bootstrap stack can't be depoyed via StackSet, because stacks created in target accounts have random names - Bootstrapping must be done with CloudFormation only This changes asset resource discovery to be done via qualified SSM Parameters.
Previously `cdk deploy` was locating CDKToolkit stack by name. Sometimes name is not known upfront, for instance when bootstraping is done via StackSets. Preivous commits in this patch series changed bootstrap stack to create SSM parameters with same value as a stack output. This patch changes lookup mehanism to use SSM and qualifier to locate assets buckets and ECR registry. With known qualifier we know by convention exact SSM parameters to lookup. This decouples discovery from CF stack names. It even allows bootstrap to be done not by CF if user desires so.
@rix0rrr , would you mind to take a look if you have time? |
e7a1f22
to
468dbb6
Compare
cdk deploy reads SSM parameters created by bootstrap stack
Did not look at the code yet. Thanks for writing a comprehensive PR description, that really helps a lot. I immediately have some things to say about this:
Well no. For For LegacySynthesized stacks... I guess we don't support bootstrapping via stacksets. We could try and support this by scanning the stacks in the account and finding the bootstrap stack between all available ones, but I don't necessarily thing that's the best way of going about it. Switching to DefaultSynthesized stacks would be better.
We can't do that.
Not sure I'm into this. We should strive to keep the CLI simple. The current mechanism for this is to have the app specify the bootstrap qualifier, and this can be done either in code or using context (either, again, in code, or in |
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 for submitting, but I think I disagree with the premise of the changes made here.
@rix0rrr , thanks for looking into this. This change focuses on a newly synthesized stacks, leaving legacy stacks out of scope. I am happy to make changes, leaving legacy behaviour as is. My follow up comments are in the context of using it with new synth only.
In theory yes, but for some reason current code uses CDKToolkit output, not Cloud Assembly asset url to upload: aws-cdk/packages/aws-cdk/lib/assets.ts Line 82 in 9417b02
I didn't want to change that behaviour. Another place where S3 bucket information is used is during template body upload if it is not set in cloud assembly:
If you think, that cloud assembly should be authoritative for asset location, then it is likely that there is no need to make use of Only thing left would be version check, which can be switched to existing SSM parameter.
I agree. Once we find a good way to move forward, I'll make sure that new behaviour kicks in only if flag is not specified.
My understanding is that qualifier can be set during synth time (via context or in code), but is never persisted in cloud assembly as a first class value. Therefore when we come to |
@rix0rrr , I'd appreciate your input on this. |
It's true. Both of these should not happen in case of a DefaultSynthesized stack, but the code won't know beforehand whether that's true or not. I wonder if it would be helpful to return a dummy instance of If any of its members are called (such as In case of a DefaultSynthesized stack, none of those members should ever need to be called (as all the information will be in the cloud assembly already) and so it's fine that we returned a dummy object. Feels that is the best way to marry legacy deployments and modern deployments. What do you think?
Hah! You are correct, I apparently didn't reason that all the way through 🤣 . I suppose adding the name of the SSM parameter to the Cloud Assembly manifest is the thing to do here. I'd prefer that over just the qualifier itself as it's functionally equivalent, but leaves more decisions open to the CDK App & the related synthesizer (which is where we prefer them). There are like 2 or 3 locations where we have this version number in the manifest. |
This PR also probably closes #9053 |
This is a best course of action IMHO, but I wasn't confident enough in making change to cloud assembly schema and bumping version. If you think it's relatively easy I can try. |
Maybe remove version check all together? Remove |
I strongly believe in giving accurate and actionable error messages as much as we can. Having to replace it with a wishy-washy "something is wrong and it might be this" seems suboptimal. Let me try and get you started... |
I added a commit to switch over to an SSM parameter name in the Cloud Assembly. I think the next step would be to have I think that should do it. Feels like most of the other changes introduced in this PR could be backed out again. Let me know if I missed something! |
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
One of the goals of the "modern synthesis" was to couple the deployment only to the naming of the resources in the bootstrap stack, not the bootstrap stack itself. We *mostly* had that correct, but missed it in one aspect: because the modern bootstrap stack template is still in flux, the CLI does a version check against it; however, it currently performs that version check against the Stack Output of the bootstrap stack, and in order to do that has to look up the bootstrap stack and inadvertently became tied to its name again. This was identified by @redbaron in #11952. In order to be able to do that version check without the CLI needing to look up the bootstrap stack, the CLI looks up the SSM parameter with the version number directly. The following changes enable that: - Encode the SSM version parameter name into the Cloud Assembly (this is the magic that decouples from the bootstrap stack name). - In order to be able to read the SSM parameter, the Deploy Role needs `ssm:GetParameter` permissions to it. Addition of these permissions requires a bootstrap stack version bump. - `ToolkitInfo.lookup()` now always returns an object (even if the lookup failed), and that object serves as a cache for the SSM read, so that we don't have to re-fetch the parameter for every asset. - Add an integration test that verifies we can deploy a modern-synthesized application without knowing the bootstrap stack name. - Various unit test changes to account for the new API. There's one little edge case we need to deal with: bootstrap stack template v5 includes the `ssm:GetParameter` permissions that we need to check the bootstrap stack version in an out-of-band way... but if we're still on bootstrap stack v4 we won't have the permissions yet to read the version! If we detect that happens (`AccessDeniedException`), we'll still formulate that into an "upgrade" message that's as accurate as possible, using the bootstrap stack template's Output version if found, or a more generic message if not. BREAKING CHANGES: users of modern synthesis (`DefaultSynthesizer`, used by CDK Pipelines) must upgrade their bootstrap stacks. Run `cdk bootstrap`.
Superseded by #12594 |
) One of the goals of the "modern synthesis" was to couple the deployment only to the naming of the resources in the bootstrap stack, not the bootstrap stack itself. We *mostly* had that correct, but missed it in one aspect: because the modern bootstrap stack template is still in flux, the CLI does a version check against it; however, it currently performs that version check against the Stack Output of the bootstrap stack, and in order to do that has to look up the bootstrap stack and inadvertently became tied to its name again. This was identified by @redbaron in #11952. In order to be able to do that version check without the CLI needing to look up the bootstrap stack, the CLI looks up the SSM parameter with the version number directly. The following changes enable that: - Encode the SSM version parameter name into the Cloud Assembly (this is the magic that decouples from the bootstrap stack name). - In order to be able to read the SSM parameter, the Deploy Role needs `ssm:GetParameter` permissions to it. Addition of these permissions requires a bootstrap stack version bump. - `ToolkitInfo.lookup()` now always returns an object (even if the lookup failed), and that object serves as a cache for the SSM read, so that we don't have to re-fetch the parameter for every asset. - Add an integration test that verifies we can deploy a modern-synthesized application without knowing the bootstrap stack name. - Various unit test changes to account for the new API. There's one little edge case we need to deal with: bootstrap stack template v5 includes the `ssm:GetParameter` permissions that we need to check the bootstrap stack version in an out-of-band way... but if we're still on bootstrap stack v4 we won't have the permissions yet to read the version! If we detect that happens (`AccessDeniedException`), we'll still formulate that into an "upgrade" message that's as accurate as possible, using the bootstrap stack template's Output version if found, or a more generic message if not. This PR supersedes #11952. Fixes #11420, fixes #9053. BREAKING CHANGE: users of modern synthesis (`DefaultSynthesizer`, used by CDK Pipelines) must upgrade their bootstrap stacks. Run `cdk bootstrap`. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
…#12594) One of the goals of the "modern synthesis" was to couple the deployment only to the naming of the resources in the bootstrap stack, not the bootstrap stack itself. We *mostly* had that correct, but missed it in one aspect: because the modern bootstrap stack template is still in flux, the CLI does a version check against it; however, it currently performs that version check against the Stack Output of the bootstrap stack, and in order to do that has to look up the bootstrap stack and inadvertently became tied to its name again. This was identified by @redbaron in aws#11952. In order to be able to do that version check without the CLI needing to look up the bootstrap stack, the CLI looks up the SSM parameter with the version number directly. The following changes enable that: - Encode the SSM version parameter name into the Cloud Assembly (this is the magic that decouples from the bootstrap stack name). - In order to be able to read the SSM parameter, the Deploy Role needs `ssm:GetParameter` permissions to it. Addition of these permissions requires a bootstrap stack version bump. - `ToolkitInfo.lookup()` now always returns an object (even if the lookup failed), and that object serves as a cache for the SSM read, so that we don't have to re-fetch the parameter for every asset. - Add an integration test that verifies we can deploy a modern-synthesized application without knowing the bootstrap stack name. - Various unit test changes to account for the new API. There's one little edge case we need to deal with: bootstrap stack template v5 includes the `ssm:GetParameter` permissions that we need to check the bootstrap stack version in an out-of-band way... but if we're still on bootstrap stack v4 we won't have the permissions yet to read the version! If we detect that happens (`AccessDeniedException`), we'll still formulate that into an "upgrade" message that's as accurate as possible, using the bootstrap stack template's Output version if found, or a more generic message if not. This PR supersedes aws#11952. Fixes aws#11420, fixes aws#9053. BREAKING CHANGE: users of modern synthesis (`DefaultSynthesizer`, used by CDK Pipelines) must upgrade their bootstrap stacks. Run `cdk bootstrap`. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
Previously
cdk deploy
was locating CDKToolkit stack by name. Sometimes name is not known upfront, for instance when bootstraping is done via StackSets.All
cdk deploy
needs to know is asset bucket and bootstrap version, these can be communicated via SSM parameters with a known names.This PR is made of individual patches gradually removing dependency on a CF stack name
from
cdk deploy
stage.cdk bootstrap
is not affected and continues to use CF stack name.Main user visible changes are:
toolkit-stack-name
CLI flag is accepted in bootstrap command, but not in deploy anymorebootstrap-qualifier
param forcdk deploy
command. It defaults to the value used by bootstrap CF template.fixes: #11420
cc: @wulfmann
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license