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: implement code generated handler framework #28251

Merged
merged 77 commits into from
Dec 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
b983212
initial commit - framework, classes, constructors, modules
colifran Dec 4, 2023
7145c7a
refactor
colifran Dec 4, 2023
dd2ff42
refactor and bug fixes
colifran Dec 5, 2023
f7b4593
initial setup for config file
colifran Dec 5, 2023
2038bcf
updated outfile location and config format
colifran Dec 5, 2023
d888a5d
Merge branch 'main' into colifran/codegen-handler-framework
colifran Dec 5, 2023
c87613b
initial work on build script
colifran Dec 5, 2023
6de2be2
refactor
colifran Dec 5, 2023
5873fe4
migrated handler framework into custom resource handlers and updated …
colifran Dec 5, 2023
dccc985
migrated handler-framework into custom-resource-handlers
colifran Dec 5, 2023
688a69d
imports for external modules
colifran Dec 6, 2023
c920b1e
refactored airlift custom resource handlers
colifran Dec 6, 2023
c78566a
formatting
colifran Dec 6, 2023
0f8c8e5
exclude dist from compilation
colifran Dec 6, 2023
00fc75a
code to generate custom super props
colifran Dec 6, 2023
ba9c570
path import and path literal in config
colifran Dec 6, 2023
3f450da
remove cdk handler and runtime determiner
colifran Dec 6, 2023
ba044b6
compatible framework runtimes
colifran Dec 6, 2023
43e60d7
singleton interface creation
colifran Dec 6, 2023
8ef2e15
refactor for generate script
colifran Dec 6, 2023
7ef5139
removed unneeded console log
colifran Dec 6, 2023
0c45784
added to config
colifran Dec 7, 2023
1647a82
no op
colifran Dec 7, 2023
7da55a3
config
colifran Dec 7, 2023
2210613
refactor for cdk handler changes and added immutable to property spec…
colifran Dec 7, 2023
9d950d9
cdk-handler and runtime determiner
colifran Dec 7, 2023
e19f090
get or create cdk handler to force singleton cdk handler and migration
colifran Dec 7, 2023
6712a4e
merge conflicts
colifran Dec 7, 2023
fd0b93f
refactor for cdk handler change and updated config
colifran Dec 7, 2023
bacd7b6
move runtime determiner and create runtime class to break circular de…
colifran Dec 8, 2023
ca3be84
renamed to custom resource framework
colifran Dec 8, 2023
721c59f
migrate
colifran Dec 8, 2023
f2504ae
refactor
colifran Dec 8, 2023
98cbe11
migrate
colifran Dec 8, 2023
aa3c176
migrate to codegen providers
colifran Dec 8, 2023
c89f470
airlift core to core
colifran Dec 8, 2023
b0e9ba4
core internal
colifran Dec 8, 2023
d6d5cbf
finished migrating core providers
colifran Dec 8, 2023
ca0ad0a
reverted drain hook change
colifran Dec 8, 2023
2ca1f33
use lambda runtime and auto generate component name
colifran Dec 8, 2023
e036649
lambda runtime isdeprecated flag
colifran Dec 8, 2023
b8da22d
generate names better
colifran Dec 8, 2023
13a0b48
formatting
colifran Dec 8, 2023
1496b55
update custom resources to use auto generated names
colifran Dec 9, 2023
972836b
remove console log
colifran Dec 9, 2023
7b87231
drain hook revert
colifran Dec 9, 2023
c4a20ba
runtimes determiner testing
colifran Dec 10, 2023
510bcaa
testing and empty readme
colifran Dec 11, 2023
a7b74e1
alpha
colifran Dec 11, 2023
228aafd
runtime deprecated
colifran Dec 11, 2023
c3fdb61
naming
colifran Dec 11, 2023
187c7df
refactor and naming update
colifran Dec 11, 2023
f857264
naming
colifran Dec 11, 2023
2db1c20
docstring
colifran Dec 11, 2023
3c81f54
fix framework unit tests
colifran Dec 11, 2023
cc69345
fix failures
colifran Dec 11, 2023
034c7ce
unit tests
colifran Dec 11, 2023
7ba9f86
selective import from core internal stack module
colifran Dec 11, 2023
1db5e8c
formatting
colifran Dec 12, 2023
c11b42a
update importing modules
colifran Dec 12, 2023
3744d65
documentation
colifran Dec 13, 2023
a64afe4
readme and naming
colifran Dec 13, 2023
3a8757a
readme
colifran Dec 13, 2023
7a326ca
fix unit tests
colifran Dec 13, 2023
8582ad6
Merge branch 'main' into colifran/codegen-handler-framework
colifran Dec 13, 2023
cb75044
Merge branch 'main' into colifran/codegen-handler-framework
colifran Dec 14, 2023
812ac0a
naming
colifran Dec 14, 2023
7b3e7c1
name generator
colifran Dec 14, 2023
cf435a0
updated generated component names
colifran Dec 14, 2023
4d25941
fixed unit tests with new naming
colifran Dec 14, 2023
e8f5a3a
reverted lambda runtime deprecated flag
colifran Dec 14, 2023
46aa221
fix constructor props
colifran Dec 14, 2023
ab259ed
node18 as esbuild target
colifran Dec 14, 2023
11f9476
readme
colifran Dec 15, 2023
f77cacf
readme
colifran Dec 15, 2023
dedc574
utils tests
colifran Dec 15, 2023
2dffd0a
Merge branch 'main' into colifran/codegen-handler-framework
mergify[bot] Dec 15, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# CDK Handler Framework

The CDK handler framework is an internal framework used to code generate constructs that extend a lambda `Function`, lambda `SingletonFunction`, or core `CustomResourceProvider` construct and prohibit the user from directly configuring the `handler`, `runtime`, `code`, and `codeDirectory` properties. In doing this, we are able to establish best practices, runtime enforcement, and consistency across all handlers we build and vend within the aws-cdk.

## CDK Handler Framework Concepts

This framework allows for the creation of three component types:
1. `ComponentType.FUNCTION` - This is a wrapper around the lambda `Function` construct. It offers the same behavior and performance as a lambda `Function`, but it restricts the consumer from configuring the `handler`, `runtime`, and `code` properties.
2. `ComponentType.SINGLETON_FUNCTION` - This is a wrapper around the lambda `SingletonFunction` construct. It offers the same behavior and performance as a lambda `SingletonFunction`, but it restricts the consumer from configuring the `handler`, `runtime`, and `code` properties.
3. `ComponentType.CUSTOM_RESOURCE_PROVIDER` - This is a wrapper around the core `CustomResourceProvider` construct. It offers the same behavior and performance as a `CustomResourceProvider` and can be instantiated via the `getOrCreate` or `getOrCreateProvider` methods. This component restricts the consumer from configuring the `runtime` and `codeDirectory` properties.

Code generating one of these three component types requires adding the component properties to the [config](./config.ts) file by providing `ComponentProps`. The `ComponentProps` are responsible for code generating the specified `ComponentType` with the `handler`, `runtime`, `code`, and `codeDirectory` properties set internally. `ComponentProps` includes the following properties:
- `type` - the framework component type to generate.
- `sourceCode` - the source code that will be excuted by the framework component.
- `runtime` - the runtime that is compatible with the framework component's source code. This is an optional property with a default node runtime maintained by the framework.
- `handler` - the name of the method with the source code that the framework component will call. This is an optional property and the default is `index.handler`.
- `minifyAndBundle` - whether the source code should be minified and bundled. This an optional property and the default is `true`. This should only be set to `false` for python files or for typescript/javascript files with a require import.

The [config](./config.ts) file is structured with the top level mapping to an aws-cdk module, i.e., aws-s3, aws-dynamodb, etc. Each service can contain one or more component modules. Component modules are containers for handler framework components and will be rendered as a code generated file. Each component module can contain one or more `ComponentProps` objects. The following example shows a more structural breakdown of how the [config](./config.ts) file is configured:

```ts
const config = {
'aws-s3': { // the aws-cdk-lib module
'replica-provider': [ // the component module
// handler framework component defined as a `ComponentProps` object
{
// the handler framework component type
type: ComponentType.FUNCTION,
// the source code that the component will use
sourceCode: path.resolve(__dirname, '..', 'aws-dynamodb', 'replica-handler', 'index.ts'),
// the handler in the source code that the component will execute
handler: 'index.onEventHandler',
},
],
},
'aws-stepfunctions-tasks': {
// contains multiple component modules
'eval-nodejs-provider': [
{
type: ComponentType.SINGLETON_FUNCTION,
sourceCode: path.resolve(__dirname, '..', 'aws-stepfunctions-tasks', 'eval-nodejs-handler', 'index.ts'),
},
],
'role-policy-provider': [
{
type: ComponentType.SINGLETON_FUNCTION,
sourceCode: path.resolve(__dirname, '..', 'aws-stepfunctions-tasks', 'role-policy-handler', 'index.py'),
runtime: Runtime.PYTHON_3_9,
// prevent minify and bundle since the source code is a python file
minifyAndBundle: false,
},
],
},
};
```

Code generation for the component modules is triggered when this package - `@aws-cdk/custom-resource-handlers` - is built. Importantly, this framework is also responsible for minifying and bundling the custom resource providers' source code and dependencies. A flag named `minifyAndBundle` can be configured as part of the `ComponentProps` to prevent minifying and bundling the source code for a specific provider. This flag is only needed for python files or for typescript/javascript files containing require imports.

Once built, all generated code and bundled source code will be written to `@aws-cdk/custom-resource-handlers/dist`. The top level field in the [config](./config.ts) file defining individual aws-cdk modules will be used to create specific directories within `@aws-cdk/custom-resource-handlers/dist` and each component module will be a separate code generated file within these directories named `<component-module>.generated.ts`. As an example, the sample [config](./config.ts) file above would create the following file structure:

|--- @aws-cdk
| |--- custom-resource-handlers
| | |--- dist
| | | |--- aws-s3
| | | | |--- replica-handler
| | | | | |--- index.js
| | | | |--- replica-provider.generated.ts
| | | |--- aws-stepfunctions-tasks
| | | | |--- eval-nodejs-handler
| | | | | |--- index.js
| | | | |--- role-policy-handler
| | | | | |--- index.py
| | | | |--- eval-nodejs-provider.generated.ts
| | | | |--- role-policy-provider.generated.ts

The code generated handler framework components are consumable from `aws-cdk-lib/custom-resource-handlers/dist` once `aws-cdk-lib` is built. The file structure of `aws-cdk-lib/custom-resource-handlers/dist` will have the same structure as `@aws-cdk/custom-resource-handlers/dist` with the exception of `core`. To prevent circular dependencies, all handler framework components defined in `core`and any associated source code will be consumable from `aws-cdk-lib/core/dist/core`.

## Creating a Handler Framework Component

Creating a new handler framework component involves three steps:
1. Add the source code to `@aws-cdk/custom-resource-handlers/lib/<aws-cdk-lib-module>`
2. Update the [config](./config.ts) file by specifying all required `ComponentProps`.
3. At this point you can directly build `@aws-cdk/custom-resource-handlers` with `yarn build` to view the generated component in `@aws-cdk/custom-resource-handlers/dist`. Alternatively, you can build `aws-cdk-lib` with `npx lerna run build --scope=aws-cdk-lib --skip-nx-cache` to make the generated component available for use within `aws-cdk-lib`
Loading
Loading