Skip to content
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
3e8f5ed
initial commit
pcheungamz Feb 28, 2025
61af5e4
Use class decorator to run applyInjectors
pcheungamz Mar 10, 2025
fd3ac61
Make Constructs property injectable in aws-appmesh, aws-appsync, aws-…
pcheungamz Mar 11, 2025
fb76398
Make Constructs property injectable in aws-cloudtrail, aws-cognito, a…
pcheungamz Mar 11, 2025
11c7812
Make Constructs property injectable in aws-ec2, aws-ecr, aws-ecr-asse…
pcheungamz Mar 11, 2025
e3be467
Make Constructs property injectable in aws-ecs-patterns, aws-efs, aws…
pcheungamz Mar 11, 2025
43c1ea6
Make Constructs property injectable in aws-elasticloadbalancingv2, aw…
pcheungamz Mar 11, 2025
169d605
Make Constructs property injectable in aws-lambda, aws-logs, aws-open…
pcheungamz Mar 12, 2025
8bc8f68
Make Constructs property injectable aws-s3-deployment, aws-secretsman…
pcheungamz Mar 12, 2025
e05ada5
Reduce log
pcheungamz Mar 14, 2025
0a58c65
Make aws-sns constructs injectable
megarach0 Mar 19, 2025
f6bb178
Make these Constructs injectable: Queue, SageMakerCreateModel, SageMa…
pcheungamz Mar 27, 2025
30e29e0
Add support for property injection: aws-ses
manan-pancholi Mar 31, 2025
b9fcc85
Remove unnecessary import to fix linting build failure
manan-pancholi Mar 31, 2025
ee2b8ef
Add support for property injection: aws-sns-subscriptions/UrlSubscrip…
manan-pancholi Apr 1, 2025
591c98b
Remove debug log
pcheungamz Apr 2, 2025
07f7e52
Add property injection support for aws-apigateway/Method
manan-pancholi Apr 8, 2025
7c00088
Change propertyInjectionDecorator to propertyInjectable
pcheungamz Apr 9, 2025
635b228
Add Blueprint Property Injector to README
pcheungamz Apr 10, 2025
36a0781
Add property injector framework tests
pcheungamz Apr 14, 2025
f530364
Fix README format. Make these Constructs injectable: StepFunctionsRes…
pcheungamz Apr 21, 2025
3ff9830
Make these Constructs injectable: CustomPolicy, ClientVpnEndpoint, As…
pcheungamz Apr 21, 2025
f36f14e
Strongly type the decorator, find 2 non-construct taggables, and hide…
rix0rrr Apr 22, 2025
11fb2e1
Fix build problem. npx lerna run build --concurrency 4 works now
pcheungamz Apr 22, 2025
7f7424c
Removed warn from PropertyInjectors.add. updated integ test snapshot
pcheungamz Apr 22, 2025
855601d
Merge branch 'main' into prop-injectors
moelasmar Apr 23, 2025
1648758
Update repository.ts
moelasmar Apr 23, 2025
aff76ea
Update instance.ts
moelasmar Apr 23, 2025
8e87663
Update instance.ts
moelasmar Apr 23, 2025
5df3ac2
Update auto-scaling-group.ts
moelasmar Apr 23, 2025
7e10393
Update cluster.ts
moelasmar Apr 23, 2025
0a86402
Update role.ts
moelasmar Apr 23, 2025
aa89620
Keep the static Class' name property
moelasmar Apr 23, 2025
23c4287
Update README
moelasmar Apr 23, 2025
dd6ee84
Update default.ts-fixture
moelasmar Apr 23, 2025
f5b2fd1
Create README-blueprints.fixture
moelasmar Apr 23, 2025
e30c495
Update default.ts-fixture
moelasmar Apr 23, 2025
e8208c9
Update README-blueprints.fixture
moelasmar Apr 23, 2025
85d20c4
Update README.md
moelasmar Apr 23, 2025
3a0895d
Create README-Injectable.fixture
moelasmar Apr 23, 2025
9377cf4
Merge branch 'main' into prop-injectors
moelasmar Apr 23, 2025
317dfca
Rename README-blueprints.fixture to README-blueprints-fixture
moelasmar Apr 23, 2025
d1c3933
Rename README-Injectable.fixture to README-Injectable-fixture
moelasmar Apr 23, 2025
1c40005
Update prop-injectable.ts
moelasmar Apr 23, 2025
ade8ae2
Update README.md
moelasmar Apr 23, 2025
715e6db
Update and rename README-Injectable-fixture to README-Injectable.ts-f…
moelasmar Apr 23, 2025
e5a880d
Update and rename README-blueprints-fixture to README-blueprints.ts-f…
moelasmar Apr 23, 2025
5b81ffa
Fixed rosetta errors
pcheungamz Apr 29, 2025
6e57be2
Merge with latest mainline
pcheungamz May 1, 2025
08a8d3c
Merge branch 'main' into prop-injectors
pcheungamz May 1, 2025
6b1b426
Update integ test
pcheungamz May 1, 2025
762812d
Remove dependencies on s3, lambda, and others in prop-injectors.test.ts
pcheungamz May 2, 2025
d10782d
fix build errors
pcheungamz May 2, 2025
cc5aaf2
Merge branch 'main' into prop-injectors
mergify[bot] May 5, 2025
5688599
update integ test after merge from main. It was missing ap-east-2
pcheungamz May 5, 2025
fa0d021
Merge branch 'main' into prop-injectors
mergify[bot] May 5, 2025
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
69 changes: 69 additions & 0 deletions packages/aws-cdk-lib/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1546,4 +1546,73 @@ warning by the `id`.
Annotations.of(this).acknowledgeWarning('IAM:Group:MaxPoliciesExceeded', 'Account has quota increased to 20');
```

## Blueprint Property Injection

The goal of Blueprint Property Injection is to provide builders an automatic way to set default property values.

Construct authors can declare that a Construct can have it properties injected by adding `@propertyInjectable`
class decorator and specifying `PROPERTY_INJECTION_ID` readonly property. For example:

```ts
@propertyInjectable
export class ApiKey extends ApiKeyBase {
/**
* Uniquely identifies this class.
*/
public static readonly PROPERTY_INJECTION_ID: string = 'aws-cdk-lib.aws-apigateway.ApiKey';
...
}
```

Organizations can set default property values to a Construct by writing Injectors for builders to consume.

Here is a simple example of an Injector for APiKey.
```ts
export class ApiKeyPropsInjector implements IPropertyInjector {
readonly constructUniqueId: string;

constructor() {
this.constructUniqueId = ApiKey.PROPERTY_INJECTION_ID;
}

inject(originalProps: ApiKeyProps, context: InjectionContext): ApiKeyProps {
return {
enabled: false,
...originalProps,
};
}
}
```
Some notes:
* ApiKey must have a `PROPERTY_INJECTION_ID` property, in addition to having `@propertyInjectable` class decorator.
* We set ApiKeyProps.enabled to false, if it is not provided; otherwise it would use the value that was passed in.
* It is also possible to force ApiKeyProps.enabled to false, and not provide a way for the builders to overwrite it.

Here is an example of how builders can use the injector the org created.

```ts
const app = new App({});
const stack = new Stack(app2, 'my-stack', {
propertyInjectors: [new ApiKeyPropsInjector()],
});
new ApiKey(stack, 'my-api-key', {});
```

This is equivalent to:

```ts
const app = new App({});
const stack = new Stack(app, 'my-stack', {});
new ApiKey(stack, 'my-api-key', {
enabled: false,
});
```

Some notes:
* We attach the injectors to Stack in this example, but we can also attach them to App or Stage.
* All the ApiKey created in the scope of stack will get `enabled: false`.
* Builders can overwrite the default value with `new ApiKey(stack, 'my-api-key', {enabled: true});`

For more information, please see the [RFC](https://github.com/aws/aws-cdk-rfcs/blob/main/text/0693-property-injection.md).

<!--END CORE DOCUMENTATION-->
7 changes: 7 additions & 0 deletions packages/aws-cdk-lib/aws-apigateway/lib/api-key.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import * as iam from '../../aws-iam';
import { ArnFormat, IResource as IResourceBase, Resource, Stack } from '../../core';
import { ValidationError } from '../../core/lib/errors';
import { addConstructMetadata } from '../../core/lib/metadata-resource';
import { propertyInjectable } from '../../core/lib/prop-injectors';

/**
* API keys are alphanumeric string values that you distribute to
Expand Down Expand Up @@ -145,7 +146,13 @@ abstract class ApiKeyBase extends Resource implements IApiKey {
* An ApiKey can be distributed to API clients that are executing requests
* for Method resources that require an Api Key.
*/
@propertyInjectable
export class ApiKey extends ApiKeyBase {
/**
* Uniquely identifies this class.
*/
public static readonly PROPERTY_INJECTION_ID: string = 'aws-cdk-lib.aws-apigateway.ApiKey';

/**
* Import an ApiKey by its Id
*/
Expand Down
7 changes: 7 additions & 0 deletions packages/aws-cdk-lib/aws-apigateway/lib/deployment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Lazy, RemovalPolicy, Resource, CfnResource } from '../../core';
import { ValidationError } from '../../core/lib/errors';
import { md5hash } from '../../core/lib/helpers-internal';
import { addConstructMetadata, MethodMetadata } from '../../core/lib/metadata-resource';
import { propertyInjectable } from '../../core/lib/prop-injectors';

export interface DeploymentProps {
/**
Expand Down Expand Up @@ -69,7 +70,13 @@ export interface DeploymentProps {
* model. Use the `node.addDependency(dep)` method to circumvent that. This is done
* automatically for the `restApi.latestDeployment` deployment.
*/
@propertyInjectable
export class Deployment extends Resource {
/**
* Uniquely identifies this class.
*/
public static readonly PROPERTY_INJECTION_ID: string = 'aws-cdk-lib.aws-apigateway.Deployment';

/** @attribute */
public readonly deploymentId: string;
public readonly api: IRestApi;
Expand Down
7 changes: 7 additions & 0 deletions packages/aws-cdk-lib/aws-apigateway/lib/domain-name.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { IBucket } from '../../aws-s3';
import { IResource, Names, Resource, Token } from '../../core';
import { ValidationError } from '../../core/lib/errors';
import { addConstructMetadata, MethodMetadata } from '../../core/lib/metadata-resource';
import { propertyInjectable } from '../../core/lib/prop-injectors';

/**
* Options for creating an api mapping
Expand Down Expand Up @@ -116,7 +117,13 @@ export interface IDomainName extends IResource {
readonly domainNameAliasHostedZoneId: string;
}

@propertyInjectable
export class DomainName extends Resource implements IDomainName {
/**
* Uniquely identifies this class.
*/
public static readonly PROPERTY_INJECTION_ID: string = 'aws-cdk-lib.aws-apigateway.DomainName';

/**
* Imports an existing domain name.
*/
Expand Down
7 changes: 7 additions & 0 deletions packages/aws-cdk-lib/aws-apigateway/lib/lambda-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { RestApi, RestApiProps } from './restapi';
import * as lambda from '../../aws-lambda';
import { UnscopedValidationError, ValidationError } from '../../core/lib/errors';
import { addConstructMetadata } from '../../core/lib/metadata-resource';
import { propertyInjectable } from '../../core/lib/prop-injectors';

export interface LambdaRestApiProps extends RestApiProps {
/**
Expand Down Expand Up @@ -51,7 +52,13 @@ export interface LambdaRestApiProps extends RestApiProps {
* method from the specified path. If not defined, you will need to explicity
* add resources and methods to the API.
*/
@propertyInjectable
export class LambdaRestApi extends RestApi {
/**
* Uniquely identifies this class.
*/
public static readonly PROPERTY_INJECTION_ID: string = 'aws-cdk-lib.aws-apigateway.LambdaRestApi';

constructor(scope: Construct, id: string, props: LambdaRestApiProps) {
if (props.options?.defaultIntegration || props.defaultIntegration) {
throw new ValidationError('Cannot specify "defaultIntegration" since Lambda integration is automatically defined', scope);
Expand Down
8 changes: 7 additions & 1 deletion packages/aws-cdk-lib/aws-apigateway/lib/method.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { IStage } from './stage';
import { validateHttpMethod } from './util';
import * as cloudwatch from '../../aws-cloudwatch';
import * as iam from '../../aws-iam';
import { Annotations, ArnFormat, FeatureFlags, Lazy, Names, Resource, Stack } from '../../core';
import { propertyInjectable, Annotations, ArnFormat, FeatureFlags, Lazy, Names, Resource, Stack } from '../../core';
import { ValidationError } from '../../core/lib/errors';
import { addConstructMetadata, MethodMetadata } from '../../core/lib/metadata-resource';
import { APIGATEWAY_REQUEST_VALIDATOR_UNIQUE_ID } from '../../cx-api';
Expand Down Expand Up @@ -163,7 +163,13 @@ export interface MethodProps {
readonly options?: MethodOptions;
}

@propertyInjectable
export class Method extends Resource {
/**
* Uniquely identifies this class.
*/
public static readonly PROPERTY_INJECTION_ID: string = 'aws-cdk-lib.aws-apigateway.Method';

/** @attribute */
public readonly methodId: string;

Expand Down
13 changes: 13 additions & 0 deletions packages/aws-cdk-lib/aws-apigateway/lib/restapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import * as iam from '../../aws-iam';
import { ArnFormat, CfnOutput, IResource as IResourceBase, Resource, Stack, Token, FeatureFlags, RemovalPolicy, Size, Lazy } from '../../core';
import { ValidationError } from '../../core/lib/errors';
import { addConstructMetadata, MethodMetadata } from '../../core/lib/metadata-resource';
import { propertyInjectable } from '../../core/lib/prop-injectors';
import { APIGATEWAY_DISABLE_CLOUDWATCH_ROLE } from '../../cx-api';

const RESTAPI_SYMBOL = Symbol.for('@aws-cdk/aws-apigateway.RestApiBase');
Expand Down Expand Up @@ -723,7 +724,13 @@ export abstract class RestApiBase extends Resource implements IRestApi, iam.IRes
*
* @resource AWS::ApiGateway::RestApi
*/
@propertyInjectable
export class SpecRestApi extends RestApiBase {
/**
* Uniquely identifies this class.
*/
public static readonly PROPERTY_INJECTION_ID: string = 'aws-cdk-lib.aws-apigateway.SpecRestApi';

/**
* The ID of this API Gateway RestApi.
*/
Expand Down Expand Up @@ -818,7 +825,13 @@ export interface RestApiAttributes {
* By default, the API will automatically be deployed and accessible from a
* public endpoint.
*/
@propertyInjectable
export class RestApi extends RestApiBase {
/**
* Uniquely identifies this class.
*/
public static readonly PROPERTY_INJECTION_ID: string = 'aws-cdk-lib.aws-apigateway.RestApi';

/**
* Return whether the given object is a `RestApi`
*/
Expand Down
7 changes: 7 additions & 0 deletions packages/aws-cdk-lib/aws-apigateway/lib/stage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import * as cloudwatch from '../../aws-cloudwatch';
import { ArnFormat, Duration, IResource, Resource, Stack, Token } from '../../core';
import { ValidationError } from '../../core/lib/errors';
import { addConstructMetadata } from '../../core/lib/metadata-resource';
import { propertyInjectable } from '../../core/lib/prop-injectors';

/**
* Represents an APIGateway Stage.
Expand Down Expand Up @@ -358,7 +359,13 @@ export abstract class StageBase extends Resource implements IStage {
}
}

@propertyInjectable
export class Stage extends StageBase {
/**
* Uniquely identifies this class.
*/
public static readonly PROPERTY_INJECTION_ID: string = 'aws-cdk-lib.aws-apigateway.Stage';

/**
* Import a Stage by its attributes
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { IBucket } from '../../../aws-s3';
import { IResource, Lazy, Resource, Token } from '../../../core';
import { ValidationError } from '../../../core/lib/errors';
import { addConstructMetadata, MethodMetadata } from '../../../core/lib/metadata-resource';
import { propertyInjectable } from '../../../core/lib/prop-injectors';

/**
* The minimum version of the SSL protocol that you want API Gateway to use for HTTPS connections.
Expand Down Expand Up @@ -152,7 +153,13 @@ export interface MTLSConfig {
/**
* Custom domain resource for the API
*/
@propertyInjectable
export class DomainName extends Resource implements IDomainName {
/**
* Uniquely identifies this class.
*/
public static readonly PROPERTY_INJECTION_ID: string = 'aws-cdk-lib.aws-apigatewayv2.DomainName';

/**
* Import from attributes
*/
Expand Down
7 changes: 7 additions & 0 deletions packages/aws-cdk-lib/aws-apigatewayv2/lib/http/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { Metric, MetricOptions } from '../../../aws-cloudwatch';
import { ArnFormat, Duration, Stack, Token } from '../../../core';
import { ValidationError } from '../../../core/lib/errors';
import { addConstructMetadata, MethodMetadata } from '../../../core/lib/metadata-resource';
import { propertyInjectable } from '../../../core/lib/prop-injectors';
import { IApi } from '../common/api';
import { ApiBase } from '../common/base';
import { DomainMappingOptions } from '../common/stage';
Expand Down Expand Up @@ -352,7 +353,13 @@ export interface HttpApiAttributes {
* Create a new API Gateway HTTP API endpoint.
* @resource AWS::ApiGatewayV2::Api
*/
@propertyInjectable
export class HttpApi extends HttpApiBase {
/**
* Uniquely identifies this class.
*/
public static readonly PROPERTY_INJECTION_ID: string = 'aws-cdk-lib.aws-apigatewayv2.HttpApi';

/**
* Import an existing HTTP API into this CDK app.
*/
Expand Down
7 changes: 7 additions & 0 deletions packages/aws-cdk-lib/aws-apigatewayv2/lib/http/authorizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { CfnAuthorizer } from '.././index';
import { Duration, Resource } from '../../../core';
import { ValidationError } from '../../../core/lib/errors';
import { addConstructMetadata } from '../../../core/lib/metadata-resource';
import { propertyInjectable } from '../../../core/lib/prop-injectors';
import { IAuthorizer } from '../common';

/**
Expand Down Expand Up @@ -135,7 +136,13 @@ export interface HttpAuthorizerAttributes {
* An authorizer for Http Apis
* @resource AWS::ApiGatewayV2::Authorizer
*/
@propertyInjectable
export class HttpAuthorizer extends Resource implements IHttpAuthorizer {
/**
* Uniquely identifies this class.
*/
public static readonly PROPERTY_INJECTION_ID: string = 'aws-cdk-lib.aws-apigatewayv2.HttpAuthorizer';

/**
* Import an existing HTTP Authorizer into this CDK app.
*/
Expand Down
7 changes: 7 additions & 0 deletions packages/aws-cdk-lib/aws-apigatewayv2/lib/http/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import * as iam from '../../../aws-iam';
import { Aws, Resource } from '../../../core';
import { UnscopedValidationError, ValidationError } from '../../../core/lib/errors';
import { addConstructMetadata, MethodMetadata } from '../../../core/lib/metadata-resource';
import { propertyInjectable } from '../../../core/lib/prop-injectors';
import { IRoute } from '../common';

/**
Expand Down Expand Up @@ -173,7 +174,13 @@ enum HttpRouteAuthorizationType {
* Route class that creates the Route for API Gateway HTTP API
* @resource AWS::ApiGatewayV2::Route
*/
@propertyInjectable
export class HttpRoute extends Resource implements IHttpRoute {
/**
* Uniquely identifies this class.
*/
public static readonly PROPERTY_INJECTION_ID: string = 'aws-cdk-lib.aws-apigatewayv2.HttpRoute';

public readonly routeId: string;
public readonly httpApi: IHttpApi;
public readonly path?: string;
Expand Down
7 changes: 7 additions & 0 deletions packages/aws-cdk-lib/aws-appmesh/lib/virtual-gateway.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { VirtualGatewayListener, VirtualGatewayListenerConfig } from './virtual-
import * as iam from '../../aws-iam';
import * as cdk from '../../core';
import { addConstructMetadata } from '../../core/lib/metadata-resource';
import { propertyInjectable } from '../../core/lib/prop-injectors';

/**
* Interface which all Virtual Gateway based classes must implement
Expand Down Expand Up @@ -129,7 +130,13 @@ abstract class VirtualGatewayBase extends cdk.Resource implements IVirtualGatewa
*
* @see https://docs.aws.amazon.com/app-mesh/latest/userguide/virtual_gateways.html
*/
@propertyInjectable
export class VirtualGateway extends VirtualGatewayBase {
/**
* Uniquely identifies this class.
*/
public static readonly PROPERTY_INJECTION_ID: string = 'aws-cdk-lib.aws-appmesh.VirtualGateway';

/**
* Import an existing VirtualGateway given an ARN
*/
Expand Down
7 changes: 7 additions & 0 deletions packages/aws-cdk-lib/aws-appmesh/lib/virtual-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { VirtualNodeListener, VirtualNodeListenerConfig } from './virtual-node-l
import * as iam from '../../aws-iam';
import * as cdk from '../../core';
import { addConstructMetadata, MethodMetadata } from '../../core/lib/metadata-resource';
import { propertyInjectable } from '../../core/lib/prop-injectors';

/**
* Interface which all VirtualNode based classes must implement
Expand Down Expand Up @@ -133,7 +134,13 @@ abstract class VirtualNodeBase extends cdk.Resource implements IVirtualNode {
*
* @see https://docs.aws.amazon.com/app-mesh/latest/userguide/virtual_nodes.html
*/
@propertyInjectable
export class VirtualNode extends VirtualNodeBase {
/**
* Uniquely identifies this class.
*/
public static readonly PROPERTY_INJECTION_ID: string = 'aws-cdk-lib.aws-appmesh.VirtualNode';

/**
* Import an existing VirtualNode given an ARN
*/
Expand Down
Loading