-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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): write Metadata resource in core framework #10306
Conversation
The CDK Metadata Resource is added by the CLI, and only added to the in-memory representation of the template. This in-memory representation is only used in the `CreateChangeSet` call if the full template body is <=50kB. If the template is larger than this size, the template file that's on disk will be uploaded to the bootstrap S3 bucket and referenced. However, that template will not have had the metadata resource injected and so the stack will not be registered. This PR: - Provisionally fixes this issue by flushing the in-memory modifications back out to disk. - Also adds the metadata resources to stacks found in nested Cloud Assemblies, such as the stacks deployed via CDK Pipelines. There is some jank around new-style synthesis stacks: the protocol specifies that those stacks have synthesized their templates as assets, and those will not (necessarily) be processed by the CLI, although it might coincidentally work if the files are the same. The proper fix to this whole mess is to have the framework inject the metadata resource at synthesis time. That fix is forthcoming, but this current one is a good stopgap until that time.
Better for new style synthesis
Better for new style synthesis
…ws-cdk into huijbers/metadata-in-framework
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.
Should we update this comment to point to this new code?
aws-cdk/packages/aws-cdk/lib/api/cxapp/cloud-executable.ts
Lines 94 to 99 in 2b3e14c
// @deprecated(v2): remove this 'if' block and all code referenced by it. | |
// This should honestly not be done here. The framework | |
// should (and will, shortly) synthesize this information directly into | |
// the template. However, in order to support old framework versions | |
// that don't synthesize this info yet, we can only remove this code | |
// once we break backwards compatibility. |
if (!Stack.isStack(construct) | ||
|| construct.parentStack | ||
// Unless disabled | ||
|| construct.node.tryGetContext(cxapi.DISABLE_VERSION_REPORTING) |
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.
Should this be a property of Stack such as stack.versionReportingEnabled
which will take into account context and the nested stack posture instead of leaking the fact that this can he set through context?
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 was also thinking that this should be an opt-in switch ("enable") and not opt-out ("disable"). This way, we (and our users) won't need to fix all their unit tests because the metadata resource will only be attached if the CLI sets that context flag.
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 could do that, but since we already have an existing opt-out flag: DISABLE_VERSION_REPORTING
(which we need to support for backwards compatibility anyway) I didn't really want to add another ENABLE_VERSION_REPORTING
flag as well.
The Stack
property probably makes sense although it would need to be exposed as a public
property or a (ew!) public @internal
one so that this function external to the class can use it.
It fights with the App's { runtimeInfo?: @default true }
property as well...
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.
DISABLE_VERSION_REPORTING
is not really public API, so I would recommend removing it in favor of ENABLE_VERSION_REPORTING
and deprecate runtimeInfo
in favor of versionReporting
(in props and at the Stack
level as public API.
// Unless disabled | ||
|| construct.node.tryGetContext(cxapi.DISABLE_VERSION_REPORTING) | ||
// While running via CLI | ||
|| !process.env[cxapi.CLI_VERSION_ENV]) { return; } |
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?
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 believe I described that twice.
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.
Won't it make sense to just not include the CLI version in case this environment variable in not defined?
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.
It's not actually about the CLI_VERSION_ENV
itself. I'm using CLI_VERSION_ENV
as a trigger to determine whether we're running under the CLI (and hence emitting the metadata)
// Because of https://github.com/aws/aws-cdk/blob/master/packages/@aws-cdk/assert/lib/synth-utils.ts#L74 | ||
// synthesize() may be called more than once on a stack in unit tests, and the below would break | ||
// if we execute it a second time. Guard against the constructs already existing. | ||
if (construct.node.tryFindChild('CDKMetadata')) { return; } |
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.
Make 'CDKMetadata' a const
@@ -369,6 +369,8 @@ export interface AssemblyBuildOptions { | |||
/** | |||
* Include the specified runtime information (module versions) in manifest. | |||
* @default - if this option is not specified, runtime info will not be included | |||
* @deprecated All template modifications that should result from this should | |||
* have already been inserted into the template. | |||
*/ | |||
readonly runtimeInfo?: RuntimeInfo; |
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.
Do we really want to continue to emit this info into the assembly? I think this should now be always undefined
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.
Yes. But I don't think we can remove it from this API due to backwards compatibility guarantees.
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.
Let's try to clean up all the flags and switches and stuff. I don't think that's going to be a major breaking change
Nevertheless, we're going to have to break the cx-api protocol version for this, because we're flipping a default. If we don't break the protocol version, people will be free to use an old CLI with the new framework. The old CLI won't emit |
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.
Looks good to me, minus some docstring changes.
Co-authored-by: Nick Lynch <nlynch@amazon.com>
Co-authored-by: Nick Lynch <nlynch@amazon.com>
Co-authored-by: Nick Lynch <nlynch@amazon.com>
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.
Looks good. See a few questions/clarifications
packages/@aws-cdk/core/lib/app.ts
Outdated
* | ||
* @default Value of 'aws:cdk:version-reporting' context key | ||
*/ | ||
readonly versionReporting?: boolean; |
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 am wondering if the correct terminology should be analytics: boolean
--broaden the scope a little bit.
const CDKMetadata = 'CDKMetadata'; | ||
if (construct.node.tryFindChild(CDKMetadata)) { return; } | ||
|
||
new MetadataResource(construct, CDKMetadata); |
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.
Remind me what's the rationale for not just adding this in the Stack
's constructor based on the prop?
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.
Can't set context anymore
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.
And why do we need to set context? My view is that the context is just used to determine the default for analyticsReporting
when new stacks are created. From that point forward we shouldn't care about the context key, no?
} | ||
if (versionReporting) { context[cxapi.VERSION_REPORTING_ENABLED_CONTEXT] = true; } | ||
// We need to keep on doing this for framework version from before this flag was deprecated. | ||
if (!versionReporting) { context[cxapi.DISABLE_VERSION_REPORTING] = true; } |
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 wonder if we can remove this constant from cxapi and just plug the explicit value here for backwards compat
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.
Oh please yes
Added do not merge |
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 master and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork). |
The Metadata resource used to be added by the CLI, which led to a bug. The better, less error-prone way to do it is to have the framework add the metadata resource to the stack template upon synthesis.
The resources need to be added just-in-time (before synthesis), because if we do it in the constructor
node.setContext()
will stop working (for theStack
already having children).We only add the Metadata resource if we're running via the CLI. If we did not do this, all unit tests everywhere that use
toMatchTemplate()
/toExactlyMatchTemplate()
/toMatch()
will break. There are hundreds alone in our codebase, nevermind however many other ones are out there. The consequences of this are that we [still] will not record users who are doing in-memory synthesis.The CLI only does the work when the
runtimeInfo
field of the assembly is filled, which we just never do anymore. However, the code cannot be removed from the CLI because old versions of the framework might still set that field and expect the resource to be added to the template.By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license