-
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
Better way to patch resources at the CloudFormation level to workaround gaps (escape hatch) #606
Comments
@rix0rrr proposed: Right now, the This lack of implementation hiding gives users no ability to take existing constructs but tweak them slightly, as the only CloudFormation generation happens at the very lowest level. As came up in #603, since every L2 is already wrapping another resource, in this very simplest construct tree:
Let's say a user wanted to take the output of the current In a normal OO system, you would subclass In our system, you can't do this since I would argue it would be beneficial if we could achieve the former, since it conforms to expectations and it also provides a more usable "escape hatch" mechanism (that customers are asking for) than simply overriding A simple way of achieving this would be to have @eladb, opinions? |
I thiiiink this might be part of the appmodel refactor? |
@rix0rrr not sure I see how this is related to the app model. It's mostly about devising decent ergonomics to patch synthesized resource properties to some arbitrary values, no? |
The synthesis implementation we use right now looks somewhat like this: class Stack extends Construct {
public toCloudFormation() {
walk(this.children, c => {
if (c instanceof StackElement) {
return c.toCloudFormation();
}
});
}
} I.e., there's a single class that walks the entire tree, and for every child checks if it looks like something that can produce CloudFormation and if so calls it. The fact that a single piece of code walks the entire tree and calls the producers, without giving intervening classes the ability to intercept this, is exactly what's making the "escape hatch" problem hard, and is making it so that people have to override What I'm arguing is that the synthesis implementation should always have been like this: class Construct {
public toCloudFormation() {
return merge(this.children.map(c => c.toCloudFormation());
}
} So that every Construct in the tree has the ability to modify the returned values from their children, and we have a natural escape hatch mechanism. We couldn't do this before, because we wanted class Construct {
public toAppModel() {
return merge(this.children.map(c => c.toAppModel());
}
} |
For example, I think CloudFormation resources can emit the following:
And then |
Some thoughts:
|
Moved to issue description |
I would add this (might be included in your head but I'd like to see it spelled out):
Might be true, but this doesn't need a change, right? People are free to instantiate |
There may be questions about the interactions between overrides and runtime validations. I reckon overrides should happen strictly after synth-time validations, too (because the lists of valid values & the likes may be outdated, too). |
@rix0rrr updated based on your inputs. |
Well - some of the validation happens at the L1 level... |
@RomainMuller good point. So you are suggesting that any "patches" should also bypass any L1 validations, in case the spec is wrong or not up-to-date |
Moved to issue description |
LGTM! |
Does it make sense to expose the full list of children (in addition to construct.children.filter( it => it instanceof s3.cloudformation.BucketResource); That way I don't risk the ID changing out from under me as you hint that it's something that might change. If we think "get by type" is going to be a particularly common use car you it may also be useful to add |
A caveat I see as well is that if the "primary" resource of an L2 changes (aka used to be type Also, are we positive the find & down-cast solution can be used in all the |
@kiiadi good point, this is actually possible ( bucket.children.find(c => (c as cdk.Resource).resourceType === 'AWS::S3::Bucket')
as s3.cloudformation.BucketResource; @RomainMuller down-casting is a basic object-oriented capability and I want to believe it's going to be supported by all the languages we bind to. In strongly-typed languages like Java, if the actual resource object has a different type, the down cast will fail at runtime. In JavaScript, we might get some weird behavior, for sure. Can you elaborate on your concern with interface proxies? Example? |
Names:
Obvsiouly any combination thereof is also an option. |
@eladb - Regarding the interface proxies, I reckon it's never an issue when dealing with Regarding the name proposals... To me, The |
Ha, let me be contrarian. I like Also, I generally prefer shorter words to longer words for verbs in programming, therefore |
Null is a valid and reasonable value for some properties; I've run into issue trying to replicate what the console does in CDK and been blocked from using |
Good point about property removal... Regardless, curious about your use case for using |
It occurred in APIGateway, when I used the console to enable CORS. When the result was examined using
You can see this in the documentation as well: https://docs.aws.amazon.com/cli/latest/reference/apigateway/get-method.html I'm not able to replicate this in CDK, because |
@ccurrie-amzn updated requirements and design (now moved to issue description) to reflect the requirement to allow |
I think it looks good enough for getting started. Hands on experience will be more instructive at this point. 😄 |
I agree with @ccurrie-amzn, on paper my pain points look covered by the content in the description. |
Thanks for your inputs guys! Looking forward for your feedback from actual use soon! |
About when to apply L1 schema validation... We are going to support two layers of overrides:
bucketResource.propertyOverrides.corsConfiguration = {
corsRules: [
{
allowedMethods: [ 'GET' ],
allowedOrigins: [ '*' ]
}
]
};
bucketResource.addPropertyOverride('VersioningConfiguration.Status', 'NewStatus'); The second option will allow anything to be assigned, and will bypass all L1 schema validations. The question is: do you think it makes sense for the first type of overrides to go through schema validations or not. Initially we were saying that it should bypass schema validation and allow anything to be assigned, but when diving a little deeper, some of the schema validation actually happens at compile time (e.g. requires/optional props), so does it make sense to opt-out of some of the validation in this usage? For the cases where the CFN schema is wrong (and thus requires an override), users could just go to the 2nd option ( |
Personally I like validation where possible. I think the default should be to validate the typed overrides, but I can see having the option to turn it off if you need to. You might consider tracking how often opt-outs happen in your usage metadata. |
@ccurrie-amzn great ideas!
|
I like the idea of tracking overrides in Metadata to target gaps. I probably lean more towards validation always for the typed properties and if that fails users have to go to option 2. We hopefully need very few use cases of option 2. |
@ccurrie-amzn see #782 regarding "turning off" validation. TL;DR, it's non-trivial, so I am punting until we have evidence that it is actually needed/valuable. |
Adds capabilities and documentation to allow users to add overrides to synthesized resource definitions in case of gaps in L2s. - resource.addOverride(path, value) - resource.addPropertyOverride(propertyPath, value) - resource.addDeletionOverride(p, v) - resource.addPropertyDeletionOVerride(pp, v) - xxxResource.propertyOverrides (of type XxxResourceProps) Fixes #606 BREAKING CHANGE: The logical ID of the AWS::AutoScaling::AutoScalingGroup resource synthesized by @aws-cdk/aws-autoscaling.AutoScalingGroup has been changed.
Adds capabilities and documentation to allow users to add overrides to synthesized resource definitions in case of gaps in L2s. - resource.addOverride(path, value) - resource.addPropertyOverride(propertyPath, value) - resource.addDeletionOverride(p, v) - resource.addPropertyDeletionOVerride(pp, v) - xxxResource.propertyOverrides (of type XxxResourceProps) Documented under the AWS Construct Library topic. Fixes #606
* **aws-codecommit:** typo in README ([#780](#780)) ([0e79c2d](0e79c2d)) * **aws-ec2:** fix capitalization of "VPCEndpointType" to "VpcEndpointType" ([#789](#789)) ([7a8ee2c](7a8ee2c)), closes [#765](#765) * **docs:** fix issue [#718](#718) (Aurora DB example) ([#783](#783)) ([016f3a8](016f3a8)) * **util:** remove [@aws-cdk](https://github.com/aws-cdk)/util ([#745](#745)) ([10015cb](10015cb)), closes [#709](#709) * **aws-cloudformation:** rename the CodePipeline actions ([#771](#771)) ([007e7b4](007e7b4)) * **aws-cloudformation:** update the README of the module to reflect the new action names ([#775](#775)) ([6c0e75b](6c0e75b)), closes [#771](#771) * **aws-codedeploy:** add auto-scaling groups property to ServerDeploymentGroup ([#739](#739)) ([0b28886](0b28886)) * **aws-codedeploy:** add deployment configuration construct ([#653](#653)) ([e6b67ad](e6b67ad)) * **aws-codepipeline, aws-codecommit, aws-s3:** change the convention for naming the source Actions to XxxSourceAction ([#753](#753)) ([9c3ce7f](9c3ce7f)) * **aws-elasticloadbalancingv2:** support for ALB/NLB ([#750](#750)) ([bd9ee01](bd9ee01)) * tagging support for AutoScaling/SecurityGroup ([#766](#766)) ([3d48eb2](3d48eb2)) * **core:** resource overrides (escape hatch) ([#784](#784)) ([5054eef](5054eef)), closes [#606](#606) * **toolkit:** stop creating 'empty' stacks ([#779](#779)) ([1dddd8a](1dddd8a)) * **cdk**: the constructor signature of `TagManager` has changed. `initialTags` is now passed inside a props object. * **util:** `@aws-cdk/util` is no longer available * **aws-elasticloadbalancingv2:** adds classes for modeling Application and Network Load Balancers. AutoScalingGroups now implement the interface that makes constructs a load balancing target. The breaking change is that Security Group rule identifiers have been changed in order to make adding rules more reliable. No code changes are necessary but existing deployments may experience unexpected changes. * **aws-cloudformation:** this renames all CloudFormation Actions for CodePipeline to bring them in line with Actions defined in other service packages. * **aws-codepipeline, aws-codecommit, aws-s3:** change the names of the source Actions from XxxSource to XxxSourceAction. This is to align them with the other Actions, like Build. Also, CodeBuild has the concept of Sources, so it makes sense to strongly differentiate between the two.
* **aws-codecommit:** typo in README ([#780](#780)) ([0e79c2d](0e79c2d)) * **aws-ec2:** fix capitalization of "VPCEndpointType" to "VpcEndpointType" ([#789](#789)) ([7a8ee2c](7a8ee2c)), closes [#765](#765) * **docs:** fix issue [#718](#718) (Aurora DB example) ([#783](#783)) ([016f3a8](016f3a8)) * **util:** remove [@aws-cdk](https://github.com/aws-cdk)/util ([#745](#745)) ([10015cb](10015cb)), closes [#709](#709) * **aws-cloudformation:** rename the CodePipeline actions ([#771](#771)) ([007e7b4](007e7b4)) * **aws-cloudformation:** update the README of the module to reflect the new action names ([#775](#775)) ([6c0e75b](6c0e75b)), closes [#771](#771) * **aws-codedeploy:** add auto-scaling groups property to ServerDeploymentGroup ([#739](#739)) ([0b28886](0b28886)) * **aws-codedeploy:** add deployment configuration construct ([#653](#653)) ([e6b67ad](e6b67ad)) * **aws-codepipeline, aws-codecommit, aws-s3:** change the convention for naming the source Actions to XxxSourceAction ([#753](#753)) ([9c3ce7f](9c3ce7f)) * **aws-elasticloadbalancingv2:** support for ALB/NLB ([#750](#750)) ([bd9ee01](bd9ee01)) * tagging support for AutoScaling/SecurityGroup ([#766](#766)) ([3d48eb2](3d48eb2)) * **core:** resource overrides (escape hatch) ([#784](#784)) ([5054eef](5054eef)), closes [#606](#606) * **toolkit:** stop creating 'empty' stacks ([#779](#779)) ([1dddd8a](1dddd8a)) * **cdk**: the constructor signature of `TagManager` has changed. `initialTags` is now passed inside a props object. * **util:** `@aws-cdk/util` is no longer available * **aws-elasticloadbalancingv2:** adds classes for modeling Application and Network Load Balancers. AutoScalingGroups now implement the interface that makes constructs a load balancing target. The breaking change is that Security Group rule identifiers have been changed in order to make adding rules more reliable. No code changes are necessary but existing deployments may experience unexpected changes. * **aws-cloudformation:** this renames all CloudFormation Actions for CodePipeline to bring them in line with Actions defined in other service packages. * **aws-codepipeline, aws-codecommit, aws-s3:** change the names of the source Actions from XxxSource to XxxSourceAction. This is to align them with the other Actions, like Build. Also, CodeBuild has the concept of Sources, so it makes sense to strongly differentiate between the two.
Bug Fixes --------- * **aws-apigateway:** allow + in path parts ([#769](#769)) ([0c50d27](0c50d27)), closes [#768](#768) * **aws-cdk:** continue after exceptions in stack monitor ([#791](#791)) ([b0f3298](b0f3298)), closes [#787](#787) * **aws-cloudfront:** check for undefined and determining of the defaultRootObject prop is set or not ([#801](#801)) ([32a74c6](32a74c6)) * **aws-cloudfront:** properly support loggingConfig ([#809](#809)) ([5512f70](5512f70)), closes [#721](#721) * **aws-codecommit:** typo in README ([#780](#780)) ([0e79c2d](0e79c2d)) * **aws-ec2:** Add Burstable Generation 3 Instances ([#812](#812)) ([d36ee6d](d36ee6d)) * **aws-ec2:** fix capitalization of "VPCEndpointType" to "VpcEndpointType" ([#789](#789)) ([7a8ee2c](7a8ee2c)), closes [#765](#765) * **aws-ec2:** fix typo in resource identifier ([#818](#818)) ([f529c80](f529c80)) * **aws-elbv2:** fix load balancer registration ([#890](#890)) ([8cc9abe](8cc9abe)) * **aws-s3:** properly export bucketDomainName ([#844](#844)) ([a65060d](a65060d)) * **aws-sqs:** Queue.import() doesn't return a value ([#885](#885)) ([c592b7f](c592b7f)), closes [#879](#879) * **cdk:** fix TagManager to evaluate to undefined if no tags are included ([#882](#882)) ([477c827](477c827)) * **cdk:** init templates were not upgraded to typescript ^3.0.0 ([#904](#904)) ([2cc7475](2cc7475)) * **cdk:** jsx support conflicts with React usage ([#884](#884)) ([76d8031](76d8031)), closes [#830](#830) * **cfn2ts:** expect Token instead of CloudFormationToken ([#896](#896)) ([6eee1d2](6eee1d2)) * **docs:** fix issue [#718](#718) (Aurora DB example) ([#783](#783)) ([016f3a8](016f3a8)) * **docs:** update supported languages in README ([#819](#819), [#450](#450)) ([#820](#820)) ([ffac98c](ffac98c)) * Correct heading level of CHANGELOG.md 0.10.0 ([40d9ef0](40d9ef0)) * Emit valid YAML-1.1 ([#876](#876)) ([ff857ea](ff857ea)), closes [#875](#875) * **toolkit:** improve error message for large templates ([#900](#900)) ([a41f48f](a41f48f)), closes [#34](#34) Code Refactoring ---------------- * **aws-iam:** move IAM classes cdk to aws-iam ([#866](#866)) ([d46a95b](d46a95b)), closes [#196](#196) * **util:** remove [@aws-cdk](https://github.com/aws-cdk)/util ([#745](#745)) ([10015cb](10015cb)), closes [#709](#709) * **framework:** remove app boilerplate and improvements to cx protocol ([#868](#868)) ([005beec](005beec)), closes [#216](#216) Features -------- * **aws-apigateway:** "LambdaRestApi" and "addProxy" routes ([#867](#867)) ([905a95d](905a95d)) * **aws-cdk:** add maven wrapper to java template ([#811](#811)) ([72aa872](72aa872)) * **aws-cloudformation:** rename the CFN CodePipeline Actions. ([#771](#771)) ([007e7b4](007e7b4)) * **aws-cloudformation:** update the ReadMe of the module to reflect the new Action names. ([#775](#775)) ([6c0e75b](6c0e75b)), closes [#771](#771) * **aws-cloudfront:** Support Security Policy ([#804](#804)) ([b39bf11](b39bf11)), closes [#795](#795) * **aws-codedeploy:** Add the auto-scaling groups property to ServerDeploymentGroup. ([#739](#739)) ([0b28886](0b28886)) * **aws-codedeploy:** Deployment Configuration Construct. ([#653](#653)) ([e6b67ad](e6b67ad)) * **aws-codedeploy:** support setting a load balancer on a Deployment Group. ([#786](#786)) ([e7af9f5](e7af9f5)) * **aws-codepipeline:** allow specifying the runOrder property when creating Actions. ([#776](#776)) ([d146c8d](d146c8d)) * **aws-codepipeline, aws-codecommit, aws-s3:** change the convention for naming the source Actions to XxxSourceAction. ([#753](#753)) ([9c3ce7f](9c3ce7f)) * **aws-dynamodb:** IAM grants support ([#870](#870)) ([c5a4200](c5a4200)) * **aws-dynamodb:** support Global Secondary Indexes ([#760](#760)) ([3601440](3601440)) * **aws-dynamodb:** tags support ([#814](#814)) ([924c84e](924c84e)) * **aws-dynamodB:** support Local Secondary Indexes ([#825](#825)) ([3175af3](3175af3)) * **aws-ec2:** add support for ICMP protocol's classification Types & Codes to SecurityGroupRule ([#893](#893)) ([85bd3c0](85bd3c0)) * **aws-ec2:** allow configuring subnets for NAT gateway ([#874](#874)) ([8ec761c](8ec761c)) * **aws-ec2:** support UDP port ranges in SecurityGroups ([#835](#835)) ([b42ef90](b42ef90)) * **aws-elasticloadbalancingv2:** support for ALB/NLB ([#750](#750)) ([bd9ee01](bd9ee01)) * **aws-s3:** support granting public access to objects ([#886](#886)) ([bdee191](bdee191)), closes [#877](#877) * **cdk:** Add support for UseOnlineResharding with UpdatePolicies ([#881](#881)) ([1f717e1](1f717e1)) * **cdk:** configurable default SSM context provider ([#889](#889)) ([353412b](353412b)) * **core:** resource overrides (escape hatch) ([#784](#784)) ([5054eef](5054eef)), closes [#606](#606) * **aws-codepipeline**: Manage IAM permissions for (some) CFN CodePipeline actions ([#843](#843)) ([4c69118](4c69118)) * **toolkit:** Stop creating 'empty' stacks ([#779](#779)) ([1dddd8a](1dddd8a)) * **aws-autoscaling, aws-ec2:** Tagging support for AutoScaling/SecurityGroup ([#766](#766)) ([3d48eb2](3d48eb2)) ### BREAKING CHANGES * **framework:** The `cdk.App` constructor doesn't accept any arguments, and `app.run()` does not return a `string` anymore. All AWS CDK apps in all languages would need to be modified to adhere to the new API of the `cdk.App` construct. Instead of: const app = new App(process.argv); // ERROR // add stacks process.stdout.write(app.run()); // ERROR The new usage is: const app = new App(); // add stacks app.run(); * **framework:** The CDK is no longer shipped with built-in support for JSX. You can still use JSX but you will have to manually configure it. * **aws-iam:** `PolicyDocument`, `PolicyStatement` and all `PolicyPrincipal` classes moved from the @aws-cdk/cdk module and into the @aws-cdk/aws-iam module. * **aws-codepipeline-api**: `Artifact.subartifact` method of the CodePipeline API was renamed to `Artifact.atPath`. * constructor signature of `TagManager` has changed. `initialTags` is now passed inside a props object. * **util:** @aws-cdk/util is no longer available * **aws-elasticloadbalancingv2:** Adds classes for modeling Application and Network Load Balancers. AutoScalingGroups now implement the interface that makes constructs a load balancing target. The breaking change is that Security Group rule identifiers have been changed in order to make adding rules more reliable. No code changes are necessary but existing deployments may experience unexpected changes. * **aws-cloudformation:** this renames all CloudFormation Actions for CodePipeline to bring them in line with Actions defined in other service packages. * **aws-codepipeline, aws-codecommit, aws-s3:** change the names of the source Actions from XxxSource to XxxSourceAction. This is to align them with the other Actions, like Build. Also, CodeBuild has the concept of Sources, so it makes sense to strongly differentiate between the two.
Bug Fixes --------- * **aws-apigateway:** allow + in path parts ([#769](#769)) ([0c50d27](0c50d27)), closes [#768](#768) * **aws-cdk:** continue after exceptions in stack monitor ([#791](#791)) ([b0f3298](b0f3298)), closes [#787](#787) * **aws-cloudfront:** check for undefined and determining of the defaultRootObject prop is set or not ([#801](#801)) ([32a74c6](32a74c6)) * **aws-cloudfront:** properly support loggingConfig ([#809](#809)) ([5512f70](5512f70)), closes [#721](#721) * **aws-codecommit:** typo in README ([#780](#780)) ([0e79c2d](0e79c2d)) * **aws-ec2:** Add Burstable Generation 3 Instances ([#812](#812)) ([d36ee6d](d36ee6d)) * **aws-ec2:** fix capitalization of "VPCEndpointType" to "VpcEndpointType" ([#789](#789)) ([7a8ee2c](7a8ee2c)), closes [#765](#765) * **aws-ec2:** fix typo in resource identifier ([#818](#818)) ([f529c80](f529c80)) * **aws-elbv2:** fix load balancer registration ([#890](#890)) ([8cc9abe](8cc9abe)) * **aws-s3:** properly export bucketDomainName ([#844](#844)) ([a65060d](a65060d)) * **aws-sqs:** Queue.import() doesn't return a value ([#885](#885)) ([c592b7f](c592b7f)), closes [#879](#879) * **cdk:** fix TagManager to evaluate to undefined if no tags are included ([#882](#882)) ([477c827](477c827)) * **cdk:** init templates were not upgraded to typescript ^3.0.0 ([#904](#904)) ([2cc7475](2cc7475)) * **cdk:** jsx support conflicts with React usage ([#884](#884)) ([76d8031](76d8031)), closes [#830](#830) * **cfn2ts:** expect Token instead of CloudFormationToken ([#896](#896)) ([6eee1d2](6eee1d2)) * **docs:** fix issue [#718](#718) (Aurora DB example) ([#783](#783)) ([016f3a8](016f3a8)) * **docs:** update supported languages in README ([#819](#819), [#450](#450)) ([#820](#820)) ([ffac98c](ffac98c)) * Correct heading level of CHANGELOG.md 0.10.0 ([40d9ef0](40d9ef0)) * Emit valid YAML-1.1 ([#876](#876)) ([ff857ea](ff857ea)), closes [#875](#875) * **toolkit:** improve error message for large templates ([#900](#900)) ([a41f48f](a41f48f)), closes [#34](#34) Code Refactoring ---------------- * **aws-iam:** move IAM classes cdk to aws-iam ([#866](#866)) ([d46a95b](d46a95b)), closes [#196](#196) * **util:** remove [@aws-cdk](https://github.com/aws-cdk)/util ([#745](#745)) ([10015cb](10015cb)), closes [#709](#709) * **framework:** remove app boilerplate and improvements to cx protocol ([#868](#868)) ([005beec](005beec)), closes [#216](#216) Features -------- * **aws-apigateway:** "LambdaRestApi" and "addProxy" routes ([#867](#867)) ([905a95d](905a95d)) * **aws-cdk:** add maven wrapper to java template ([#811](#811)) ([72aa872](72aa872)) * **aws-cloudformation:** rename the CFN CodePipeline Actions. ([#771](#771)) ([007e7b4](007e7b4)) * **aws-cloudformation:** update the ReadMe of the module to reflect the new Action names. ([#775](#775)) ([6c0e75b](6c0e75b)), closes [#771](#771) * **aws-cloudfront:** Support Security Policy ([#804](#804)) ([b39bf11](b39bf11)), closes [#795](#795) * **aws-codedeploy:** Add the auto-scaling groups property to ServerDeploymentGroup. ([#739](#739)) ([0b28886](0b28886)) * **aws-codedeploy:** Deployment Configuration Construct. ([#653](#653)) ([e6b67ad](e6b67ad)) * **aws-codedeploy:** support setting a load balancer on a Deployment Group. ([#786](#786)) ([e7af9f5](e7af9f5)) * **aws-codepipeline:** allow specifying the runOrder property when creating Actions. ([#776](#776)) ([d146c8d](d146c8d)) * **aws-codepipeline, aws-codecommit, aws-s3:** change the convention for naming the source Actions to XxxSourceAction. ([#753](#753)) ([9c3ce7f](9c3ce7f)) * **aws-dynamodb:** IAM grants support ([#870](#870)) ([c5a4200](c5a4200)) * **aws-dynamodb:** support Global Secondary Indexes ([#760](#760)) ([3601440](3601440)) * **aws-dynamodb:** tags support ([#814](#814)) ([924c84e](924c84e)) * **aws-dynamodB:** support Local Secondary Indexes ([#825](#825)) ([3175af3](3175af3)) * **aws-ec2:** add support for ICMP protocol's classification Types & Codes to SecurityGroupRule ([#893](#893)) ([85bd3c0](85bd3c0)) * **aws-ec2:** allow configuring subnets for NAT gateway ([#874](#874)) ([8ec761c](8ec761c)) * **aws-ec2:** support UDP port ranges in SecurityGroups ([#835](#835)) ([b42ef90](b42ef90)) * **aws-elasticloadbalancingv2:** support for ALB/NLB ([#750](#750)) ([bd9ee01](bd9ee01)) * **aws-s3:** support granting public access to objects ([#886](#886)) ([bdee191](bdee191)), closes [#877](#877) * **cdk:** Add support for UseOnlineResharding with UpdatePolicies ([#881](#881)) ([1f717e1](1f717e1)) * **cdk:** configurable default SSM context provider ([#889](#889)) ([353412b](353412b)) * **core:** resource overrides (escape hatch) ([#784](#784)) ([5054eef](5054eef)), closes [#606](#606) * **aws-codepipeline**: Manage IAM permissions for (some) CFN CodePipeline actions ([#843](#843)) ([4c69118](4c69118)) * **toolkit:** Stop creating 'empty' stacks ([#779](#779)) ([1dddd8a](1dddd8a)) * **aws-autoscaling, aws-ec2:** Tagging support for AutoScaling/SecurityGroup ([#766](#766)) ([3d48eb2](3d48eb2)) ### BREAKING CHANGES * **framework:** The `cdk.App` constructor doesn't accept any arguments, and `app.run()` does not return a `string` anymore. All AWS CDK apps in all languages would need to be modified to adhere to the new API of the `cdk.App` construct. Instead of: const app = new App(process.argv); // ERROR // add stacks process.stdout.write(app.run()); // ERROR The new usage is: const app = new App(); // add stacks app.run(); * **framework:** The CDK is no longer shipped with built-in support for JSX. You can still use JSX but you will have to manually configure it. * **aws-iam:** `PolicyDocument`, `PolicyStatement` and all `PolicyPrincipal` classes moved from the @aws-cdk/cdk module and into the @aws-cdk/aws-iam module. * **aws-codepipeline-api**: `Artifact.subartifact` method of the CodePipeline API was renamed to `Artifact.atPath`. * constructor signature of `TagManager` has changed. `initialTags` is now passed inside a props object. * **util:** @aws-cdk/util is no longer available * **aws-elasticloadbalancingv2:** Adds classes for modeling Application and Network Load Balancers. AutoScalingGroups now implement the interface that makes constructs a load balancing target. The breaking change is that Security Group rule identifiers have been changed in order to make adding rules more reliable. No code changes are necessary but existing deployments may experience unexpected changes. * **aws-cloudformation:** this renames all CloudFormation Actions for CodePipeline to bring them in line with Actions defined in other service packages. * **aws-codepipeline, aws-codecommit, aws-s3:** change the names of the source Actions from XxxSource to XxxSourceAction. This is to align them with the other Actions, like Build. Also, CodeBuild has the concept of Sources, so it makes sense to strongly differentiate between the two.
Are these escape hatches officially/nicely documented anywhere on the main docs site? I stumbled across this issue by accident and wasn't aware of it prior, but it's a super useful feature that should be easily discoverable! |
Must have missed that previously. Thanks! |
@eladb is there a new version of the document? The old link is dead. |
@Console32 - here you go - https://docs.aws.amazon.com/cdk/latest/guide/cfn_layer.html |
Currently, the only way to workaround gaps in the AWS Construct Library is to overload
toCloudFormation
at theStack
level and patch the synthesized output:Requirements
DependsOn
(e.g. Add support for AWS::CloudFormation::Init #777)cdk.Resource
, but we should document)null
as those are sometimes needed by CloudFormation (e.g)Non functional:
Design
Based on the requirements above, here's a design proposal.
Accessing L1 resources
To get a handle on an L1 resource behind an L2, users will use the
construct.findChild(id)
ortryFindChild(id)
and downcast it to the specific L1.For example, to access the L1 bucket resource given an L2 bucket:
By convention, the ID of the "main" resource of L2s is
Resource
, so in most cases, it should be straightforward to find the child.In more complex scenarios, users will have to consult the L2 code in order to learn the ID (for example,
asg.findChild('LaunchConfig')
will returnautoScaling.cloudformation.LaunchConfigurationResource
.Perhaps we can improve our convention such that the IDs of the children that are not the main resource will be 1:1 with the CloudFormation resource type name, so instead of
LaunchConfig
we should useLaunchConfiguration
.This approach allows users to access L1 resources freely, and obtain a strongly-typed L1 type from them without requiring that the L2 layer will "expose" those resources explicitly.
findChild
will fail if the child could not be located, which means that if the underlying L2 changes the IDs or structure for some reason, synthesis will fail.It is also possible to use
construct.children
for more advanced queries. For example, we can look for a child that has a certain CloudFormation resource type:From that point, users are interacting with the strong-typed L1 resources (which extend
cdk.Resource
), so we will look into how to extend their surface area to support the various requirements.Resource Options
cdk.Resource
already has a few facilities for setting resource options such asMetadata
,DependsOn
, etc:This will synthesize to:
Raw Overrides
At the lowest level, we want to allow users to "patch" the synthesized resource definition and bypass any validations at the L1/L2 layers.
To that end, we will add a method
resource.addOverride(path, value)
which will allow applying arbitrary overrides to a synthesized resource.addOverride
will be able to override anything under the resource definition (including resource options such asDependsOn
, etc). We will also addresource.addPropertyOverride(propertyPath, value)
as sugar for property overrides.For example:
Will synthesize to:
It should be possible to also assign
null
as an override value:Synthesizes to:
It should also possible to clear a value using an override:
Overrides may freely use tokens (or stringified tokens) for values, and those will be resolved during synthesis:
Will synthesize to:
Strong-type property overrides
Users should also be able to define overrides for L1 resource properties via the generated property types. To that end, each generated resource will expose another property
propertyOverrides
of typeXxxProps
.So,
s3.cloudformation.BucketResource#propertyOverrides
will have the types3.cloudformation.BucketResourceProps
, which allow users to define overrides for bucket resource properties as follows:Notes:
propertyOverrides
are merged into the resource on top of the values defined during initialization.null
in the overrides.Defining raw resources
It is also possible to directly use
cdk.Resource
to define arbitrary CloudFormation resources:The text was updated successfully, but these errors were encountered: