From 1e73ac5f53809e4b5f1192e3307ba7780bc22a81 Mon Sep 17 00:00:00 2001 From: Kazuho Cryer-Shinozuka Date: Wed, 23 Oct 2024 23:16:08 +0900 Subject: [PATCH 1/5] docs: fix improper JSDoc formatting (#31820) ### Issue # (if applicable) None ### Reason for this change There are some improper JSDoc formatting. ### Description of changes I have corrected multiple instances of improper JSDoc formatting. ```diff /** - * description - * - * @default - xxx - */ + * description + * + * @default - xxx + */ ``` ### Description of how you validated changes None ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../lib/auto-scaling-configuration.ts | 12 +-- .../aws-apprunner-alpha/lib/service.ts | 4 +- .../aws-apprunner-alpha/lib/vpc-connector.ts | 20 ++--- .../@aws-cdk/aws-gamelift-alpha/lib/alias.ts | 4 +- .../@aws-cdk/aws-gamelift-alpha/lib/build.ts | 8 +- .../aws-gamelift-alpha/lib/fleet-base.ts | 4 +- .../lib/game-server-group.ts | 8 +- .../aws-gamelift-alpha/lib/ingress-rule.ts | 74 +++++++++---------- .../aws-kinesisfirehose-alpha/lib/source.ts | 24 +++--- .../lib/logging-config.ts | 16 ++-- packages/@aws-cdk/aws-pipes-alpha/lib/pipe.ts | 32 ++++---- .../aws-pipes-sources-alpha/lib/sqs.ts | 10 +-- .../lib/streamSource.ts | 18 ++--- .../@aws-cdk/aws-redshift-alpha/lib/table.ts | 8 +- .../lib/firewall-domain-list.ts | 46 ++++++------ .../lib/firewall-rule-group-association.ts | 40 +++++----- .../lib/target-application.ts | 54 +++++++------- .../cdk-cli-wrapper/lib/commands/common.ts | 2 +- .../cli-lib-alpha/lib/commands/common.ts | 2 +- .../lib/runner/integration-tests.ts | 8 +- .../aws-apigatewayv2/lib/websocket/api.ts | 8 +- .../aws-cdk-lib/aws-appsync/lib/schema.ts | 20 ++--- .../aws-batch/lib/linux-parameters.ts | 24 +++--- .../lib/certificate-base.ts | 8 +- .../aws-cloudfront/lib/distribution.ts | 46 ++++++------ .../aws-cloudfront/lib/endpoint.ts | 8 +- .../aws-codebuild/lib/build-spec.ts | 8 +- .../lib/ecs/deployment-group.ts | 22 +++--- .../aws-cognito/lib/user-pool-idps/oidc.ts | 10 +-- packages/aws-cdk-lib/aws-config/lib/rule.ts | 6 +- packages/aws-cdk-lib/aws-docdb/lib/cluster.ts | 42 +++++------ .../aws-cdk-lib/aws-dynamodb/lib/table.ts | 14 ++-- ...ion-multiple-target-groups-service-base.ts | 6 +- .../lib/base/fargate-service-base.ts | 62 ++++++++-------- .../lib/base/scheduled-task-base.ts | 16 ++-- packages/aws-cdk-lib/aws-ecs/lib/cluster.ts | 2 +- .../aws-ecs/lib/linux-parameters.ts | 24 +++--- .../aws-events-targets/lib/ecs-task.ts | 36 ++++----- packages/aws-cdk-lib/aws-iam/lib/role.ts | 2 +- .../aws-cdk-lib/aws-ses/lib/email-identity.ts | 20 ++--- .../test/private/fake-task.ts | 4 +- .../aws-cdk-lib/aws-synthetics/lib/runtime.ts | 6 +- packages/aws-cdk/lib/api/deployments.ts | 34 ++++----- 43 files changed, 411 insertions(+), 411 deletions(-) diff --git a/packages/@aws-cdk/aws-apprunner-alpha/lib/auto-scaling-configuration.ts b/packages/@aws-cdk/aws-apprunner-alpha/lib/auto-scaling-configuration.ts index 1d3c1ce943fca..aae6e0ef9069a 100644 --- a/packages/@aws-cdk/aws-apprunner-alpha/lib/auto-scaling-configuration.ts +++ b/packages/@aws-cdk/aws-apprunner-alpha/lib/auto-scaling-configuration.ts @@ -133,15 +133,15 @@ export class AutoScalingConfiguration extends cdk.Resource implements IAutoScali } /** - * The ARN of the Auto Scaling Configuration. - * @attribute - */ + * The ARN of the Auto Scaling Configuration. + * @attribute + */ readonly autoScalingConfigurationArn: string; /** - * The name of the Auto Scaling Configuration. - * @attribute - */ + * The name of the Auto Scaling Configuration. + * @attribute + */ readonly autoScalingConfigurationName: string; /** diff --git a/packages/@aws-cdk/aws-apprunner-alpha/lib/service.ts b/packages/@aws-cdk/aws-apprunner-alpha/lib/service.ts index 80040c76ad560..9941de291cb1d 100644 --- a/packages/@aws-cdk/aws-apprunner-alpha/lib/service.ts +++ b/packages/@aws-cdk/aws-apprunner-alpha/lib/service.ts @@ -435,8 +435,8 @@ export abstract class Source { } /** - * Called when the Job is initialized to allow this object to bind. - */ + * Called when the Job is initialized to allow this object to bind. + */ public abstract bind(scope: Construct): SourceConfig; } diff --git a/packages/@aws-cdk/aws-apprunner-alpha/lib/vpc-connector.ts b/packages/@aws-cdk/aws-apprunner-alpha/lib/vpc-connector.ts index a6371eacd86f7..f2f3a7f99fd3a 100644 --- a/packages/@aws-cdk/aws-apprunner-alpha/lib/vpc-connector.ts +++ b/packages/@aws-cdk/aws-apprunner-alpha/lib/vpc-connector.ts @@ -28,10 +28,10 @@ export interface VpcConnectorProps { readonly securityGroups?: ec2.ISecurityGroup[]; /** - * The name for the VpcConnector. - * - * @default - a name generated by CloudFormation - */ + * The name for the VpcConnector. + * + * @default - a name generated by CloudFormation + */ readonly vpcConnectorName?: string; } @@ -109,9 +109,9 @@ export class VpcConnector extends cdk.Resource implements IVpcConnector { } /** - * The ARN of the VPC connector. - * @attribute - */ + * The ARN of the VPC connector. + * @attribute + */ readonly vpcConnectorArn: string; /** @@ -121,9 +121,9 @@ export class VpcConnector extends cdk.Resource implements IVpcConnector { readonly vpcConnectorRevision: number; /** - * The name of the VPC connector. - * @attribute - */ + * The name of the VPC connector. + * @attribute + */ readonly vpcConnectorName: string; /** diff --git a/packages/@aws-cdk/aws-gamelift-alpha/lib/alias.ts b/packages/@aws-cdk/aws-gamelift-alpha/lib/alias.ts index ba75175c489e2..1b0e359791f1f 100644 --- a/packages/@aws-cdk/aws-gamelift-alpha/lib/alias.ts +++ b/packages/@aws-cdk/aws-gamelift-alpha/lib/alias.ts @@ -186,8 +186,8 @@ export class Alias extends AliasBase { public readonly aliasId: string; /** - * The ARN of the alias. - */ + * The ARN of the alias. + */ public readonly aliasArn: string; /** diff --git a/packages/@aws-cdk/aws-gamelift-alpha/lib/build.ts b/packages/@aws-cdk/aws-gamelift-alpha/lib/build.ts index 51bf6fd2c78de..edb8ac74ee883 100644 --- a/packages/@aws-cdk/aws-gamelift-alpha/lib/build.ts +++ b/packages/@aws-cdk/aws-gamelift-alpha/lib/build.ts @@ -122,10 +122,10 @@ export interface BuildProps { readonly buildName?: string; /** - * Version of this build - * - * @default No version - */ + * Version of this build + * + * @default No version + */ readonly buildVersion?: string; /** diff --git a/packages/@aws-cdk/aws-gamelift-alpha/lib/fleet-base.ts b/packages/@aws-cdk/aws-gamelift-alpha/lib/fleet-base.ts index 1194243f51943..4446fbf7d3bbc 100644 --- a/packages/@aws-cdk/aws-gamelift-alpha/lib/fleet-base.ts +++ b/packages/@aws-cdk/aws-gamelift-alpha/lib/fleet-base.ts @@ -443,8 +443,8 @@ export abstract class FleetBase extends cdk.Resource implements IFleet { } /** - * The Identifier of the fleet. - */ + * The Identifier of the fleet. + */ public abstract readonly fleetId: string; /** diff --git a/packages/@aws-cdk/aws-gamelift-alpha/lib/game-server-group.ts b/packages/@aws-cdk/aws-gamelift-alpha/lib/game-server-group.ts index 71c607fe8b741..4411552d3a6f1 100644 --- a/packages/@aws-cdk/aws-gamelift-alpha/lib/game-server-group.ts +++ b/packages/@aws-cdk/aws-gamelift-alpha/lib/game-server-group.ts @@ -319,10 +319,10 @@ export interface GameServerGroupProps { readonly deleteOption?: DeleteOption; /** - * Indicates how GameLift FleetIQ balances the use of Spot Instances and On-Demand Instances in the game server group. - * - * @default SPOT_PREFERRED - */ + * Indicates how GameLift FleetIQ balances the use of Spot Instances and On-Demand Instances in the game server group. + * + * @default SPOT_PREFERRED + */ readonly balancingStrategy?: BalancingStrategy; } diff --git a/packages/@aws-cdk/aws-gamelift-alpha/lib/ingress-rule.ts b/packages/@aws-cdk/aws-gamelift-alpha/lib/ingress-rule.ts index 63914e41a876c..b944cfdf76d75 100644 --- a/packages/@aws-cdk/aws-gamelift-alpha/lib/ingress-rule.ts +++ b/packages/@aws-cdk/aws-gamelift-alpha/lib/ingress-rule.ts @@ -15,25 +15,25 @@ export enum Protocol { */ export interface PortProps { /** - * The protocol for the range - */ + * The protocol for the range + */ readonly protocol: Protocol; /** - * A starting value for a range of allowed port numbers. - * - * For fleets using Windows and Linux builds, only ports 1026-60000 are valid. - */ + * A starting value for a range of allowed port numbers. + * + * For fleets using Windows and Linux builds, only ports 1026-60000 are valid. + */ readonly fromPort: number; /** - * An ending value for a range of allowed port numbers. Port numbers are end-inclusive. - * This value must be higher than `fromPort`. - * - * For fleets using Windows and Linux builds, only ports 1026-60000 are valid. - * - * @default the `fromPort` value - */ + * An ending value for a range of allowed port numbers. Port numbers are end-inclusive. + * This value must be higher than `fromPort`. + * + * For fleets using Windows and Linux builds, only ports 1026-60000 are valid. + * + * @default the `fromPort` value + */ readonly toPort?: number; } @@ -42,8 +42,8 @@ export interface PortProps { */ export class Port { /** - * A single TCP port - */ + * A single TCP port + */ public static tcp(port: number): Port { return new Port({ protocol: Protocol.TCP, @@ -53,8 +53,8 @@ export class Port { } /** - * A TCP port range - */ + * A TCP port range + */ public static tcpRange(startPort: number, endPort: number) { return new Port({ protocol: Protocol.TCP, @@ -64,8 +64,8 @@ export class Port { } /** - * Any TCP traffic - */ + * Any TCP traffic + */ public static allTcp() { return new Port({ protocol: Protocol.TCP, @@ -75,8 +75,8 @@ export class Port { } /** - * A single UDP port - */ + * A single UDP port + */ public static udp(port: number): Port { return new Port({ protocol: Protocol.UDP, @@ -86,8 +86,8 @@ export class Port { } /** - * A UDP port range - */ + * A UDP port range + */ public static udpRange(startPort: number, endPort: number) { return new Port({ protocol: Protocol.UDP, @@ -97,8 +97,8 @@ export class Port { } /** - * Any UDP traffic - */ + * Any UDP traffic + */ public static allUdp() { return new Port({ protocol: Protocol.UDP, @@ -127,13 +127,13 @@ export class Port { export interface IPeer { /** - * A unique identifier for this connection peer - */ + * A unique identifier for this connection peer + */ readonly uniqueId: string; /** - * Produce the ingress rule JSON for the given connection - */ + * Produce the ingress rule JSON for the given connection + */ toJson(): any; } @@ -147,15 +147,15 @@ export interface IPeer { */ export class Peer { /** - * Create an IPv4 peer from a CIDR - */ + * Create an IPv4 peer from a CIDR + */ public static ipv4(cidrIp: string): IPeer { return new CidrIPv4(cidrIp); } /** - * Any IPv4 address - */ + * Any IPv4 address + */ public static anyIpv4(): IPeer { return new AnyIPv4(); } @@ -188,8 +188,8 @@ class CidrIPv4 implements IPeer { } /** - * Produce the ingress rule JSON for the given connection - */ + * Produce the ingress rule JSON for the given connection + */ public toJson(): any { return { ipRange: this.cidrIp }; } @@ -213,8 +213,8 @@ class AnyIPv4 extends CidrIPv4 { */ export interface IngressRule { /** - * The port range used for ingress traffic - */ + * The port range used for ingress traffic + */ readonly port: Port; /** diff --git a/packages/@aws-cdk/aws-kinesisfirehose-alpha/lib/source.ts b/packages/@aws-cdk/aws-kinesisfirehose-alpha/lib/source.ts index ad0009a123654..3bba057c6be75 100644 --- a/packages/@aws-cdk/aws-kinesisfirehose-alpha/lib/source.ts +++ b/packages/@aws-cdk/aws-kinesisfirehose-alpha/lib/source.ts @@ -8,21 +8,21 @@ import * as kinesis from 'aws-cdk-lib/aws-kinesis'; */ interface SourceConfig { /** - * Configuration for using a Kinesis Data Stream as a source for the delivery stream. - * - * This will be returned by the _bind method depending on what type of Source class is specified. - * - * @default - Kinesis Data Stream Source configuration property is not provided. - */ + * Configuration for using a Kinesis Data Stream as a source for the delivery stream. + * + * This will be returned by the _bind method depending on what type of Source class is specified. + * + * @default - Kinesis Data Stream Source configuration property is not provided. + */ readonly kinesisStreamSourceConfiguration?: CfnDeliveryStream.KinesisStreamSourceConfigurationProperty; /** - * Configuration for using an MSK (Managed Streaming for Kafka) cluster as a source for the delivery stream. - * - * This will be returned by the _bind method depending on what type of Source class is specified. - * - * @default - MSK Source configuration property is not provided. - */ + * Configuration for using an MSK (Managed Streaming for Kafka) cluster as a source for the delivery stream. + * + * This will be returned by the _bind method depending on what type of Source class is specified. + * + * @default - MSK Source configuration property is not provided. + */ readonly mskSourceConfiguration?: CfnDeliveryStream.MSKSourceConfigurationProperty; } diff --git a/packages/@aws-cdk/aws-kinesisfirehose-destinations-alpha/lib/logging-config.ts b/packages/@aws-cdk/aws-kinesisfirehose-destinations-alpha/lib/logging-config.ts index 69839e17027ae..970c30a68e08e 100644 --- a/packages/@aws-cdk/aws-kinesisfirehose-destinations-alpha/lib/logging-config.ts +++ b/packages/@aws-cdk/aws-kinesisfirehose-destinations-alpha/lib/logging-config.ts @@ -8,17 +8,17 @@ import * as logs from 'aws-cdk-lib/aws-logs'; */ export interface ILoggingConfig { /** - * If true, log errors when data transformation or data delivery fails. - * - * `true` when using `EnableLogging`, `false` when using `DisableLogging`. - */ + * If true, log errors when data transformation or data delivery fails. + * + * `true` when using `EnableLogging`, `false` when using `DisableLogging`. + */ readonly logging: boolean; /** - * The CloudWatch log group where log streams will be created to hold error logs. - * - * @default - if `logging` is set to `true`, a log group will be created for you. - */ + * The CloudWatch log group where log streams will be created to hold error logs. + * + * @default - if `logging` is set to `true`, a log group will be created for you. + */ readonly logGroup?: logs.ILogGroup; } diff --git a/packages/@aws-cdk/aws-pipes-alpha/lib/pipe.ts b/packages/@aws-cdk/aws-pipes-alpha/lib/pipe.ts index f350a38bff3fb..6056bcc3d79ac 100644 --- a/packages/@aws-cdk/aws-pipes-alpha/lib/pipe.ts +++ b/packages/@aws-cdk/aws-pipes-alpha/lib/pipe.ts @@ -115,25 +115,25 @@ export interface PipeProps { readonly logDestinations?: ILogDestination[]; /** - * The level of logging detail to include. - * - * This applies to all log destinations for the pipe. - * - * @see https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-pipes-logs.html - * @default - LogLevel.ERROR - */ + * The level of logging detail to include. + * + * This applies to all log destinations for the pipe. + * + * @see https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-pipes-logs.html + * @default - LogLevel.ERROR + */ readonly logLevel?: LogLevel; /** - * Whether the execution data (specifically, the `payload` , `awsRequest` , and `awsResponse` fields) is included in the log messages for this pipe. - * - * This applies to all log destinations for the pipe. - * - * For more information, see [Including execution data in logs](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-pipes-logs.html#eb-pipes-logs-execution-data) and the [message schema](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-pipes-logs-schema.html) in the *Amazon EventBridge User Guide* . - * - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-pipes-pipe-pipelogconfiguration.html#cfn-pipes-pipe-pipelogconfiguration-includeexecutiondata - * @default - none - */ + * Whether the execution data (specifically, the `payload` , `awsRequest` , and `awsResponse` fields) is included in the log messages for this pipe. + * + * This applies to all log destinations for the pipe. + * + * For more information, see [Including execution data in logs](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-pipes-logs.html#eb-pipes-logs-execution-data) and the [message schema](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-pipes-logs-schema.html) in the *Amazon EventBridge User Guide* . + * + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-pipes-pipe-pipelogconfiguration.html#cfn-pipes-pipe-pipelogconfiguration-includeexecutiondata + * @default - none + */ readonly logIncludeExecutionData?: IncludeExecutionData[]; /** diff --git a/packages/@aws-cdk/aws-pipes-sources-alpha/lib/sqs.ts b/packages/@aws-cdk/aws-pipes-sources-alpha/lib/sqs.ts index 0b43b3a643777..38a4c61f38db0 100644 --- a/packages/@aws-cdk/aws-pipes-sources-alpha/lib/sqs.ts +++ b/packages/@aws-cdk/aws-pipes-sources-alpha/lib/sqs.ts @@ -8,11 +8,11 @@ import { IQueue } from 'aws-cdk-lib/aws-sqs'; */ export interface SqsSourceParameters { /** - * The maximum number of records to include in each batch. - * - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-pipes-pipe-pipesourcesqsqueueparameters.html#cfn-pipes-pipe-pipesourcesqsqueueparameters-batchsize - * @default 10 - */ + * The maximum number of records to include in each batch. + * + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-pipes-pipe-pipesourcesqsqueueparameters.html#cfn-pipes-pipe-pipesourcesqsqueueparameters-batchsize + * @default 10 + */ readonly batchSize?: number; /** diff --git a/packages/@aws-cdk/aws-pipes-sources-alpha/lib/streamSource.ts b/packages/@aws-cdk/aws-pipes-sources-alpha/lib/streamSource.ts index c15454aac85a9..6b0842ae26f5a 100644 --- a/packages/@aws-cdk/aws-pipes-sources-alpha/lib/streamSource.ts +++ b/packages/@aws-cdk/aws-pipes-sources-alpha/lib/streamSource.ts @@ -17,15 +17,15 @@ export interface StreamSourceParameters { readonly batchSize?: number; /** - * Define the target to send dead-letter queue events to. - * - * The dead-letter queue stores any events that are not successfully delivered to a Pipes target after all retry attempts are exhausted. - * You can then resolve the issue that caused the failed invocations and replay the events at a later time. - * In some cases, such as when access is denied to a resource, events are sent directly to the dead-letter queue and are not retried. - * - * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-pipes-pipe-pipesourcekinesisstreamparameters.html#cfn-pipes-pipe-pipesourcekinesisstreamparameters-deadletterconfig - * @default - no dead-letter queue or topic - */ + * Define the target to send dead-letter queue events to. + * + * The dead-letter queue stores any events that are not successfully delivered to a Pipes target after all retry attempts are exhausted. + * You can then resolve the issue that caused the failed invocations and replay the events at a later time. + * In some cases, such as when access is denied to a resource, events are sent directly to the dead-letter queue and are not retried. + * + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-pipes-pipe-pipesourcekinesisstreamparameters.html#cfn-pipes-pipe-pipesourcekinesisstreamparameters-deadletterconfig + * @default - no dead-letter queue or topic + */ readonly deadLetterTarget?: IQueue | ITopic; /** diff --git a/packages/@aws-cdk/aws-redshift-alpha/lib/table.ts b/packages/@aws-cdk/aws-redshift-alpha/lib/table.ts index c8d31d646e801..efa6d2d32e5f0 100644 --- a/packages/@aws-cdk/aws-redshift-alpha/lib/table.ts +++ b/packages/@aws-cdk/aws-redshift-alpha/lib/table.ts @@ -144,10 +144,10 @@ export interface TableProps extends DatabaseOptions { readonly removalPolicy?: cdk.RemovalPolicy; /** - * A comment to attach to the table. - * - * @default - no comment - */ + * A comment to attach to the table. + * + * @default - no comment + */ readonly tableComment?: string; } diff --git a/packages/@aws-cdk/aws-route53resolver-alpha/lib/firewall-domain-list.ts b/packages/@aws-cdk/aws-route53resolver-alpha/lib/firewall-domain-list.ts index cad3a21ffc7ef..162588ea0327a 100644 --- a/packages/@aws-cdk/aws-route53resolver-alpha/lib/firewall-domain-list.ts +++ b/packages/@aws-cdk/aws-route53resolver-alpha/lib/firewall-domain-list.ts @@ -164,47 +164,47 @@ export class FirewallDomainList extends Resource implements IFirewallDomainList public readonly firewallDomainListArn: string; /** - * The date and time that the domain list was created - * @attribute - */ + * The date and time that the domain list was created + * @attribute + */ public readonly firewallDomainListCreationTime: string; /** - * The creator request ID - * @attribute - */ + * The creator request ID + * @attribute + */ public readonly firewallDomainListCreatorRequestId: string; /** - * The number of domains in the list - * @attribute - */ + * The number of domains in the list + * @attribute + */ public readonly firewallDomainListDomainCount: number; /** - * The owner of the list, used only for lists that are not managed by you. - * For example, the managed domain list `AWSManagedDomainsMalwareDomainList` - * has the managed owner name `Route 53 Resolver DNS Firewall`. - * @attribute - */ + * The owner of the list, used only for lists that are not managed by you. + * For example, the managed domain list `AWSManagedDomainsMalwareDomainList` + * has the managed owner name `Route 53 Resolver DNS Firewall`. + * @attribute + */ public readonly firewallDomainListManagedOwnerName: string; /** - * The date and time that the domain list was last modified - * @attribute - */ + * The date and time that the domain list was last modified + * @attribute + */ public readonly firewallDomainListModificationTime: string; /** - * The status of the domain list - * @attribute - */ + * The status of the domain list + * @attribute + */ public readonly firewallDomainListStatus: string; /** - * Additional information about the status of the rule group - * @attribute - */ + * Additional information about the status of the rule group + * @attribute + */ public readonly firewallDomainListStatusMessage: string; constructor(scope: Construct, id: string, props: FirewallDomainListProps) { diff --git a/packages/@aws-cdk/aws-route53resolver-alpha/lib/firewall-rule-group-association.ts b/packages/@aws-cdk/aws-route53resolver-alpha/lib/firewall-rule-group-association.ts index 2197762b32da6..f7091e2eca2ef 100644 --- a/packages/@aws-cdk/aws-route53resolver-alpha/lib/firewall-rule-group-association.ts +++ b/packages/@aws-cdk/aws-route53resolver-alpha/lib/firewall-rule-group-association.ts @@ -60,15 +60,15 @@ export class FirewallRuleGroupAssociation extends Resource { public readonly firewallRuleGroupAssociationArn: string; /** - * The date and time that the association was created - * @attribute - */ + * The date and time that the association was created + * @attribute + */ public readonly firewallRuleGroupAssociationCreationTime: string; /** - * The creator request ID - * @attribute - */ + * The creator request ID + * @attribute + */ public readonly firewallRuleGroupAssociationCreatorRequestId: string; /** @@ -79,29 +79,29 @@ export class FirewallRuleGroupAssociation extends Resource { public readonly firewallRuleGroupAssociationId: string; /** - * The owner of the association, used only for lists that are not managed by you. - * If you use AWS Firewall Manager to manage your firewallls from DNS Firewall, - * then this reports Firewall Manager as the managed owner. - * @attribute - */ + * The owner of the association, used only for lists that are not managed by you. + * If you use AWS Firewall Manager to manage your firewallls from DNS Firewall, + * then this reports Firewall Manager as the managed owner. + * @attribute + */ public readonly firewallRuleGroupAssociationManagedOwnerName: string; /** - * The date and time that the association was last modified - * @attribute - */ + * The date and time that the association was last modified + * @attribute + */ public readonly firewallRuleGroupAssociationModificationTime: string; /** - * The status of the association - * @attribute - */ + * The status of the association + * @attribute + */ public readonly firewallRuleGroupAssociationStatus: string; /** - * Additional information about the status of the association - * @attribute - */ + * Additional information about the status of the association + * @attribute + */ public readonly firewallRuleGroupAssociationStatusMessage: string; constructor(scope: Construct, id: string, props: FirewallRuleGroupAssociationProps) { diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry-alpha/lib/target-application.ts b/packages/@aws-cdk/aws-servicecatalogappregistry-alpha/lib/target-application.ts index 6c1dd508fc16a..2da1b4d8bfdfa 100644 --- a/packages/@aws-cdk/aws-servicecatalogappregistry-alpha/lib/target-application.ts +++ b/packages/@aws-cdk/aws-servicecatalogappregistry-alpha/lib/target-application.ts @@ -8,20 +8,20 @@ import { hashValues } from './common'; */ export interface TargetApplicationCommonOptions extends cdk.StackProps { /** - * Stack ID in which application will be created or imported. The id of a stack is also the identifier that you use to - * refer to it in the [AWS CDK Toolkit](https://docs.aws.amazon.com/cdk/v2/guide/cli.html). - * - * @default - The value of `stackName` will be used as stack id - * @deprecated - Use `stackName` instead to control the name and id of the stack - */ + * Stack ID in which application will be created or imported. The id of a stack is also the identifier that you use to + * refer to it in the [AWS CDK Toolkit](https://docs.aws.amazon.com/cdk/v2/guide/cli.html). + * + * @default - The value of `stackName` will be used as stack id + * @deprecated - Use `stackName` instead to control the name and id of the stack + */ readonly stackId?: string; /** - * Determines whether any cross-account stacks defined in the CDK app definition should be associated with the - * target application. If set to `true`, the application will first be shared with the accounts that own the stacks. - * - * @default - false - */ + * Determines whether any cross-account stacks defined in the CDK app definition should be associated with the + * target application. If set to `true`, the application will first be shared with the accounts that own the stacks. + * + * @default - false + */ readonly associateCrossAccountStacks?: boolean; } @@ -30,15 +30,15 @@ export interface TargetApplicationCommonOptions extends cdk.StackProps { */ export interface CreateTargetApplicationOptions extends TargetApplicationCommonOptions { /** - * Enforces a particular physical application name. - */ + * Enforces a particular physical application name. + */ readonly applicationName: string; /** - * Application description. - * - * @default - Application containing stacks deployed via CDK. - */ + * Application description. + * + * @default - Application containing stacks deployed via CDK. + */ readonly applicationDescription?: string; /** @@ -54,8 +54,8 @@ export interface CreateTargetApplicationOptions extends TargetApplicationCommonO */ export interface ExistingTargetApplicationOptions extends TargetApplicationCommonOptions { /** - * Enforces a particular application arn. - */ + * Enforces a particular application arn. + */ readonly applicationArnValue: string; } @@ -65,24 +65,24 @@ export interface ExistingTargetApplicationOptions extends TargetApplicationCommo */ export abstract class TargetApplication { /** - * Factory method to build the input using the provided - * application ARN. - */ + * Factory method to build the input using the provided + * application ARN. + */ public static existingApplicationFromArn(options: ExistingTargetApplicationOptions) : TargetApplication { return new ExistingTargetApplication(options); } /** - * Factory method to build the input using the provided - * application name and stack props. - */ + * Factory method to build the input using the provided + * application name and stack props. + */ public static createApplicationStack(options: CreateTargetApplicationOptions) : TargetApplication { return new CreateTargetApplication(options); } /** - * Called when the ApplicationAssociator is initialized - */ + * Called when the ApplicationAssociator is initialized + */ public abstract bind(scope: Construct): BindTargetApplicationResult; } diff --git a/packages/@aws-cdk/cdk-cli-wrapper/lib/commands/common.ts b/packages/@aws-cdk/cdk-cli-wrapper/lib/commands/common.ts index 393307c260e5b..4dab7838b1109 100644 --- a/packages/@aws-cdk/cdk-cli-wrapper/lib/commands/common.ts +++ b/packages/@aws-cdk/cdk-cli-wrapper/lib/commands/common.ts @@ -89,7 +89,7 @@ export interface DefaultCdkOptions { readonly lookups?: boolean; /** - * Ignores synthesis errors, which will likely produce an invalid output + * Ignores synthesis errors, which will likely produce an invalid output * * @default false */ diff --git a/packages/@aws-cdk/cli-lib-alpha/lib/commands/common.ts b/packages/@aws-cdk/cli-lib-alpha/lib/commands/common.ts index df6413a2a70a4..3602ab6cadb8b 100644 --- a/packages/@aws-cdk/cli-lib-alpha/lib/commands/common.ts +++ b/packages/@aws-cdk/cli-lib-alpha/lib/commands/common.ts @@ -68,7 +68,7 @@ export interface SharedOptions { readonly lookups?: boolean; /** - * Ignores synthesis errors, which will likely produce an invalid output + * Ignores synthesis errors, which will likely produce an invalid output * * @default false */ diff --git a/packages/@aws-cdk/integ-runner/lib/runner/integration-tests.ts b/packages/@aws-cdk/integ-runner/lib/runner/integration-tests.ts index ecda707117ff8..503b4068cef0c 100644 --- a/packages/@aws-cdk/integ-runner/lib/runner/integration-tests.ts +++ b/packages/@aws-cdk/integ-runner/lib/runner/integration-tests.ts @@ -160,10 +160,10 @@ export interface IntegrationTestsDiscoveryOptions { readonly exclude?: boolean; /** - * List of tests to include (or exclude if `exclude=true`) - * - * @default - all matched files - */ + * List of tests to include (or exclude if `exclude=true`) + * + * @default - all matched files + */ readonly tests?: string[]; /** diff --git a/packages/aws-cdk-lib/aws-apigatewayv2/lib/websocket/api.ts b/packages/aws-cdk-lib/aws-apigatewayv2/lib/websocket/api.ts index 569c05f427c74..195c46812db2a 100644 --- a/packages/aws-cdk-lib/aws-apigatewayv2/lib/websocket/api.ts +++ b/packages/aws-cdk-lib/aws-apigatewayv2/lib/websocket/api.ts @@ -23,10 +23,10 @@ export class WebSocketApiKeySelectionExpression { public static readonly HEADER_X_API_KEY = new WebSocketApiKeySelectionExpression('$request.header.x-api-key'); /** - * The API will extract the key value from the `usageIdentifierKey` attribute in the `context` map, - * returned by the Lambda Authorizer. - * See https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-lambda-authorizer-output.html - */ + * The API will extract the key value from the `usageIdentifierKey` attribute in the `context` map, + * returned by the Lambda Authorizer. + * See https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-lambda-authorizer-output.html + */ public static readonly AUTHORIZER_USAGE_IDENTIFIER_KEY = new WebSocketApiKeySelectionExpression('$context.authorizer.usageIdentifierKey'); /** diff --git a/packages/aws-cdk-lib/aws-appsync/lib/schema.ts b/packages/aws-cdk-lib/aws-appsync/lib/schema.ts index d6ef44b4b4b8a..fb7f82107ead7 100644 --- a/packages/aws-cdk-lib/aws-appsync/lib/schema.ts +++ b/packages/aws-cdk-lib/aws-appsync/lib/schema.ts @@ -8,13 +8,13 @@ import { IGraphqlApi } from './graphqlapi-base'; */ export interface ISchemaConfig { /** - * The ID of the api the schema is bound to - */ + * The ID of the api the schema is bound to + */ apiId: string; /** - * The schema definition string - */ + * The schema definition string + */ definition: string; } @@ -33,12 +33,12 @@ export interface SchemaBindOptions {} */ export interface ISchema { /** - * Binds a schema string to a GraphQlApi - * - * @returns ISchemaConfig with apiId and schema definition string - * @param api the api to bind the schema to - * @param options configuration for bind behavior - */ + * Binds a schema string to a GraphQlApi + * + * @returns ISchemaConfig with apiId and schema definition string + * @param api the api to bind the schema to + * @param options configuration for bind behavior + */ bind(api: IGraphqlApi, options?: SchemaBindOptions): ISchemaConfig; } diff --git a/packages/aws-cdk-lib/aws-batch/lib/linux-parameters.ts b/packages/aws-cdk-lib/aws-batch/lib/linux-parameters.ts index c24cebd6c5781..d525df6b963b2 100644 --- a/packages/aws-cdk-lib/aws-batch/lib/linux-parameters.ts +++ b/packages/aws-cdk-lib/aws-batch/lib/linux-parameters.ts @@ -32,18 +32,18 @@ export interface LinuxParametersProps { readonly maxSwap?: cdk.Size; /** - * This allows you to tune a container's memory swappiness behavior. This parameter - * maps to the --memory-swappiness option to docker run. The swappiness relates - * to the kernel's tendency to swap memory. A value of 0 will cause swapping to - * not happen unless absolutely necessary. A value of 100 will cause pages to - * be swapped very aggressively. - * - * This parameter is only supported when you are using the EC2 launch type. - * Accepted values are whole numbers between 0 and 100. If a value is not - * specified for maxSwap then this parameter is ignored. - * - * @default 60 - */ + * This allows you to tune a container's memory swappiness behavior. This parameter + * maps to the --memory-swappiness option to docker run. The swappiness relates + * to the kernel's tendency to swap memory. A value of 0 will cause swapping to + * not happen unless absolutely necessary. A value of 100 will cause pages to + * be swapped very aggressively. + * + * This parameter is only supported when you are using the EC2 launch type. + * Accepted values are whole numbers between 0 and 100. If a value is not + * specified for maxSwap then this parameter is ignored. + * + * @default 60 + */ readonly swappiness?: number; } diff --git a/packages/aws-cdk-lib/aws-certificatemanager/lib/certificate-base.ts b/packages/aws-cdk-lib/aws-certificatemanager/lib/certificate-base.ts index 6cd1e913fd439..3be3e4049edf8 100644 --- a/packages/aws-cdk-lib/aws-certificatemanager/lib/certificate-base.ts +++ b/packages/aws-cdk-lib/aws-certificatemanager/lib/certificate-base.ts @@ -12,10 +12,10 @@ export abstract class CertificateBase extends Resource implements ICertificate { public abstract readonly certificateArn: string; /** - * If the certificate is provisionned in a different region than the - * containing stack, this should be the region in which the certificate lives - * so we can correctly create `Metric` instances. - */ + * If the certificate is provisionned in a different region than the + * containing stack, this should be the region in which the certificate lives + * so we can correctly create `Metric` instances. + */ protected readonly region?: string; public metricDaysToExpiry(props?: cloudwatch.MetricOptions): cloudwatch.Metric { diff --git a/packages/aws-cdk-lib/aws-cloudfront/lib/distribution.ts b/packages/aws-cdk-lib/aws-cloudfront/lib/distribution.ts index 1dc2fe099ac50..70f3fdfae0265 100644 --- a/packages/aws-cdk-lib/aws-cloudfront/lib/distribution.ts +++ b/packages/aws-cdk-lib/aws-cloudfront/lib/distribution.ts @@ -232,32 +232,32 @@ export interface DistributionProps { readonly errorResponses?: ErrorResponse[]; /** - * The minimum version of the SSL protocol that you want CloudFront to use for HTTPS connections. - * - * CloudFront serves your objects only to browsers or devices that support at - * least the SSL version that you specify. - * - * @default - SecurityPolicyProtocol.TLS_V1_2_2021 if the '@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021' feature flag is set; otherwise, SecurityPolicyProtocol.TLS_V1_2_2019. - */ + * The minimum version of the SSL protocol that you want CloudFront to use for HTTPS connections. + * + * CloudFront serves your objects only to browsers or devices that support at + * least the SSL version that you specify. + * + * @default - SecurityPolicyProtocol.TLS_V1_2_2021 if the '@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021' feature flag is set; otherwise, SecurityPolicyProtocol.TLS_V1_2_2019. + */ readonly minimumProtocolVersion?: SecurityPolicyProtocol; /** - * The SSL method CloudFront will use for your distribution. - * - * Server Name Indication (SNI) - is an extension to the TLS computer networking protocol by which a client indicates - * which hostname it is attempting to connect to at the start of the handshaking process. This allows a server to present - * multiple certificates on the same IP address and TCP port number and hence allows multiple secure (HTTPS) websites - * (or any other service over TLS) to be served by the same IP address without requiring all those sites to use the same certificate. - * - * CloudFront can use SNI to host multiple distributions on the same IP - which a large majority of clients will support. - * - * If your clients cannot support SNI however - CloudFront can use dedicated IPs for your distribution - but there is a prorated monthly charge for - * using this feature. By default, we use SNI - but you can optionally enable dedicated IPs (VIP). - * - * See the CloudFront SSL for more details about pricing : https://aws.amazon.com/cloudfront/custom-ssl-domains/ - * - * @default SSLMethod.SNI - */ + * The SSL method CloudFront will use for your distribution. + * + * Server Name Indication (SNI) - is an extension to the TLS computer networking protocol by which a client indicates + * which hostname it is attempting to connect to at the start of the handshaking process. This allows a server to present + * multiple certificates on the same IP address and TCP port number and hence allows multiple secure (HTTPS) websites + * (or any other service over TLS) to be served by the same IP address without requiring all those sites to use the same certificate. + * + * CloudFront can use SNI to host multiple distributions on the same IP - which a large majority of clients will support. + * + * If your clients cannot support SNI however - CloudFront can use dedicated IPs for your distribution - but there is a prorated monthly charge for + * using this feature. By default, we use SNI - but you can optionally enable dedicated IPs (VIP). + * + * See the CloudFront SSL for more details about pricing : https://aws.amazon.com/cloudfront/custom-ssl-domains/ + * + * @default SSLMethod.SNI + */ readonly sslSupportMethod?: SSLMethod; /** diff --git a/packages/aws-cdk-lib/aws-cloudfront/lib/endpoint.ts b/packages/aws-cdk-lib/aws-cloudfront/lib/endpoint.ts index d7069944f2560..65d049e17e0ac 100644 --- a/packages/aws-cdk-lib/aws-cloudfront/lib/endpoint.ts +++ b/packages/aws-cdk-lib/aws-cloudfront/lib/endpoint.ts @@ -9,10 +9,10 @@ import { PhysicalName } from '../../core'; export abstract class Endpoint { /** - * Configure a Kinesis Stream Endpoint for Realtime Log Config - * - * @default - a role will be created and used across your endpoints - */ + * Configure a Kinesis Stream Endpoint for Realtime Log Config + * + * @default - a role will be created and used across your endpoints + */ public static fromKinesisStream(stream: kinesis.IStream, role?: iam.IRole): Endpoint { return new (class extends Endpoint { public _renderEndpoint(scope: Construct) { diff --git a/packages/aws-cdk-lib/aws-codebuild/lib/build-spec.ts b/packages/aws-cdk-lib/aws-codebuild/lib/build-spec.ts index 930ade02086f3..f83e33440eaa0 100644 --- a/packages/aws-cdk-lib/aws-codebuild/lib/build-spec.ts +++ b/packages/aws-cdk-lib/aws-codebuild/lib/build-spec.ts @@ -31,10 +31,10 @@ export abstract class BuildSpec { } /** - * Use the contents of a local file as the build spec string - * - * Use this if you have a local .yml or .json file that you want to use as the buildspec - */ + * Use the contents of a local file as the build spec string + * + * Use this if you have a local .yml or .json file that you want to use as the buildspec + */ public static fromAsset(path: string): BuildSpec { return new AssetBuildSpec(path); } diff --git a/packages/aws-cdk-lib/aws-codedeploy/lib/ecs/deployment-group.ts b/packages/aws-cdk-lib/aws-codedeploy/lib/ecs/deployment-group.ts index 9ff4b247952f4..1acee55f5889b 100644 --- a/packages/aws-cdk-lib/aws-codedeploy/lib/ecs/deployment-group.ts +++ b/packages/aws-cdk-lib/aws-codedeploy/lib/ecs/deployment-group.ts @@ -97,17 +97,17 @@ export interface EcsBlueGreenDeploymentConfig { readonly deploymentApprovalWaitTime?: cdk.Duration; /** - * Specify how long CodeDeploy waits before it terminates the original 'blue' ECS task set when a blue-green deployment is complete. - * - * During this wait time, CodeDeploy will continue to monitor any CloudWatch alarms specified for the deployment group, - * and the deployment group can be configured to automatically roll back if those alarms fire. Once CodeDeploy begins to - * terminate the 'blue' ECS task set, the deployment can no longer be rolled back, manually or automatically. - * - * By default, the deployment will immediately terminate the 'blue' ECS task set after production traffic is successfully - * routed to the 'green' ECS task set. - * - * @default 0 - */ + * Specify how long CodeDeploy waits before it terminates the original 'blue' ECS task set when a blue-green deployment is complete. + * + * During this wait time, CodeDeploy will continue to monitor any CloudWatch alarms specified for the deployment group, + * and the deployment group can be configured to automatically roll back if those alarms fire. Once CodeDeploy begins to + * terminate the 'blue' ECS task set, the deployment can no longer be rolled back, manually or automatically. + * + * By default, the deployment will immediately terminate the 'blue' ECS task set after production traffic is successfully + * routed to the 'green' ECS task set. + * + * @default 0 + */ readonly terminationWaitTime?: cdk.Duration; } diff --git a/packages/aws-cdk-lib/aws-cognito/lib/user-pool-idps/oidc.ts b/packages/aws-cdk-lib/aws-cognito/lib/user-pool-idps/oidc.ts index c17b48a799bdc..72e6e92c5ed4e 100644 --- a/packages/aws-cdk-lib/aws-cognito/lib/user-pool-idps/oidc.ts +++ b/packages/aws-cdk-lib/aws-cognito/lib/user-pool-idps/oidc.ts @@ -72,17 +72,17 @@ export interface OidcEndpoints { readonly authorization: string; /** - * Token endpoint - */ + * Token endpoint + */ readonly token: string; /** - * UserInfo endpoint - */ + * UserInfo endpoint + */ readonly userInfo: string; /** - * Jwks_uri endpoint + * Jwks_uri endpoint */ readonly jwksUri: string; } diff --git a/packages/aws-cdk-lib/aws-config/lib/rule.ts b/packages/aws-cdk-lib/aws-config/lib/rule.ts index 81285ebb87d12..9b9dc866b645b 100644 --- a/packages/aws-cdk-lib/aws-config/lib/rule.ts +++ b/packages/aws-cdk-lib/aws-config/lib/rule.ts @@ -1319,9 +1319,9 @@ export class ManagedRuleIdentifiers { */ public static readonly EKS_CLUSTER_OLDEST_SUPPORTED_VERSION = 'EKS_CLUSTER_OLDEST_SUPPORTED_VERSION'; /** - * Checks if an Amazon Elastic Kubernetes Service (EKS) cluster is running a supported Kubernetes version. - * @see https://docs.aws.amazon.com/config/latest/developerguide/eks-cluster-supported-version.html - */ + * Checks if an Amazon Elastic Kubernetes Service (EKS) cluster is running a supported Kubernetes version. + * @see https://docs.aws.amazon.com/config/latest/developerguide/eks-cluster-supported-version.html + */ public static readonly EKS_CLUSTER_SUPPORTED_VERSION = 'EKS_CLUSTER_SUPPORTED_VERSION'; /** * Checks whether Amazon Elastic Kubernetes Service (Amazon EKS) endpoint is not publicly accessible. diff --git a/packages/aws-cdk-lib/aws-docdb/lib/cluster.ts b/packages/aws-cdk-lib/aws-docdb/lib/cluster.ts index 6701038ac2d6d..91e99ec8eeef5 100644 --- a/packages/aws-cdk-lib/aws-docdb/lib/cluster.ts +++ b/packages/aws-cdk-lib/aws-docdb/lib/cluster.ts @@ -118,31 +118,31 @@ export interface DatabaseClusterProps { readonly caCertificate?: CaCertificate; /** - * What subnets to run the DocumentDB instances in. - * - * Must be at least 2 subnets in two different AZs. - */ + * What subnets to run the DocumentDB instances in. + * + * Must be at least 2 subnets in two different AZs. + */ readonly vpc: ec2.IVpc; /** - * Where to place the instances within the VPC - * - * @default private subnets - */ + * Where to place the instances within the VPC + * + * @default private subnets + */ readonly vpcSubnets?: ec2.SubnetSelection; /** - * Security group. - * - * @default a new security group is created. - */ + * Security group. + * + * @default a new security group is created. + */ readonly securityGroup?: ec2.ISecurityGroup; /** - * The DB parameter group to associate with the instance. - * - * @default no parameter group - */ + * The DB parameter group to associate with the instance. + * + * @default no parameter group + */ readonly parameterGroup?: IClusterParameterGroup; /** @@ -211,11 +211,11 @@ export interface DatabaseClusterProps { readonly cloudWatchLogsRetention?: logs.RetentionDays; /** - * The IAM role for the Lambda function associated with the custom resource - * that sets the retention policy. - * - * @default - a new role is created. - */ + * The IAM role for the Lambda function associated with the custom resource + * that sets the retention policy. + * + * @default - a new role is created. + */ readonly cloudWatchLogsRetentionRole?: IRole; /** diff --git a/packages/aws-cdk-lib/aws-dynamodb/lib/table.ts b/packages/aws-cdk-lib/aws-dynamodb/lib/table.ts index 03d2681382544..0b381a5f90dcb 100644 --- a/packages/aws-cdk-lib/aws-dynamodb/lib/table.ts +++ b/packages/aws-cdk-lib/aws-dynamodb/lib/table.ts @@ -243,13 +243,13 @@ export interface TableOptions extends SchemaOptions { */ readonly maxReadRequestUnits?: number; /** - * The write request units for the table. Careful if you add Global Secondary Indexes, as - * those will share the table's maximum on-demand throughput. - * - * Can only be provided if billingMode is PAY_PER_REQUEST. - * - * @default - on-demand throughput is disabled - */ + * The write request units for the table. Careful if you add Global Secondary Indexes, as + * those will share the table's maximum on-demand throughput. + * + * Can only be provided if billingMode is PAY_PER_REQUEST. + * + * @default - on-demand throughput is disabled + */ readonly maxWriteRequestUnits?: number; /** diff --git a/packages/aws-cdk-lib/aws-ecs-patterns/lib/base/application-multiple-target-groups-service-base.ts b/packages/aws-cdk-lib/aws-ecs-patterns/lib/base/application-multiple-target-groups-service-base.ts index 11898cbfb511c..15032a4957839 100644 --- a/packages/aws-cdk-lib/aws-ecs-patterns/lib/base/application-multiple-target-groups-service-base.ts +++ b/packages/aws-cdk-lib/aws-ecs-patterns/lib/base/application-multiple-target-groups-service-base.ts @@ -382,7 +382,7 @@ export abstract class ApplicationMultipleTargetGroupsServiceBase extends Constru public readonly loadBalancer: ApplicationLoadBalancer; /** - * The default listener for the service (first added listener). + * The default listener for the service (first added listener). * @deprecated - Use `listeners` instead. */ public readonly listener: ApplicationListener; @@ -394,8 +394,8 @@ export abstract class ApplicationMultipleTargetGroupsServiceBase extends Constru protected logDriver?: LogDriver; /** - * The listeners of the service. - */ + * The listeners of the service. + */ public readonly listeners = new Array(); /** * The target groups of the service. diff --git a/packages/aws-cdk-lib/aws-ecs-patterns/lib/base/fargate-service-base.ts b/packages/aws-cdk-lib/aws-ecs-patterns/lib/base/fargate-service-base.ts index d8df18c5501db..838bacd046d45 100644 --- a/packages/aws-cdk-lib/aws-ecs-patterns/lib/base/fargate-service-base.ts +++ b/packages/aws-cdk-lib/aws-ecs-patterns/lib/base/fargate-service-base.ts @@ -36,40 +36,40 @@ export interface FargateServiceBaseProps { readonly cpu?: number; /** - * The amount (in MiB) of memory used by the task. - * - * This field is required and you must use one of the following values, which determines your range of valid values - * for the cpu parameter: - * - * 512 (0.5 GB), 1024 (1 GB), 2048 (2 GB) - Available cpu values: 256 (.25 vCPU) - * - * 1024 (1 GB), 2048 (2 GB), 3072 (3 GB), 4096 (4 GB) - Available cpu values: 512 (.5 vCPU) - * - * 2048 (2 GB), 3072 (3 GB), 4096 (4 GB), 5120 (5 GB), 6144 (6 GB), 7168 (7 GB), 8192 (8 GB) - Available cpu values: 1024 (1 vCPU) - * - * Between 4096 (4 GB) and 16384 (16 GB) in increments of 1024 (1 GB) - Available cpu values: 2048 (2 vCPU) - * - * Between 8192 (8 GB) and 30720 (30 GB) in increments of 1024 (1 GB) - Available cpu values: 4096 (4 vCPU) - * - * Between 16384 (16 GB) and 61440 (60 GB) in increments of 4096 (4 GB) - Available cpu values: 8192 (8 vCPU) - * - * Between 32768 (32 GB) and 122880 (120 GB) in increments of 8192 (8 GB) - Available cpu values: 16384 (16 vCPU) - * - * This default is set in the underlying FargateTaskDefinition construct. - * - * @default 512 - */ + * The amount (in MiB) of memory used by the task. + * + * This field is required and you must use one of the following values, which determines your range of valid values + * for the cpu parameter: + * + * 512 (0.5 GB), 1024 (1 GB), 2048 (2 GB) - Available cpu values: 256 (.25 vCPU) + * + * 1024 (1 GB), 2048 (2 GB), 3072 (3 GB), 4096 (4 GB) - Available cpu values: 512 (.5 vCPU) + * + * 2048 (2 GB), 3072 (3 GB), 4096 (4 GB), 5120 (5 GB), 6144 (6 GB), 7168 (7 GB), 8192 (8 GB) - Available cpu values: 1024 (1 vCPU) + * + * Between 4096 (4 GB) and 16384 (16 GB) in increments of 1024 (1 GB) - Available cpu values: 2048 (2 vCPU) + * + * Between 8192 (8 GB) and 30720 (30 GB) in increments of 1024 (1 GB) - Available cpu values: 4096 (4 vCPU) + * + * Between 16384 (16 GB) and 61440 (60 GB) in increments of 4096 (4 GB) - Available cpu values: 8192 (8 vCPU) + * + * Between 32768 (32 GB) and 122880 (120 GB) in increments of 8192 (8 GB) - Available cpu values: 16384 (16 vCPU) + * + * This default is set in the underlying FargateTaskDefinition construct. + * + * @default 512 + */ readonly memoryLimitMiB?: number; /** - * The amount (in GiB) of ephemeral storage to be allocated to the task. - * - * The minimum supported value is `21` GiB and the maximum supported value is `200` GiB. - * - * Only supported in Fargate platform version 1.4.0 or later. - * - * @default Undefined, in which case, the task will receive 20GiB ephemeral storage. - */ + * The amount (in GiB) of ephemeral storage to be allocated to the task. + * + * The minimum supported value is `21` GiB and the maximum supported value is `200` GiB. + * + * Only supported in Fargate platform version 1.4.0 or later. + * + * @default Undefined, in which case, the task will receive 20GiB ephemeral storage. + */ readonly ephemeralStorageGiB?: number; /** diff --git a/packages/aws-cdk-lib/aws-ecs-patterns/lib/base/scheduled-task-base.ts b/packages/aws-cdk-lib/aws-ecs-patterns/lib/base/scheduled-task-base.ts index 887e41b7ecea2..509c77b5cdf3d 100644 --- a/packages/aws-cdk-lib/aws-ecs-patterns/lib/base/scheduled-task-base.ts +++ b/packages/aws-cdk-lib/aws-ecs-patterns/lib/base/scheduled-task-base.ts @@ -73,10 +73,10 @@ export interface ScheduledTaskBaseProps { readonly securityGroups?: ISecurityGroup[]; /** - * Specifies whether to propagate the tags from the task definition to the task. If no value is specified, the tags are not propagated. - * - * @default - Tags will not be propagated - */ + * Specifies whether to propagate the tags from the task definition to the task. If no value is specified, the tags are not propagated. + * + * @default - Tags will not be propagated + */ readonly propagateTags?: PropagatedTagSource; /** @@ -168,10 +168,10 @@ export abstract class ScheduledTaskBase extends Construct { private readonly _securityGroups?: ISecurityGroup[]; /** - * Specifies whether to propagate the tags from the task definition to the task. If no value is specified, the tags are not propagated. - * - * @default - Tags will not be propagated - */ + * Specifies whether to propagate the tags from the task definition to the task. If no value is specified, the tags are not propagated. + * + * @default - Tags will not be propagated + */ public readonly propagateTags?: PropagatedTagSource; /** diff --git a/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts b/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts index de9ee678f04e4..fb504110aa77a 100644 --- a/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts +++ b/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts @@ -107,7 +107,7 @@ export enum MachineImageType { export class Cluster extends Resource implements ICluster { /** - * Return whether the given object is a Cluster + * Return whether the given object is a Cluster */ public static isCluster(x: any) : x is Cluster { return x !== null && typeof(x) === 'object' && CLUSTER_SYMBOL in x; diff --git a/packages/aws-cdk-lib/aws-ecs/lib/linux-parameters.ts b/packages/aws-cdk-lib/aws-ecs/lib/linux-parameters.ts index 282fd1f221599..78030d180f20d 100644 --- a/packages/aws-cdk-lib/aws-ecs/lib/linux-parameters.ts +++ b/packages/aws-cdk-lib/aws-ecs/lib/linux-parameters.ts @@ -32,18 +32,18 @@ export interface LinuxParametersProps { readonly maxSwap?: cdk.Size; /** - * This allows you to tune a container's memory swappiness behavior. This parameter - * maps to the --memory-swappiness option to docker run. The swappiness relates - * to the kernel's tendency to swap memory. A value of 0 will cause swapping to - * not happen unless absolutely necessary. A value of 100 will cause pages to - * be swapped very aggressively. - * - * This parameter is only supported when you are using the EC2 launch type. - * Accepted values are whole numbers between 0 and 100. If a value is not - * specified for maxSwap then this parameter is ignored. - * - * @default 60 - */ + * This allows you to tune a container's memory swappiness behavior. This parameter + * maps to the --memory-swappiness option to docker run. The swappiness relates + * to the kernel's tendency to swap memory. A value of 0 will cause swapping to + * not happen unless absolutely necessary. A value of 100 will cause pages to + * be swapped very aggressively. + * + * This parameter is only supported when you are using the EC2 launch type. + * Accepted values are whole numbers between 0 and 100. If a value is not + * specified for maxSwap then this parameter is ignored. + * + * @default 60 + */ readonly swappiness?: number; } diff --git a/packages/aws-cdk-lib/aws-events-targets/lib/ecs-task.ts b/packages/aws-cdk-lib/aws-events-targets/lib/ecs-task.ts index 87e5c3dd8a06c..886622d0215a0 100644 --- a/packages/aws-cdk-lib/aws-events-targets/lib/ecs-task.ts +++ b/packages/aws-cdk-lib/aws-events-targets/lib/ecs-task.ts @@ -105,33 +105,33 @@ export interface EcsTaskProps extends TargetBaseProps { readonly assignPublicIp?: boolean; /** - * Specifies whether to propagate the tags from the task definition to the task. If no value is specified, the tags are not propagated. - * - * @default - Tags will not be propagated - */ + * Specifies whether to propagate the tags from the task definition to the task. If no value is specified, the tags are not propagated. + * + * @default - Tags will not be propagated + */ readonly propagateTags?: ecs.PropagatedTagSource; /** - * The metadata that you apply to the task to help you categorize and organize them. Each tag consists of a key and an optional value, both of which you define. - * - * @default - No additional tags are applied to the task - */ + * The metadata that you apply to the task to help you categorize and organize them. Each tag consists of a key and an optional value, both of which you define. + * + * @default - No additional tags are applied to the task + */ readonly tags?: Tag[]; /** - * Whether or not to enable the execute command functionality for the containers in this task. - * If true, this enables execute command functionality on all containers in the task. - * - * @default - false - */ + * Whether or not to enable the execute command functionality for the containers in this task. + * If true, this enables execute command functionality on all containers in the task. + * + * @default - false + */ readonly enableExecuteCommand?: boolean; /** - * Specifies the launch type on which your task is running. The launch type that you specify here - * must match one of the launch type (compatibilities) of the target task. - * - * @default - 'EC2' if `isEc2Compatible` for the `taskDefinition` is true, otherwise 'FARGATE' - */ + * Specifies the launch type on which your task is running. The launch type that you specify here + * must match one of the launch type (compatibilities) of the target task. + * + * @default - 'EC2' if `isEc2Compatible` for the `taskDefinition` is true, otherwise 'FARGATE' + */ readonly launchType?: ecs.LaunchType; } diff --git a/packages/aws-cdk-lib/aws-iam/lib/role.ts b/packages/aws-cdk-lib/aws-iam/lib/role.ts index 37484fdf0f2ff..8705f132f6173 100644 --- a/packages/aws-cdk-lib/aws-iam/lib/role.ts +++ b/packages/aws-cdk-lib/aws-iam/lib/role.ts @@ -300,7 +300,7 @@ export class Role extends Resource implements IRole { } /** - * Return whether the given object is a Role + * Return whether the given object is a Role */ public static isRole(x: any) : x is Role { return x !== null && typeof(x) === 'object' && IAM_ROLE_SYMBOL in x; diff --git a/packages/aws-cdk-lib/aws-ses/lib/email-identity.ts b/packages/aws-cdk-lib/aws-ses/lib/email-identity.ts index 49ec4298d17c1..82d8e5d6b0ff5 100644 --- a/packages/aws-cdk-lib/aws-ses/lib/email-identity.ts +++ b/packages/aws-cdk-lib/aws-ses/lib/email-identity.ts @@ -187,19 +187,19 @@ export interface DkimIdentityConfig { readonly domainSigningPrivateKey?: string; /** - * A string that's used to identify a public key in the DNS configuration for - * a domain - * - * @default - use Easy DKIM - */ + * A string that's used to identify a public key in the DNS configuration for + * a domain + * + * @default - use Easy DKIM + */ readonly domainSigningSelector?: string; /** - * The key length of the future DKIM key pair to be generated. This can be changed - * at most once per day. - * - * @default EasyDkimSigningKeyLength.RSA_2048_BIT - */ + * The key length of the future DKIM key pair to be generated. This can be changed + * at most once per day. + * + * @default EasyDkimSigningKeyLength.RSA_2048_BIT + */ readonly nextSigningKeyLength?: EasyDkimSigningKeyLength; } diff --git a/packages/aws-cdk-lib/aws-stepfunctions/test/private/fake-task.ts b/packages/aws-cdk-lib/aws-stepfunctions/test/private/fake-task.ts index 20b4a38e391fc..fe5c69b880230 100644 --- a/packages/aws-cdk-lib/aws-stepfunctions/test/private/fake-task.ts +++ b/packages/aws-cdk-lib/aws-stepfunctions/test/private/fake-task.ts @@ -16,8 +16,8 @@ export class FakeTask extends sfn.TaskStateBase { } /** - * @internal - */ + * @internal + */ protected _renderTask(): any { return { Resource: 'my-resource', diff --git a/packages/aws-cdk-lib/aws-synthetics/lib/runtime.ts b/packages/aws-cdk-lib/aws-synthetics/lib/runtime.ts index a44f914678a52..e41cfae47fa11 100644 --- a/packages/aws-cdk-lib/aws-synthetics/lib/runtime.ts +++ b/packages/aws-cdk-lib/aws-synthetics/lib/runtime.ts @@ -349,9 +349,9 @@ export class Runtime { public static readonly SYNTHETICS_PYTHON_SELENIUM_4_0 = new Runtime('syn-python-selenium-4.0', RuntimeFamily.PYTHON); /** - * @param name The name of the runtime version - * @param family The Lambda runtime family - */ + * @param name The name of the runtime version + * @param family The Lambda runtime family + */ public constructor(public readonly name: string, public readonly family: RuntimeFamily) { } } diff --git a/packages/aws-cdk/lib/api/deployments.ts b/packages/aws-cdk/lib/api/deployments.ts index a2e729ce30689..16c87b07adc42 100644 --- a/packages/aws-cdk/lib/api/deployments.ts +++ b/packages/aws-cdk/lib/api/deployments.ts @@ -711,23 +711,23 @@ export class Deployments { } /** - * Try to use the bootstrap lookupRole. There are two scenarios that are handled here - * 1. The lookup role may not exist (it was added in bootstrap stack version 7) - * 2. The lookup role may not have the correct permissions (ReadOnlyAccess was added in - * bootstrap stack version 8) - * - * In the case of 1 (lookup role doesn't exist) `forEnvironment` will either: - * 1. Return the default credentials if the default credentials are for the stack account - * 2. Throw an error if the default credentials are not for the stack account. - * - * If we successfully assume the lookup role we then proceed to 2 and check whether the bootstrap - * stack version is valid. If it is not we throw an error which should be handled in the calling - * function (and fallback to use a different role, etc) - * - * If we do not successfully assume the lookup role, but do get back the default credentials - * then return those and note that we are returning the default credentials. The calling - * function can then decide to use them or fallback to another role. - */ + * Try to use the bootstrap lookupRole. There are two scenarios that are handled here + * 1. The lookup role may not exist (it was added in bootstrap stack version 7) + * 2. The lookup role may not have the correct permissions (ReadOnlyAccess was added in + * bootstrap stack version 8) + * + * In the case of 1 (lookup role doesn't exist) `forEnvironment` will either: + * 1. Return the default credentials if the default credentials are for the stack account + * 2. Throw an error if the default credentials are not for the stack account. + * + * If we successfully assume the lookup role we then proceed to 2 and check whether the bootstrap + * stack version is valid. If it is not we throw an error which should be handled in the calling + * function (and fallback to use a different role, etc) + * + * If we do not successfully assume the lookup role, but do get back the default credentials + * then return those and note that we are returning the default credentials. The calling + * function can then decide to use them or fallback to another role. + */ public async prepareSdkWithLookupRoleFor( stack: cxapi.CloudFormationStackArtifact, ): Promise { From fee2cf88c58c6c1f25b9e6fad87c8042de464fd9 Mon Sep 17 00:00:00 2001 From: Atanas Pamukchiev Date: Wed, 23 Oct 2024 18:53:01 +0200 Subject: [PATCH 2/5] feat(cli): add ability to configure hotswap properties for ECS (#30511) ### Issue #29618 ### Reason for this change We aim to speed up deployment times in our development environment by using the hotswap feature. However, our services have dependencies on each other, and the current hotswap behavior is too disruptive. ### Description of changes We modified the hotswap implementation for ECS services to pass the `minimumHealthyPercent` and `maximumHealthyPercent` configurable parameters. These parameters are exposed to the cli and can be passed as `--hotswap-ecs-minimum-healthy-percent ` and `--hotswap-ecs-maximum-healthy-percent ` The implementation is careful to maintain the existing behaviour. That is, if none of the new flags is used, the current `minimumHealthyPercent = 0` and `maximumHealthyPercent = undefined` values are used. ### Description of how you validated changes We added a unit test validating that the correct values are passed to the task definition. We also executed using the locally built version of cdk validating that the behavior is as expected: the parameters are respected during hotswap deployments, and the existing API is maintained. ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../tests/cli-integ-tests/cli.integtest.ts | 52 +++++++++++ packages/aws-cdk/README.md | 13 +++ packages/aws-cdk/lib/api/deploy-stack.ts | 10 +- packages/aws-cdk/lib/api/deployments.ts | 8 +- .../aws-cdk/lib/api/hotswap-deployments.ts | 31 +++++-- packages/aws-cdk/lib/api/hotswap/common.ts | 46 ++++++++++ .../aws-cdk/lib/api/hotswap/ecs-services.ts | 14 ++- packages/aws-cdk/lib/cdk-toolkit.ts | 11 ++- packages/aws-cdk/lib/settings.ts | 6 ++ .../aws-cdk/test/api/deploy-stack.test.ts | 4 +- .../ecs-services-hotswap-deployments.test.ts | 91 ++++++++++++++++++- .../test/api/hotswap/hotswap-test-setup.ts | 6 +- 12 files changed, 272 insertions(+), 20 deletions(-) diff --git a/packages/@aws-cdk-testing/cli-integ/tests/cli-integ-tests/cli.integtest.ts b/packages/@aws-cdk-testing/cli-integ/tests/cli-integ-tests/cli.integtest.ts index a7365c8a1b993..b1c0d4f62bbad 100644 --- a/packages/@aws-cdk-testing/cli-integ/tests/cli-integ-tests/cli.integtest.ts +++ b/packages/@aws-cdk-testing/cli-integ/tests/cli-integ-tests/cli.integtest.ts @@ -2301,6 +2301,58 @@ integTest('hotswap deployment supports AppSync APIs with many functions', }), ); +integTest('hotswap ECS deployment respects properties override', withDefaultFixture(async (fixture) => { + // Update the CDK context with the new ECS properties + let ecsMinimumHealthyPercent = 100; + let ecsMaximumHealthyPercent = 200; + let cdkJson = JSON.parse(await fs.readFile(path.join(fixture.integTestDir, 'cdk.json'), 'utf8')); + cdkJson = { + ...cdkJson, + hotswap: { + ecs: { + minimumHealthyPercent: ecsMinimumHealthyPercent, + maximumHealthyPercent: ecsMaximumHealthyPercent, + }, + }, + }; + + await fs.writeFile(path.join(fixture.integTestDir, 'cdk.json'), JSON.stringify(cdkJson)); + + // GIVEN + const stackArn = await fixture.cdkDeploy('ecs-hotswap', { + captureStderr: false, + }); + + // WHEN + await fixture.cdkDeploy('ecs-hotswap', { + options: [ + '--hotswap', + ], + modEnv: { + DYNAMIC_ECS_PROPERTY_VALUE: 'new value', + }, + }); + + const describeStacksResponse = await fixture.aws.cloudFormation.send( + new DescribeStacksCommand({ + StackName: stackArn, + }), + ); + + const clusterName = describeStacksResponse.Stacks?.[0].Outputs?.find(output => output.OutputKey == 'ClusterName')?.OutputValue!; + const serviceName = describeStacksResponse.Stacks?.[0].Outputs?.find(output => output.OutputKey == 'ServiceName')?.OutputValue!; + + // THEN + const describeServicesResponse = await fixture.aws.ecs.send( + new DescribeServicesCommand({ + cluster: clusterName, + services: [serviceName], + }), + ); + expect(describeServicesResponse.services?.[0].deploymentConfiguration?.minimumHealthyPercent).toEqual(ecsMinimumHealthyPercent); + expect(describeServicesResponse.services?.[0].deploymentConfiguration?.maximumPercent).toEqual(ecsMaximumHealthyPercent); +})); + async function listChildren(parent: string, pred: (x: string) => Promise) { const ret = new Array(); for (const child of await fs.readdir(parent, { encoding: 'utf-8' })) { diff --git a/packages/aws-cdk/README.md b/packages/aws-cdk/README.md index deec121451f77..30818c8cb1402 100644 --- a/packages/aws-cdk/README.md +++ b/packages/aws-cdk/README.md @@ -451,6 +451,19 @@ Hotswapping is currently supported for the following changes - VTL mapping template changes for AppSync Resolvers and Functions. - Schema changes for AppSync GraphQL Apis. +You can optionally configure the behavior of your hotswap deployments in `cdk.json`. Currently you can only configure ECS hotswap behavior: + +```json +{ +"hotswap": { + "ecs": { + "minimumHealthyPercent": 100, + "maximumHealthyPercent": 250 + } + } +} +``` + **⚠ Note #1**: This command deliberately introduces drift in CloudFormation stacks in order to speed up deployments. For this reason, only use it for development purposes. **Never use this flag for your production deployments**! diff --git a/packages/aws-cdk/lib/api/deploy-stack.ts b/packages/aws-cdk/lib/api/deploy-stack.ts index 4a142d82e4309..16da0447b81f5 100644 --- a/packages/aws-cdk/lib/api/deploy-stack.ts +++ b/packages/aws-cdk/lib/api/deploy-stack.ts @@ -5,7 +5,7 @@ import * as uuid from 'uuid'; import { ISDK, SdkProvider } from './aws-auth'; import { EnvironmentResources } from './environment-resources'; import { CfnEvaluationException } from './evaluate-cloudformation-template'; -import { HotswapMode, ICON } from './hotswap/common'; +import { HotswapMode, HotswapPropertyOverrides, ICON } from './hotswap/common'; import { tryHotswapDeployment } from './hotswap-deployments'; import { addMetadataAssetsToManifest } from '../assets'; import { Tag } from '../cdk-toolkit'; @@ -173,6 +173,11 @@ export interface DeployStackOptions { */ readonly hotswap?: HotswapMode; + /** + * Extra properties that configure hotswap behavior + */ + readonly hotswapPropertyOverrides?: HotswapPropertyOverrides; + /** * The extra string to append to the User-Agent header when performing AWS SDK calls. * @@ -264,6 +269,7 @@ export async function deployStack(options: DeployStackOptions): Promise Promise; const RESOURCE_DETECTORS: { [key: string]: HotswapDetector } = { @@ -62,7 +65,7 @@ const RESOURCE_DETECTORS: { [key: string]: HotswapDetector } = { export async function tryHotswapDeployment( sdkProvider: SdkProvider, assetParams: { [key: string]: string }, cloudFormationStack: CloudFormationStack, stackArtifact: cxapi.CloudFormationStackArtifact, - hotswapMode: HotswapMode, + hotswapMode: HotswapMode, hotswapPropertyOverrides: HotswapPropertyOverrides, ): Promise { // resolve the environment, so we can substitute things like AWS::Region in CFN expressions const resolvedEnv = await sdkProvider.resolveEnvironment(stackArtifact.environment); @@ -86,7 +89,7 @@ export async function tryHotswapDeployment( const stackChanges = cfn_diff.fullDiff(currentTemplate.deployedRootTemplate, stackArtifact.template); const { hotswappableChanges, nonHotswappableChanges } = await classifyResourceChanges( - stackChanges, evaluateCfnTemplate, sdk, currentTemplate.nestedStacks, + stackChanges, evaluateCfnTemplate, sdk, currentTemplate.nestedStacks, hotswapPropertyOverrides, ); logNonHotswappableChanges(nonHotswappableChanges, hotswapMode); @@ -113,6 +116,7 @@ async function classifyResourceChanges( evaluateCfnTemplate: EvaluateCloudFormationTemplate, sdk: ISDK, nestedStackNames: { [nestedStackName: string]: NestedStackTemplates }, + hotswapPropertyOverrides: HotswapPropertyOverrides, ): Promise { const resourceDifferences = getStackResourceDifferences(stackChanges); @@ -131,7 +135,14 @@ async function classifyResourceChanges( // gather the results of the detector functions for (const [logicalId, change] of Object.entries(resourceDifferences)) { if (change.newValue?.Type === 'AWS::CloudFormation::Stack' && change.oldValue?.Type === 'AWS::CloudFormation::Stack') { - const nestedHotswappableResources = await findNestedHotswappableChanges(logicalId, change, nestedStackNames, evaluateCfnTemplate, sdk); + const nestedHotswappableResources = await findNestedHotswappableChanges( + logicalId, + change, + nestedStackNames, + evaluateCfnTemplate, + sdk, + hotswapPropertyOverrides, + ); hotswappableResources.push(...nestedHotswappableResources.hotswappableChanges); nonHotswappableResources.push(...nestedHotswappableResources.nonHotswappableChanges); @@ -151,7 +162,7 @@ async function classifyResourceChanges( const resourceType: string = hotswappableChangeCandidate.newValue.Type; if (resourceType in RESOURCE_DETECTORS) { // run detector functions lazily to prevent unhandled promise rejections - promises.push(() => RESOURCE_DETECTORS[resourceType](logicalId, hotswappableChangeCandidate, evaluateCfnTemplate)); + promises.push(() => RESOURCE_DETECTORS[resourceType](logicalId, hotswappableChangeCandidate, evaluateCfnTemplate, hotswapPropertyOverrides)); } else { reportNonHotswappableChange(nonHotswappableResources, hotswappableChangeCandidate, undefined, 'This resource type is not supported for hotswap deployments'); } @@ -233,6 +244,7 @@ async function findNestedHotswappableChanges( nestedStackTemplates: { [nestedStackName: string]: NestedStackTemplates }, evaluateCfnTemplate: EvaluateCloudFormationTemplate, sdk: ISDK, + hotswapPropertyOverrides: HotswapPropertyOverrides, ): Promise { const nestedStack = nestedStackTemplates[logicalId]; if (!nestedStack.physicalName) { @@ -256,7 +268,12 @@ async function findNestedHotswappableChanges( nestedStackTemplates[logicalId].deployedTemplate, nestedStackTemplates[logicalId].generatedTemplate, ); - return classifyResourceChanges(nestedDiff, evaluateNestedCfnTemplate, sdk, nestedStackTemplates[logicalId].nestedStackTemplates); + return classifyResourceChanges( + nestedDiff, + evaluateNestedCfnTemplate, + sdk, + nestedStackTemplates[logicalId].nestedStackTemplates, + hotswapPropertyOverrides); } /** Returns 'true' if a pair of changes is for the same resource. */ diff --git a/packages/aws-cdk/lib/api/hotswap/common.ts b/packages/aws-cdk/lib/api/hotswap/common.ts index eb4b787d04e92..a066e7b0e4d5d 100644 --- a/packages/aws-cdk/lib/api/hotswap/common.ts +++ b/packages/aws-cdk/lib/api/hotswap/common.ts @@ -98,6 +98,52 @@ export class HotswappableChangeCandidate { type Exclude = { [key: string]: Exclude | true } +/** + * Represents configuration property overrides for hotswap deployments + */ +export class HotswapPropertyOverrides { + // Each supported resource type will have its own properties. Currently this is ECS + ecsHotswapProperties?: EcsHotswapProperties; + + public constructor (ecsHotswapProperties?: EcsHotswapProperties) { + this.ecsHotswapProperties = ecsHotswapProperties; + } +} + +/** + * Represents configuration properties for ECS hotswap deployments + */ +export class EcsHotswapProperties { + // The lower limit on the number of your service's tasks that must remain in the RUNNING state during a deployment, as a percentage of the desiredCount + readonly minimumHealthyPercent?: number; + // The upper limit on the number of your service's tasks that are allowed in the RUNNING or PENDING state during a deployment, as a percentage of the desiredCount + readonly maximumHealthyPercent?: number; + + public constructor (minimumHealthyPercent?: number, maximumHealthyPercent?: number) { + if (minimumHealthyPercent !== undefined && minimumHealthyPercent < 0 ) { + throw new Error('hotswap-ecs-minimum-healthy-percent can\'t be a negative number'); + } + if (maximumHealthyPercent !== undefined && maximumHealthyPercent < 0 ) { + throw new Error('hotswap-ecs-maximum-healthy-percent can\'t be a negative number'); + } + // In order to preserve the current behaviour, when minimumHealthyPercent is not defined, it will be set to the currently default value of 0 + if (minimumHealthyPercent == undefined) { + this.minimumHealthyPercent = 0; + } else { + this.minimumHealthyPercent = minimumHealthyPercent; + } + this.maximumHealthyPercent = maximumHealthyPercent; + } + + /** + * Check if any hotswap properties are defined + * @returns true if all properties are undefined, false otherwise + */ + public isEmpty(): boolean { + return this.minimumHealthyPercent === 0 && this.maximumHealthyPercent === undefined; + } +} + /** * This function transforms all keys (recursively) in the provided `val` object. * diff --git a/packages/aws-cdk/lib/api/hotswap/ecs-services.ts b/packages/aws-cdk/lib/api/hotswap/ecs-services.ts index c79032eec6e88..f6f626d32f2c9 100644 --- a/packages/aws-cdk/lib/api/hotswap/ecs-services.ts +++ b/packages/aws-cdk/lib/api/hotswap/ecs-services.ts @@ -1,10 +1,13 @@ import * as AWS from 'aws-sdk'; -import { ChangeHotswapResult, classifyChanges, HotswappableChangeCandidate, lowerCaseFirstCharacter, reportNonHotswappableChange, transformObjectKeys } from './common'; +import { ChangeHotswapResult, classifyChanges, HotswappableChangeCandidate, HotswapPropertyOverrides, lowerCaseFirstCharacter, reportNonHotswappableChange, transformObjectKeys } from './common'; import { ISDK } from '../aws-auth'; import { EvaluateCloudFormationTemplate } from '../evaluate-cloudformation-template'; export async function isHotswappableEcsServiceChange( - logicalId: string, change: HotswappableChangeCandidate, evaluateCfnTemplate: EvaluateCloudFormationTemplate, + logicalId: string, + change: HotswappableChangeCandidate, + evaluateCfnTemplate: EvaluateCloudFormationTemplate, + hotswapPropertyOverrides: HotswapPropertyOverrides, ): Promise { // the only resource change we can evaluate here is an ECS TaskDefinition if (change.newValue.Type !== 'AWS::ECS::TaskDefinition') { @@ -83,6 +86,10 @@ export async function isHotswappableEcsServiceChange( const registerTaskDefResponse = await sdk.ecs().registerTaskDefinition(lowercasedTaskDef).promise(); const taskDefRevArn = registerTaskDefResponse.taskDefinition?.taskDefinitionArn; + let ecsHotswapProperties = hotswapPropertyOverrides.ecsHotswapProperties; + let minimumHealthyPercent = ecsHotswapProperties?.minimumHealthyPercent; + let maximumHealthyPercent = ecsHotswapProperties?.maximumHealthyPercent; + // Step 2 - update the services using that TaskDefinition to point to the new TaskDefinition Revision const servicePerClusterUpdates: { [cluster: string]: Array<{ promise: Promise; ecsService: EcsService }> } = {}; for (const ecsService of ecsServicesReferencingTaskDef) { @@ -105,7 +112,8 @@ export async function isHotswappableEcsServiceChange( cluster: clusterName, forceNewDeployment: true, deploymentConfiguration: { - minimumHealthyPercent: 0, + minimumHealthyPercent: minimumHealthyPercent !== undefined ? minimumHealthyPercent : 0, + maximumPercent: maximumHealthyPercent !== undefined ? maximumHealthyPercent : undefined, }, }).promise(), ecsService: ecsService, diff --git a/packages/aws-cdk/lib/cdk-toolkit.ts b/packages/aws-cdk/lib/cdk-toolkit.ts index 64a9a0b4dd20c..57dabce74a5dd 100644 --- a/packages/aws-cdk/lib/cdk-toolkit.ts +++ b/packages/aws-cdk/lib/cdk-toolkit.ts @@ -13,7 +13,7 @@ import { CloudAssembly, DefaultSelection, ExtendedStackSelection, StackCollectio import { CloudExecutable } from './api/cxapp/cloud-executable'; import { Deployments } from './api/deployments'; import { GarbageCollector } from './api/garbage-collection/garbage-collector'; -import { HotswapMode } from './api/hotswap/common'; +import { HotswapMode, HotswapPropertyOverrides, EcsHotswapProperties } from './api/hotswap/common'; import { findCloudWatchLogGroups } from './api/logs/find-cloudwatch-logs'; import { CloudWatchLogEventMonitor } from './api/logs/logs-monitor'; import { createDiffChangeSet, ResourcesToImport } from './api/util/cloudformation'; @@ -237,6 +237,14 @@ export class CdkToolkit { warning('⚠️ They should only be used for development - never use them for your production Stacks!\n'); } + let hotswapPropertiesFromSettings = this.props.configuration.settings.get(['hotswap']) || {}; + + let hotswapPropertyOverrides = new HotswapPropertyOverrides(); + hotswapPropertyOverrides.ecsHotswapProperties = new EcsHotswapProperties( + hotswapPropertiesFromSettings.ecs?.minimumHealthyPercent, + hotswapPropertiesFromSettings.ecs?.maximumHealthyPercent, + ); + const stacks = stackCollection.stackArtifacts; const stackOutputs: { [key: string]: any } = { }; @@ -347,6 +355,7 @@ export class CdkToolkit { ci: options.ci, rollback: options.rollback, hotswap: options.hotswap, + hotswapPropertyOverrides: hotswapPropertyOverrides, extraUserAgent: options.extraUserAgent, assetParallelism: options.assetParallelism, ignoreNoStacks: options.ignoreNoStacks, diff --git a/packages/aws-cdk/lib/settings.ts b/packages/aws-cdk/lib/settings.ts index 74684dc3501d3..37e607f34c4dd 100644 --- a/packages/aws-cdk/lib/settings.ts +++ b/packages/aws-cdk/lib/settings.ts @@ -292,6 +292,12 @@ export class Settings { assetParallelism: argv['asset-parallelism'], assetPrebuild: argv['asset-prebuild'], ignoreNoStacks: argv['ignore-no-stacks'], + hotswap: { + ecs: { + minimumEcsHealthyPercent: argv.minimumEcsHealthyPercent, + maximumEcsHealthyPercent: argv.maximumEcsHealthyPercent, + }, + }, unstable: argv.unstable, }); } diff --git a/packages/aws-cdk/test/api/deploy-stack.test.ts b/packages/aws-cdk/test/api/deploy-stack.test.ts index bdb58f8aad99d..7afcea68f4c60 100644 --- a/packages/aws-cdk/test/api/deploy-stack.test.ts +++ b/packages/aws-cdk/test/api/deploy-stack.test.ts @@ -151,7 +151,7 @@ test('correctly passes CFN parameters when hotswapping', async () => { }); // THEN - expect(tryHotswapDeployment).toHaveBeenCalledWith(expect.anything(), { A: 'A-value', B: 'B=value' }, expect.anything(), expect.anything(), HotswapMode.FALL_BACK); + expect(tryHotswapDeployment).toHaveBeenCalledWith(expect.anything(), { A: 'A-value', B: 'B=value' }, expect.anything(), expect.anything(), HotswapMode.FALL_BACK, expect.anything()); }); test('correctly passes SSM parameters when hotswapping', async () => { @@ -181,7 +181,7 @@ test('correctly passes SSM parameters when hotswapping', async () => { }); // THEN - expect(tryHotswapDeployment).toHaveBeenCalledWith(expect.anything(), { SomeParameter: 'SomeValue' }, expect.anything(), expect.anything(), HotswapMode.FALL_BACK); + expect(tryHotswapDeployment).toHaveBeenCalledWith(expect.anything(), { SomeParameter: 'SomeValue' }, expect.anything(), expect.anything(), HotswapMode.FALL_BACK, expect.anything()); }); test('call CreateStack when method=direct and the stack doesnt exist yet', async () => { diff --git a/packages/aws-cdk/test/api/hotswap/ecs-services-hotswap-deployments.test.ts b/packages/aws-cdk/test/api/hotswap/ecs-services-hotswap-deployments.test.ts index d1ef496819328..182749aaa89d0 100644 --- a/packages/aws-cdk/test/api/hotswap/ecs-services-hotswap-deployments.test.ts +++ b/packages/aws-cdk/test/api/hotswap/ecs-services-hotswap-deployments.test.ts @@ -1,6 +1,7 @@ import * as AWS from 'aws-sdk'; import * as setup from './hotswap-test-setup'; -import { HotswapMode } from '../../../lib/api/hotswap/common'; +import { EcsHotswapProperties, HotswapMode, HotswapPropertyOverrides } from '../../../lib/api/hotswap/common'; +import { Configuration } from '../../../lib/settings'; import { silentTest } from '../../util/silent'; let hotswapMockSdkProvider: setup.HotswapMockSdkProvider; @@ -9,7 +10,6 @@ let mockUpdateService: (params: AWS.ECS.UpdateServiceRequest) => AWS.ECS.UpdateS beforeEach(() => { hotswapMockSdkProvider = setup.setupHotswapTests(); - mockRegisterTaskDef = jest.fn(); mockUpdateService = jest.fn(); hotswapMockSdkProvider.stubEcs({ @@ -637,3 +637,90 @@ describe.each([HotswapMode.FALL_BACK, HotswapMode.HOTSWAP_ONLY])('%p mode', (hot }); }); }); + +describe.each([ + new Configuration().settings.set(['hotswap'], { ecs: { minimumHealthyPercent: 10 } }), + new Configuration().settings.set(['hotswap'], { ecs: { minimumHealthyPercent: 10, maximumHealthyPercent: 100 } }), +])('hotswap properties', (settings) => { + test('should handle all possible hotswap properties', async () => { + // GIVEN + setup.setCurrentCfnStackTemplate({ + Resources: { + TaskDef: { + Type: 'AWS::ECS::TaskDefinition', + Properties: { + Family: 'my-task-def', + ContainerDefinitions: [ + { Image: 'image1' }, + ], + }, + }, + Service: { + Type: 'AWS::ECS::Service', + Properties: { + TaskDefinition: { Ref: 'TaskDef' }, + }, + }, + }, + }); + setup.pushStackResourceSummaries( + setup.stackSummaryOf('Service', 'AWS::ECS::Service', + 'arn:aws:ecs:region:account:service/my-cluster/my-service'), + ); + mockRegisterTaskDef.mockReturnValue({ + taskDefinition: { + taskDefinitionArn: 'arn:aws:ecs:region:account:task-definition/my-task-def:3', + }, + }); + const cdkStackArtifact = setup.cdkStackArtifactOf({ + template: { + Resources: { + TaskDef: { + Type: 'AWS::ECS::TaskDefinition', + Properties: { + Family: 'my-task-def', + ContainerDefinitions: [ + { Image: 'image2' }, + ], + }, + }, + Service: { + Type: 'AWS::ECS::Service', + Properties: { + TaskDefinition: { Ref: 'TaskDef' }, + }, + }, + }, + }, + }); + + // WHEN + let ecsHotswapProperties = new EcsHotswapProperties(settings.get(['hotswap']).ecs.minimumHealthyPercent, settings.get(['hotswap']).ecs.maximumHealthyPercent); + const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment( + HotswapMode.HOTSWAP_ONLY, + cdkStackArtifact, + {}, + new HotswapPropertyOverrides(ecsHotswapProperties), + ); + + // THEN + expect(deployStackResult).not.toBeUndefined(); + expect(mockRegisterTaskDef).toBeCalledWith({ + family: 'my-task-def', + containerDefinitions: [ + { image: 'image2' }, + ], + }); + expect(mockUpdateService).toBeCalledWith({ + service: 'arn:aws:ecs:region:account:service/my-cluster/my-service', + cluster: 'my-cluster', + taskDefinition: 'arn:aws:ecs:region:account:task-definition/my-task-def:3', + deploymentConfiguration: { + minimumHealthyPercent: settings.get(['hotswap']).ecs?.minimumHealthyPercent == undefined ? + 0 : settings.get(['hotswap']).ecs?.minimumHealthyPercent, + maximumPercent: settings.get(['hotswap']).ecs?.maximumHealthyPercent, + }, + forceNewDeployment: true, + }); + }); +}); diff --git a/packages/aws-cdk/test/api/hotswap/hotswap-test-setup.ts b/packages/aws-cdk/test/api/hotswap/hotswap-test-setup.ts index 505f128a0dee2..1288c827f2300 100644 --- a/packages/aws-cdk/test/api/hotswap/hotswap-test-setup.ts +++ b/packages/aws-cdk/test/api/hotswap/hotswap-test-setup.ts @@ -4,7 +4,7 @@ import * as codebuild from 'aws-sdk/clients/codebuild'; import * as lambda from 'aws-sdk/clients/lambda'; import * as stepfunctions from 'aws-sdk/clients/stepfunctions'; import { DeployStackResult } from '../../../lib/api'; -import { HotswapMode } from '../../../lib/api/hotswap/common'; +import { HotswapMode, HotswapPropertyOverrides } from '../../../lib/api/hotswap/common'; import * as deployments from '../../../lib/api/hotswap-deployments'; import { CloudFormationStack, Template } from '../../../lib/api/util/cloudformation'; import { testStack, TestStackArtifact } from '../../util'; @@ -179,7 +179,9 @@ export class HotswapMockSdkProvider { hotswapMode: HotswapMode, stackArtifact: cxapi.CloudFormationStackArtifact, assetParams: { [key: string]: string } = {}, + hotswapPropertyOverrides?: HotswapPropertyOverrides, ): Promise { - return deployments.tryHotswapDeployment(this.mockSdkProvider, assetParams, currentCfnStack, stackArtifact, hotswapMode); + let hotswapProps = hotswapPropertyOverrides || new HotswapPropertyOverrides(); + return deployments.tryHotswapDeployment(this.mockSdkProvider, assetParams, currentCfnStack, stackArtifact, hotswapMode, hotswapProps); } } From 2e691b64668c6d19f80f73479cbd9658e159a901 Mon Sep 17 00:00:00 2001 From: paulhcsun <47882901+paulhcsun@users.noreply.github.com> Date: Wed, 23 Oct 2024 10:30:39 -0700 Subject: [PATCH 3/5] chore(kinesisfirehose-alpha): update README with Logging resource clarification (#31861) ### Description of changes Clarify in README that a LogGroup and LogStream with **default settings** will be created. ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/@aws-cdk/aws-kinesisfirehose-alpha/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-kinesisfirehose-alpha/README.md b/packages/@aws-cdk/aws-kinesisfirehose-alpha/README.md index ad33ea30db7f5..3b216e66b1355 100644 --- a/packages/@aws-cdk/aws-kinesisfirehose-alpha/README.md +++ b/packages/@aws-cdk/aws-kinesisfirehose-alpha/README.md @@ -181,7 +181,7 @@ your delivery streams via logs and metrics. Amazon Data Firehose will send logs to CloudWatch when data transformation or data delivery fails. The CDK will enable logging by default and create a CloudWatch LogGroup -and LogStream for your Delivery Stream. +and LogStream with default settings for your Delivery Stream. When creating a destination, you can provide an `ILoggingConfig`, which can either be an `EnableLogging` or `DisableLogging` instance. If you use `EnableLogging`, the CDK will create a CloudWatch LogGroup and LogStream with all CloudFormation default settings for you, or you can optionally From 58dfda087a8aabde2683cd99df005d6e5e73a7ce Mon Sep 17 00:00:00 2001 From: Xia Zhao <78883180+xazhao@users.noreply.github.com> Date: Wed, 23 Oct 2024 11:02:46 -0700 Subject: [PATCH 4/5] fix(events-targets): kinesis Stream target with Customer-Managed KMS key causes EventBridge FailedInvocations (#31836) ### Issue # (if applicable) Closes #10996. ### Reason for this change When a Kinesis Stream is encrypted with a custom managed KMS key, CDK will generate a KMS key for the Kinesis Stream. ``` stream = new kinesis.Stream(stack, 'MyStream', { encryption: kinesis.StreamEncryption.KMS, }); ``` If it is used as a events target, CDK will provide permissions to the role of target so it can write to the kinesis stream: ``` { Action: ['kinesis:PutRecord', 'kinesis:PutRecords'], Effect: 'Allow', Resource: streamArn, } ``` If the kinesis is not encrypted with the customer managed kms key, these permissions will be sufficient. However, since the kinesis is encrypted with the the customer managed kms key, the invocation will fail because events doesn't have the permissions to the KMS key. Actually there's already `grantWrite()` method to grant sufficient permissions in this case. When a customer managed KMS key is used, it will generate extra policies for the key. We should use it. https://github.com/aws/aws-cdk/blob/366b4927c50168113dd4057f6255ab6c76278135/packages/aws-cdk-lib/aws-kinesis/lib/stream.ts#L355 Difference: these permissions will be added to the event ``` { Action: ['kinesis:ListShards(new permission)', 'kinesis:PutRecord', 'kinesis:PutRecords'], Effect: 'Allow', Resource: streamArn, } ``` these permissions will be added to the event if the target kinesis stream is using a customer managed KMS key ``` { Action: ['kms:Encrypt', 'kms:ReEncrypt*', 'kms:GenerateDataKey*'], Effect: 'Allow', Resource: streamKeyArn, }, ``` ### Description of changes Use the existing `grantWrite()` method instead of manipulating IAM policies directly. ### Description of how you validated changes unit tests/integration tests ### Checklist - [ ] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- ...efaultTestDeployAssertF9D5974E.assets.json | 19 + ...aultTestDeployAssertF9D5974E.template.json | 36 ++ .../aws-cdk-kinesis-event-target.assets.json | 19 + ...aws-cdk-kinesis-event-target.template.json | 180 ++++++++++ .../cdk.out | 1 + .../integ.json | 12 + .../manifest.json | 139 ++++++++ .../tree.json | 337 ++++++++++++++++++ .../integ.kinesis-stream-customer-key.ts | 27 ++ ...efaultTestDeployAssertE4CFAC29.assets.json | 2 +- ...s-cdk-kinesis-event-target-dlq.assets.json | 6 +- ...cdk-kinesis-event-target-dlq.template.json | 1 + .../cdk.out | 2 +- .../integ.json | 2 +- .../manifest.json | 6 +- .../tree.json | 1 + .../aws-cdk-kinesis-event-target.assets.json | 6 +- ...aws-cdk-kinesis-event-target.template.json | 1 + .../integ.kinesis-stream.js.snapshot/cdk.out | 2 +- .../integ.json | 2 +- .../manifest.json | 5 +- .../tree.json | 1 + .../aws-events-targets/lib/kinesis-stream.ts | 6 +- .../test/kinesis/kinesis-stream.test.ts | 55 ++- 24 files changed, 846 insertions(+), 22 deletions(-) create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-customer-key.js.snapshot/KinesisKmsDefaultTestDeployAssertF9D5974E.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-customer-key.js.snapshot/KinesisKmsDefaultTestDeployAssertF9D5974E.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-customer-key.js.snapshot/aws-cdk-kinesis-event-target.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-customer-key.js.snapshot/aws-cdk-kinesis-event-target.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-customer-key.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-customer-key.js.snapshot/integ.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-customer-key.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-customer-key.js.snapshot/tree.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-customer-key.ts diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-customer-key.js.snapshot/KinesisKmsDefaultTestDeployAssertF9D5974E.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-customer-key.js.snapshot/KinesisKmsDefaultTestDeployAssertF9D5974E.assets.json new file mode 100644 index 0000000000000..c2007b5c09632 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-customer-key.js.snapshot/KinesisKmsDefaultTestDeployAssertF9D5974E.assets.json @@ -0,0 +1,19 @@ +{ + "version": "38.0.1", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "KinesisKmsDefaultTestDeployAssertF9D5974E.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-customer-key.js.snapshot/KinesisKmsDefaultTestDeployAssertF9D5974E.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-customer-key.js.snapshot/KinesisKmsDefaultTestDeployAssertF9D5974E.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-customer-key.js.snapshot/KinesisKmsDefaultTestDeployAssertF9D5974E.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-customer-key.js.snapshot/aws-cdk-kinesis-event-target.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-customer-key.js.snapshot/aws-cdk-kinesis-event-target.assets.json new file mode 100644 index 0000000000000..fa4cd04a8a23e --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-customer-key.js.snapshot/aws-cdk-kinesis-event-target.assets.json @@ -0,0 +1,19 @@ +{ + "version": "38.0.1", + "files": { + "21dc15bc2eacafdd9b16fd80172b8974e3c6a524d55f408eb8f9ab807afa5e63": { + "source": { + "path": "aws-cdk-kinesis-event-target.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21dc15bc2eacafdd9b16fd80172b8974e3c6a524d55f408eb8f9ab807afa5e63.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-customer-key.js.snapshot/aws-cdk-kinesis-event-target.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-customer-key.js.snapshot/aws-cdk-kinesis-event-target.template.json new file mode 100644 index 0000000000000..8bffab542ba70 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-customer-key.js.snapshot/aws-cdk-kinesis-event-target.template.json @@ -0,0 +1,180 @@ +{ + "Resources": { + "MyStreamKey76F3300E": { + "Type": "AWS::KMS::Key", + "Properties": { + "Description": "Created by aws-cdk-kinesis-event-target/MyStream", + "KeyPolicy": { + "Statement": [ + { + "Action": "kms:*", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] + } + }, + "Resource": "*" + } + ], + "Version": "2012-10-17" + } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "MyStream5C050E93": { + "Type": "AWS::Kinesis::Stream", + "Properties": { + "RetentionPeriodHours": 24, + "ShardCount": 1, + "StreamEncryption": { + "EncryptionType": "KMS", + "KeyId": { + "Fn::GetAtt": [ + "MyStreamKey76F3300E", + "Arn" + ] + } + } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "MyStreamEventsRole5B6CC6AF": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "events.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "MyStreamEventsRoleDefaultPolicy2089B49E": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "kinesis:ListShards", + "kinesis:PutRecord", + "kinesis:PutRecords" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "MyStream5C050E93", + "Arn" + ] + } + }, + { + "Action": [ + "kms:Encrypt", + "kms:GenerateDataKey*", + "kms:ReEncrypt*" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "MyStreamKey76F3300E", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "MyStreamEventsRoleDefaultPolicy2089B49E", + "Roles": [ + { + "Ref": "MyStreamEventsRole5B6CC6AF" + } + ] + } + }, + "EveryMinute2BBCEA8F": { + "Type": "AWS::Events::Rule", + "Properties": { + "ScheduleExpression": "rate(1 minute)", + "State": "ENABLED", + "Targets": [ + { + "Arn": { + "Fn::GetAtt": [ + "MyStream5C050E93", + "Arn" + ] + }, + "Id": "Target0", + "KinesisParameters": { + "PartitionKeyPath": "$.id" + }, + "RoleArn": { + "Fn::GetAtt": [ + "MyStreamEventsRole5B6CC6AF", + "Arn" + ] + } + } + ] + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-customer-key.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-customer-key.js.snapshot/cdk.out new file mode 100644 index 0000000000000..c6e612584e352 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-customer-key.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"38.0.1"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-customer-key.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-customer-key.js.snapshot/integ.json new file mode 100644 index 0000000000000..5f7c6f30454e0 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-customer-key.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "38.0.1", + "testCases": { + "KinesisKms/DefaultTest": { + "stacks": [ + "aws-cdk-kinesis-event-target" + ], + "assertionStack": "KinesisKms/DefaultTest/DeployAssert", + "assertionStackName": "KinesisKmsDefaultTestDeployAssertF9D5974E" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-customer-key.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-customer-key.js.snapshot/manifest.json new file mode 100644 index 0000000000000..bd01961af6a22 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-customer-key.js.snapshot/manifest.json @@ -0,0 +1,139 @@ +{ + "version": "38.0.1", + "artifacts": { + "aws-cdk-kinesis-event-target.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-kinesis-event-target.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-kinesis-event-target": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-kinesis-event-target.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "notificationArns": [], + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21dc15bc2eacafdd9b16fd80172b8974e3c6a524d55f408eb8f9ab807afa5e63.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-kinesis-event-target.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "aws-cdk-kinesis-event-target.assets" + ], + "metadata": { + "/aws-cdk-kinesis-event-target/MyStream/Key/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyStreamKey76F3300E" + } + ], + "/aws-cdk-kinesis-event-target/MyStream/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyStream5C050E93" + } + ], + "/aws-cdk-kinesis-event-target/MyStream/EventsRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyStreamEventsRole5B6CC6AF" + } + ], + "/aws-cdk-kinesis-event-target/MyStream/EventsRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyStreamEventsRoleDefaultPolicy2089B49E" + } + ], + "/aws-cdk-kinesis-event-target/EveryMinute/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "EveryMinute2BBCEA8F" + } + ], + "/aws-cdk-kinesis-event-target/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-kinesis-event-target/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-kinesis-event-target" + }, + "KinesisKmsDefaultTestDeployAssertF9D5974E.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "KinesisKmsDefaultTestDeployAssertF9D5974E.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "KinesisKmsDefaultTestDeployAssertF9D5974E": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "KinesisKmsDefaultTestDeployAssertF9D5974E.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "notificationArns": [], + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "KinesisKmsDefaultTestDeployAssertF9D5974E.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "KinesisKmsDefaultTestDeployAssertF9D5974E.assets" + ], + "metadata": { + "/KinesisKms/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/KinesisKms/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "KinesisKms/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-customer-key.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-customer-key.js.snapshot/tree.json new file mode 100644 index 0000000000000..4eb0cc2568865 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-customer-key.js.snapshot/tree.json @@ -0,0 +1,337 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "aws-cdk-kinesis-event-target": { + "id": "aws-cdk-kinesis-event-target", + "path": "aws-cdk-kinesis-event-target", + "children": { + "MyStream": { + "id": "MyStream", + "path": "aws-cdk-kinesis-event-target/MyStream", + "children": { + "Key": { + "id": "Key", + "path": "aws-cdk-kinesis-event-target/MyStream/Key", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-kinesis-event-target/MyStream/Key/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::KMS::Key", + "aws:cdk:cloudformation:props": { + "description": "Created by aws-cdk-kinesis-event-target/MyStream", + "keyPolicy": { + "Statement": [ + { + "Action": "kms:*", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] + } + }, + "Resource": "*" + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_kms.CfnKey", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_kms.Key", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "aws-cdk-kinesis-event-target/MyStream/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Kinesis::Stream", + "aws:cdk:cloudformation:props": { + "retentionPeriodHours": 24, + "shardCount": 1, + "streamEncryption": { + "encryptionType": "KMS", + "keyId": { + "Fn::GetAtt": [ + "MyStreamKey76F3300E", + "Arn" + ] + } + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_kinesis.CfnStream", + "version": "0.0.0" + } + }, + "EventsRole": { + "id": "EventsRole", + "path": "aws-cdk-kinesis-event-target/MyStream/EventsRole", + "children": { + "ImportEventsRole": { + "id": "ImportEventsRole", + "path": "aws-cdk-kinesis-event-target/MyStream/EventsRole/ImportEventsRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "aws-cdk-kinesis-event-target/MyStream/EventsRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "events.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "aws-cdk-kinesis-event-target/MyStream/EventsRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-kinesis-event-target/MyStream/EventsRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "kinesis:ListShards", + "kinesis:PutRecord", + "kinesis:PutRecords" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "MyStream5C050E93", + "Arn" + ] + } + }, + { + "Action": [ + "kms:Encrypt", + "kms:GenerateDataKey*", + "kms:ReEncrypt*" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "MyStreamKey76F3300E", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "policyName": "MyStreamEventsRoleDefaultPolicy2089B49E", + "roles": [ + { + "Ref": "MyStreamEventsRole5B6CC6AF" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_kinesis.Stream", + "version": "0.0.0" + } + }, + "EveryMinute": { + "id": "EveryMinute", + "path": "aws-cdk-kinesis-event-target/EveryMinute", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-kinesis-event-target/EveryMinute/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Events::Rule", + "aws:cdk:cloudformation:props": { + "scheduleExpression": "rate(1 minute)", + "state": "ENABLED", + "targets": [ + { + "id": "Target0", + "arn": { + "Fn::GetAtt": [ + "MyStream5C050E93", + "Arn" + ] + }, + "roleArn": { + "Fn::GetAtt": [ + "MyStreamEventsRole5B6CC6AF", + "Arn" + ] + }, + "kinesisParameters": { + "partitionKeyPath": "$.id" + } + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_events.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_events.Rule", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-kinesis-event-target/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-kinesis-event-target/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "KinesisKms": { + "id": "KinesisKms", + "path": "KinesisKms", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "KinesisKms/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "KinesisKms/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "KinesisKms/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "KinesisKms/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "KinesisKms/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-customer-key.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-customer-key.ts new file mode 100644 index 0000000000000..4b4bd9c688415 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-customer-key.ts @@ -0,0 +1,27 @@ +import * as events from 'aws-cdk-lib/aws-events'; +import * as kinesis from 'aws-cdk-lib/aws-kinesis'; +import * as cdk from 'aws-cdk-lib'; +import * as targets from 'aws-cdk-lib/aws-events-targets'; +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; + +// --------------------------------- +// Define a rule that triggers a put to a Kinesis stream encrypted by a customer-managed KMS key every 1min. + +const app = new cdk.App(); + +const stack = new cdk.Stack(app, 'aws-cdk-kinesis-event-target'); + +const stream = new kinesis.Stream(stack, 'MyStream', { + encryption: kinesis.StreamEncryption.KMS, +}); +const event = new events.Rule(stack, 'EveryMinute', { + schedule: events.Schedule.rate(cdk.Duration.minutes(1)), +}); + +event.addTarget(new targets.KinesisStream(stream, { + partitionKeyPath: events.EventField.eventId, +})); + +new IntegTest(app, 'KinesisKms', { + testCases: [stack], +}); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/KinesisDlqDefaultTestDeployAssertE4CFAC29.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/KinesisDlqDefaultTestDeployAssertE4CFAC29.assets.json index 3be133b269609..0e6f5a6ddbc24 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/KinesisDlqDefaultTestDeployAssertE4CFAC29.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/KinesisDlqDefaultTestDeployAssertE4CFAC29.assets.json @@ -1,5 +1,5 @@ { - "version": "36.0.24", + "version": "38.0.1", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/aws-cdk-kinesis-event-target-dlq.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/aws-cdk-kinesis-event-target-dlq.assets.json index 7e452036ed237..6bf674349e819 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/aws-cdk-kinesis-event-target-dlq.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/aws-cdk-kinesis-event-target-dlq.assets.json @@ -1,7 +1,7 @@ { - "version": "36.0.24", + "version": "38.0.1", "files": { - "b92166c0aa5448c8df40d6ed216b585ca5a8c8f600b343c74efb8983a16eb5a1": { + "4aade69c48604b052f7b859d3429c09e78b3f44bf5da100091f2b8164a2d80e5": { "source": { "path": "aws-cdk-kinesis-event-target-dlq.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "b92166c0aa5448c8df40d6ed216b585ca5a8c8f600b343c74efb8983a16eb5a1.json", + "objectKey": "4aade69c48604b052f7b859d3429c09e78b3f44bf5da100091f2b8164a2d80e5.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/aws-cdk-kinesis-event-target-dlq.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/aws-cdk-kinesis-event-target-dlq.template.json index f86d9fd999442..3dbb9c1887aa2 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/aws-cdk-kinesis-event-target-dlq.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/aws-cdk-kinesis-event-target-dlq.template.json @@ -45,6 +45,7 @@ "Statement": [ { "Action": [ + "kinesis:ListShards", "kinesis:PutRecord", "kinesis:PutRecords" ], diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/cdk.out index 4efaa16f29af9..c6e612584e352 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/cdk.out +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"36.0.24"} \ No newline at end of file +{"version":"38.0.1"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/integ.json index a34d4ef7c0934..389153af3c926 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/integ.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "36.0.24", + "version": "38.0.1", "testCases": { "KinesisDlq/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/manifest.json index dcc9d0018043f..2eb5e8f396f26 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/manifest.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "36.0.24", + "version": "38.0.1", "artifacts": { "aws-cdk-kinesis-event-target-dlq.assets": { "type": "cdk:asset-manifest", @@ -16,9 +16,10 @@ "templateFile": "aws-cdk-kinesis-event-target-dlq.template.json", "terminationProtection": false, "validateOnSynth": false, + "notificationArns": [], "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/b92166c0aa5448c8df40d6ed216b585ca5a8c8f600b343c74efb8983a16eb5a1.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/4aade69c48604b052f7b859d3429c09e78b3f44bf5da100091f2b8164a2d80e5.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -100,6 +101,7 @@ "templateFile": "KinesisDlqDefaultTestDeployAssertE4CFAC29.template.json", "terminationProtection": false, "validateOnSynth": false, + "notificationArns": [], "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/tree.json index 6af467fa6c2b9..c989583ab6d8e 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/tree.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/tree.json @@ -90,6 +90,7 @@ "Statement": [ { "Action": [ + "kinesis:ListShards", "kinesis:PutRecord", "kinesis:PutRecords" ], diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream.js.snapshot/aws-cdk-kinesis-event-target.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream.js.snapshot/aws-cdk-kinesis-event-target.assets.json index 4d6eef75fa685..636bd608d1af9 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream.js.snapshot/aws-cdk-kinesis-event-target.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream.js.snapshot/aws-cdk-kinesis-event-target.assets.json @@ -1,7 +1,7 @@ { - "version": "36.0.0", + "version": "38.0.1", "files": { - "74908ecc1f1b06754e5120fe2f8ca8bdf8740a59e6424e70a70791aa23922900": { + "cc7c8dc15f12d6e9793c1db711131a00d663645ea38c73e4905c4fd8c8f8b323": { "source": { "path": "aws-cdk-kinesis-event-target.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "74908ecc1f1b06754e5120fe2f8ca8bdf8740a59e6424e70a70791aa23922900.json", + "objectKey": "cc7c8dc15f12d6e9793c1db711131a00d663645ea38c73e4905c4fd8c8f8b323.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream.js.snapshot/aws-cdk-kinesis-event-target.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream.js.snapshot/aws-cdk-kinesis-event-target.template.json index b8bf461749c68..8f1b3135fc16a 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream.js.snapshot/aws-cdk-kinesis-event-target.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream.js.snapshot/aws-cdk-kinesis-event-target.template.json @@ -45,6 +45,7 @@ "Statement": [ { "Action": [ + "kinesis:ListShards", "kinesis:PutRecord", "kinesis:PutRecords" ], diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream.js.snapshot/cdk.out index 1f0068d32659a..c6e612584e352 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream.js.snapshot/cdk.out +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"36.0.0"} \ No newline at end of file +{"version":"38.0.1"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream.js.snapshot/integ.json index e7829f9338715..7b37522ce4243 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream.js.snapshot/integ.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "36.0.0", + "version": "38.0.1", "testCases": { "integ.kinesis-stream": { "stacks": [ diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream.js.snapshot/manifest.json index 4f318c66777a3..d64cef03aeaf9 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream.js.snapshot/manifest.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "36.0.0", + "version": "38.0.1", "artifacts": { "aws-cdk-kinesis-event-target.assets": { "type": "cdk:asset-manifest", @@ -16,9 +16,10 @@ "templateFile": "aws-cdk-kinesis-event-target.template.json", "terminationProtection": false, "validateOnSynth": false, + "notificationArns": [], "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/74908ecc1f1b06754e5120fe2f8ca8bdf8740a59e6424e70a70791aa23922900.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/cc7c8dc15f12d6e9793c1db711131a00d663645ea38c73e4905c4fd8c8f8b323.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream.js.snapshot/tree.json index ca5873b706721..74c4c2d0dbd38 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream.js.snapshot/tree.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream.js.snapshot/tree.json @@ -90,6 +90,7 @@ "Statement": [ { "Action": [ + "kinesis:ListShards", "kinesis:PutRecord", "kinesis:PutRecords" ], diff --git a/packages/aws-cdk-lib/aws-events-targets/lib/kinesis-stream.ts b/packages/aws-cdk-lib/aws-events-targets/lib/kinesis-stream.ts index 119992f6430e7..ffdf794a3dc2e 100644 --- a/packages/aws-cdk-lib/aws-events-targets/lib/kinesis-stream.ts +++ b/packages/aws-cdk-lib/aws-events-targets/lib/kinesis-stream.ts @@ -1,6 +1,5 @@ import { bindBaseTargetConfig, singletonEventRole, TargetBaseProps } from './util'; import * as events from '../../aws-events'; -import * as iam from '../../aws-iam'; import * as kinesis from '../../aws-kinesis'; /** @@ -46,10 +45,7 @@ export class KinesisStream implements events.IRuleTarget { */ public bind(_rule: events.IRule, _id?: string): events.RuleTargetConfig { const role = singletonEventRole(this.stream); - role.addToPrincipalPolicy(new iam.PolicyStatement({ - actions: ['kinesis:PutRecord', 'kinesis:PutRecords'], - resources: [this.stream.streamArn], - })); + this.stream.grantWrite(role); return { ...bindBaseTargetConfig(this.props), diff --git a/packages/aws-cdk-lib/aws-events-targets/test/kinesis/kinesis-stream.test.ts b/packages/aws-cdk-lib/aws-events-targets/test/kinesis/kinesis-stream.test.ts index 705007b0c4421..b817120984753 100644 --- a/packages/aws-cdk-lib/aws-events-targets/test/kinesis/kinesis-stream.test.ts +++ b/packages/aws-cdk-lib/aws-events-targets/test/kinesis/kinesis-stream.test.ts @@ -5,6 +5,57 @@ import * as sqs from '../../../aws-sqs'; import { Duration, Stack } from '../../../core'; import * as targets from '../../lib'; +describe('KinesisStream event target with customer managed key', () => { + let stack: Stack; + let stream: kinesis.Stream; + let streamArn: any; + let streamKeyArn: any; + + beforeEach(() => { + stack = new Stack(); + stream = new kinesis.Stream(stack, 'MyStream', { + encryption: kinesis.StreamEncryption.KMS, + }); + streamArn = { 'Fn::GetAtt': ['MyStream5C050E93', 'Arn'] }; + streamKeyArn = { 'Fn::GetAtt': ['MyStreamKey76F3300E', 'Arn'] }; + }); + describe('when added to an event rule as a target', () => { + let rule: events.Rule; + + beforeEach(() => { + rule = new events.Rule(stack, 'rule', { + schedule: events.Schedule.expression('rate(1 minute)'), + }); + }); + + describe('with default settings', () => { + beforeEach(() => { + rule.addTarget(new targets.KinesisStream(stream)); + }); + + test("creates a policy that has PutRecord, PutRecords and ListShards permissions on the stream's ARN", () => { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: ['kinesis:ListShards', 'kinesis:PutRecord', 'kinesis:PutRecords'], + Effect: 'Allow', + Resource: streamArn, + }, + { + Action: ['kms:Encrypt', 'kms:ReEncrypt*', 'kms:GenerateDataKey*'], + Effect: 'Allow', + Resource: streamKeyArn, + }, + ], + Version: '2012-10-17', + }, + }); + }); + }); + }); +}); + describe('KinesisStream event target', () => { let stack: Stack; let stream: kinesis.Stream; @@ -42,12 +93,12 @@ describe('KinesisStream event target', () => { }); }); - test("creates a policy that has PutRecord and PutRecords permissions on the stream's ARN", () => { + test("creates a policy that has PutRecord, PutRecords and ListShards permissions on the stream's ARN", () => { Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { - Action: ['kinesis:PutRecord', 'kinesis:PutRecords'], + Action: ['kinesis:ListShards', 'kinesis:PutRecord', 'kinesis:PutRecords'], Effect: 'Allow', Resource: streamArn, }, From 0b03eb0f62c132c1bd586a8ec31818398d07707f Mon Sep 17 00:00:00 2001 From: Lee Date: Wed, 23 Oct 2024 19:36:06 +0100 Subject: [PATCH 5/5] fix(dynamodb): replication regions are incompatible with resource policies in TableV2 and feature flag (#31513) ### Issue # (if applicable) Closes #30705 ### Reason for this change Resource policies were shared across all replicas in a region. ### Description of changes Changed the logic to only apply resource policy to the local replica region, or to specific replicas only when defined. ### Description of how you validated changes yes ### Checklist - [X] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../ResourcePolicyTest-v2-FF.assets.json | 20 ++ .../ResourcePolicyTest-v2-FF.template.json | 95 ++++++++++ .../cdk.out | 1 + .../integ.json | 12 ++ .../manifest.json | 115 ++++++++++++ ...efaultTestDeployAssertBE3353C7.assets.json | 19 ++ ...aultTestDeployAssertBE3353C7.template.json | 36 ++++ .../tree.json | 174 ++++++++++++++++++ .../test/integ.dynamodb-v2.policy-ff.ts | 47 +++++ .../test/integ.dynamodb-v2.policy.ts | 9 +- .../aws-cdk-lib/aws-dynamodb/lib/table-v2.ts | 12 +- packages/aws-cdk-lib/cx-api/README.md | 19 ++ packages/aws-cdk-lib/cx-api/lib/features.ts | 16 ++ 13 files changed, 570 insertions(+), 5 deletions(-) create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy-ff.js.snapshot/ResourcePolicyTest-v2-FF.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy-ff.js.snapshot/ResourcePolicyTest-v2-FF.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy-ff.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy-ff.js.snapshot/integ.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy-ff.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy-ff.js.snapshot/tablev2resourcepolicyintegtestDefaultTestDeployAssertBE3353C7.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy-ff.js.snapshot/tablev2resourcepolicyintegtestDefaultTestDeployAssertBE3353C7.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy-ff.js.snapshot/tree.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy-ff.ts diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy-ff.js.snapshot/ResourcePolicyTest-v2-FF.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy-ff.js.snapshot/ResourcePolicyTest-v2-FF.assets.json new file mode 100644 index 0000000000000..31c84ba046a09 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy-ff.js.snapshot/ResourcePolicyTest-v2-FF.assets.json @@ -0,0 +1,20 @@ +{ + "version": "38.0.1", + "files": { + "0aaa25e74c3bd8b4c72922081490518294b93ff15f40df38ae16908cbe6d69c5": { + "source": { + "path": "ResourcePolicyTest-v2-FF.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-eu-west-1": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-eu-west-1", + "objectKey": "0aaa25e74c3bd8b4c72922081490518294b93ff15f40df38ae16908cbe6d69c5.json", + "region": "eu-west-1", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-eu-west-1" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy-ff.js.snapshot/ResourcePolicyTest-v2-FF.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy-ff.js.snapshot/ResourcePolicyTest-v2-FF.template.json new file mode 100644 index 0000000000000..28240d04c34e3 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy-ff.js.snapshot/ResourcePolicyTest-v2-FF.template.json @@ -0,0 +1,95 @@ +{ + "Resources": { + "TableTestV215EEA02B7": { + "Type": "AWS::DynamoDB::GlobalTable", + "Properties": { + "AttributeDefinitions": [ + { + "AttributeName": "id", + "AttributeType": "S" + } + ], + "BillingMode": "PAY_PER_REQUEST", + "KeySchema": [ + { + "AttributeName": "id", + "KeyType": "HASH" + } + ], + "Replicas": [ + { + "Region": "eu-west-2" + }, + { + "Region": "eu-west-1", + "ResourcePolicy": { + "PolicyDocument": { + "Statement": [ + { + "Action": "dynamodb:*", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:aws:iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] + } + }, + "Resource": "*" + } + ], + "Version": "2012-10-17" + } + } + } + ], + "StreamSpecification": { + "StreamViewType": "NEW_AND_OLD_IMAGES" + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy-ff.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy-ff.js.snapshot/cdk.out new file mode 100644 index 0000000000000..c6e612584e352 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy-ff.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"38.0.1"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy-ff.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy-ff.js.snapshot/integ.json new file mode 100644 index 0000000000000..0be4870b3749d --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy-ff.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "38.0.1", + "testCases": { + "table-v2-resource-policy-integ-test/DefaultTest": { + "stacks": [ + "ResourcePolicyTest-v2-FF" + ], + "assertionStack": "table-v2-resource-policy-integ-test/DefaultTest/DeployAssert", + "assertionStackName": "tablev2resourcepolicyintegtestDefaultTestDeployAssertBE3353C7" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy-ff.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy-ff.js.snapshot/manifest.json new file mode 100644 index 0000000000000..a84913e0473df --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy-ff.js.snapshot/manifest.json @@ -0,0 +1,115 @@ +{ + "version": "38.0.1", + "artifacts": { + "ResourcePolicyTest-v2-FF.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "ResourcePolicyTest-v2-FF.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "ResourcePolicyTest-v2-FF": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/eu-west-1", + "properties": { + "templateFile": "ResourcePolicyTest-v2-FF.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "notificationArns": [], + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-eu-west-1", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-eu-west-1", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-eu-west-1/0aaa25e74c3bd8b4c72922081490518294b93ff15f40df38ae16908cbe6d69c5.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "ResourcePolicyTest-v2-FF.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-eu-west-1", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "ResourcePolicyTest-v2-FF.assets" + ], + "metadata": { + "/ResourcePolicyTest-v2-FF/TableTestV2-1/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "TableTestV215EEA02B7" + } + ], + "/ResourcePolicyTest-v2-FF/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/ResourcePolicyTest-v2-FF/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "ResourcePolicyTest-v2-FF" + }, + "tablev2resourcepolicyintegtestDefaultTestDeployAssertBE3353C7.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "tablev2resourcepolicyintegtestDefaultTestDeployAssertBE3353C7.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "tablev2resourcepolicyintegtestDefaultTestDeployAssertBE3353C7": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "tablev2resourcepolicyintegtestDefaultTestDeployAssertBE3353C7.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "notificationArns": [], + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "tablev2resourcepolicyintegtestDefaultTestDeployAssertBE3353C7.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "tablev2resourcepolicyintegtestDefaultTestDeployAssertBE3353C7.assets" + ], + "metadata": { + "/table-v2-resource-policy-integ-test/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/table-v2-resource-policy-integ-test/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "table-v2-resource-policy-integ-test/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy-ff.js.snapshot/tablev2resourcepolicyintegtestDefaultTestDeployAssertBE3353C7.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy-ff.js.snapshot/tablev2resourcepolicyintegtestDefaultTestDeployAssertBE3353C7.assets.json new file mode 100644 index 0000000000000..d49a26b8c2ab8 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy-ff.js.snapshot/tablev2resourcepolicyintegtestDefaultTestDeployAssertBE3353C7.assets.json @@ -0,0 +1,19 @@ +{ + "version": "38.0.1", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "tablev2resourcepolicyintegtestDefaultTestDeployAssertBE3353C7.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy-ff.js.snapshot/tablev2resourcepolicyintegtestDefaultTestDeployAssertBE3353C7.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy-ff.js.snapshot/tablev2resourcepolicyintegtestDefaultTestDeployAssertBE3353C7.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy-ff.js.snapshot/tablev2resourcepolicyintegtestDefaultTestDeployAssertBE3353C7.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy-ff.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy-ff.js.snapshot/tree.json new file mode 100644 index 0000000000000..b3a565db2d3c0 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy-ff.js.snapshot/tree.json @@ -0,0 +1,174 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "ResourcePolicyTest-v2-FF": { + "id": "ResourcePolicyTest-v2-FF", + "path": "ResourcePolicyTest-v2-FF", + "children": { + "TableTestV2-1": { + "id": "TableTestV2-1", + "path": "ResourcePolicyTest-v2-FF/TableTestV2-1", + "children": { + "Resource": { + "id": "Resource", + "path": "ResourcePolicyTest-v2-FF/TableTestV2-1/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::DynamoDB::GlobalTable", + "aws:cdk:cloudformation:props": { + "attributeDefinitions": [ + { + "attributeName": "id", + "attributeType": "S" + } + ], + "billingMode": "PAY_PER_REQUEST", + "keySchema": [ + { + "attributeName": "id", + "keyType": "HASH" + } + ], + "replicas": [ + { + "region": "eu-west-2" + }, + { + "region": "eu-west-1", + "resourcePolicy": { + "policyDocument": { + "Statement": [ + { + "Action": "dynamodb:*", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:aws:iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] + } + }, + "Resource": "*" + } + ], + "Version": "2012-10-17" + } + } + } + ], + "streamSpecification": { + "streamViewType": "NEW_AND_OLD_IMAGES" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_dynamodb.CfnGlobalTable", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_dynamodb.TableBaseV2", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "ResourcePolicyTest-v2-FF/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "ResourcePolicyTest-v2-FF/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "table-v2-resource-policy-integ-test": { + "id": "table-v2-resource-policy-integ-test", + "path": "table-v2-resource-policy-integ-test", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "table-v2-resource-policy-integ-test/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "table-v2-resource-policy-integ-test/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "table-v2-resource-policy-integ-test/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "table-v2-resource-policy-integ-test/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "table-v2-resource-policy-integ-test/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy-ff.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy-ff.ts new file mode 100644 index 0000000000000..819561ce50d08 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy-ff.ts @@ -0,0 +1,47 @@ +import { App, RemovalPolicy, Stack, StackProps } from 'aws-cdk-lib'; +import { Construct } from 'constructs'; +import * as dynamodb from 'aws-cdk-lib/aws-dynamodb'; +import * as iam from 'aws-cdk-lib/aws-iam'; +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; + +const app = new App({ + postCliContext: { + '@aws-cdk/aws-dynamodb:resourcePolicyPerReplica': true, + }, +}); + +class TestStack extends Stack { + constructor(scope: Construct, id: string, props?: StackProps) { + super(scope, id, props); + + const docu = new iam.PolicyDocument({ + statements: [ + new iam.PolicyStatement({ + actions: ['dynamodb:*'], + principals: [new iam.AccountRootPrincipal()], + resources: ['*'], + }), + ], + }); + + // table with resource policy + new dynamodb.TableV2(this, 'TableTestV2-1', { + partitionKey: { + name: 'id', + type: dynamodb.AttributeType.STRING, + }, + removalPolicy: RemovalPolicy.DESTROY, + resourcePolicy: docu, + replicas: [{ + region: 'eu-west-2', + }], + }); + + } +} + +const stack = new TestStack(app, 'ResourcePolicyTest-v2-FF', { env: { region: 'eu-west-1' } }); + +new IntegTest(app, 'table-v2-resource-policy-integ-test', { + testCases: [stack], +}); \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy.ts index 5a30de692de21..50ca86a684b2d 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-dynamodb/test/integ.dynamodb-v2.policy.ts @@ -4,7 +4,11 @@ import * as dynamodb from 'aws-cdk-lib/aws-dynamodb'; import * as iam from 'aws-cdk-lib/aws-iam'; import { IntegTest } from '@aws-cdk/integ-tests-alpha'; -const app = new App(); +const app = new App({ + postCliContext: { + '@aws-cdk/aws-dynamodb:resourcePolicyPerReplica': false, + }, +}); class TestStack extends Stack { constructor(scope: Construct, id: string, props?: StackProps) { @@ -21,7 +25,7 @@ class TestStack extends Stack { }); // table with resource policy - const table = new dynamodb.TableV2(this, 'TableTestV2-1', { + new dynamodb.TableV2(this, 'TableTestV2-1', { partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING, @@ -30,7 +34,6 @@ class TestStack extends Stack { resourcePolicy: docu, }); - table.grantReadData(new iam.AccountPrincipal('123456789012')); } } diff --git a/packages/aws-cdk-lib/aws-dynamodb/lib/table-v2.ts b/packages/aws-cdk-lib/aws-dynamodb/lib/table-v2.ts index 65e3c588968e5..b6507d3f7deb1 100644 --- a/packages/aws-cdk-lib/aws-dynamodb/lib/table-v2.ts +++ b/packages/aws-cdk-lib/aws-dynamodb/lib/table-v2.ts @@ -12,7 +12,8 @@ import { TableBaseV2, ITableV2 } from './table-v2-base'; import { PolicyDocument } from '../../aws-iam'; import { IStream } from '../../aws-kinesis'; import { IKey, Key } from '../../aws-kms'; -import { ArnFormat, CfnTag, Lazy, PhysicalName, RemovalPolicy, Stack, Token } from '../../core'; +import { ArnFormat, CfnTag, FeatureFlags, Lazy, PhysicalName, RemovalPolicy, Stack, Token } from '../../core'; +import * as cxapi from '../../cx-api'; const HASH_KEY_TYPE = 'HASH'; const RANGE_KEY_TYPE = 'RANGE'; @@ -664,7 +665,14 @@ export class TableV2 extends TableBaseV2 { private configureReplicaTable(props: ReplicaTableProps): CfnGlobalTable.ReplicaSpecificationProperty { const pointInTimeRecovery = props.pointInTimeRecovery ?? this.tableOptions.pointInTimeRecovery; const contributorInsights = props.contributorInsights ?? this.tableOptions.contributorInsights; - const resourcePolicy = props.resourcePolicy ?? this.tableOptions.resourcePolicy; + /* + * Feature flag set as the following may be a breaking change. + * @see https://github.com/aws/aws-cdk/pull/31097 + * @see https://github.com/aws/aws-cdk/blob/main/packages/%40aws-cdk/cx-api/FEATURE_FLAGS.md + */ + const resourcePolicy = FeatureFlags.of(this).isEnabled(cxapi.DYNAMODB_TABLEV2_RESOURCE_POLICY_PER_REPLICA) + ? (props.region === this.region ? this.tableOptions.resourcePolicy : props.resourcePolicy) || undefined + : props.resourcePolicy ?? this.tableOptions.resourcePolicy; return { region: props.region, diff --git a/packages/aws-cdk-lib/cx-api/README.md b/packages/aws-cdk-lib/cx-api/README.md index 68a16be402040..f90bcac9b4f13 100644 --- a/packages/aws-cdk-lib/cx-api/README.md +++ b/packages/aws-cdk-lib/cx-api/README.md @@ -475,3 +475,22 @@ _cdk.json_ } } ``` + +* `@aws-cdk/aws-dynamodb:resourcePolicyPerReplica` + +If this flag is not set, the default behavior for \`TableV2\` is to use a different \`resourcePolicy\` for each replica. + +If this flag is set to false, the behavior is that each replica shares the same \`resourcePolicy\` as the source table. +This will prevent you from creating a new table which has an additional replica and a resource policy. + +This is a feature flag as the old behavior was technically incorrect but users may have come to depend on it. + +_cdk.json_ + +```json +{ + "context": { + "@aws-cdk/aws-dynamodb:resourcePolicyPerReplica": false, + }, +} +``` \ No newline at end of file diff --git a/packages/aws-cdk-lib/cx-api/lib/features.ts b/packages/aws-cdk-lib/cx-api/lib/features.ts index 7cd1ee4b5e7e0..182d14a5f738f 100644 --- a/packages/aws-cdk-lib/cx-api/lib/features.ts +++ b/packages/aws-cdk-lib/cx-api/lib/features.ts @@ -108,6 +108,7 @@ export const LOG_API_RESPONSE_DATA_PROPERTY_TRUE_DEFAULT = '@aws-cdk/custom-reso export const S3_KEEP_NOTIFICATION_IN_IMPORTED_BUCKET = '@aws-cdk/aws-s3:keepNotificationInImportedBucket'; export const USE_NEW_S3URI_PARAMETERS_FOR_BEDROCK_INVOKE_MODEL_TASK = '@aws-cdk/aws-stepfunctions-tasks:useNewS3UriParametersForBedrockInvokeModelTask'; export const REDUCE_EC2_FARGATE_CLOUDWATCH_PERMISSIONS = '@aws-cdk/aws-ecs:reduceEc2FargateCloudWatchPermissions'; +export const DYNAMODB_TABLEV2_RESOURCE_POLICY_PER_REPLICA = '@aws-cdk/aws-dynamodb:resourcePolicyPerReplica'; export const EC2_SUM_TIMEOUT_ENABLED = '@aws-cdk/aws-ec2:ec2SumTImeoutEnabled'; export const APPSYNC_GRAPHQLAPI_SCOPE_LAMBDA_FUNCTION_PERMISSION = '@aws-cdk/aws-appsync:appSyncGraphQLAPIScopeLambdaPermission'; export const USE_CORRECT_VALUE_FOR_INSTANCE_RESOURCE_ID_PROPERTY = '@aws-cdk/aws-rds:setCorrectValueForDatabaseInstanceReadReplicaInstanceResourceId'; @@ -1149,6 +1150,21 @@ export const FLAGS: Record = { compatibilityWithOldBehaviorMd: 'Disable the feature flag to continue grant permissions to log group when no log group is specified', }, + ////////////////////////////////////////////////////////////////////// + [DYNAMODB_TABLEV2_RESOURCE_POLICY_PER_REPLICA]: { + type: FlagType.BugFix, + summary: 'When enabled will allow you to specify a resource policy per replica, and not copy the source table policy to all replicas', + detailsMd: ` + If this flag is not set, the default behavior for \`TableV2\` is to use a different \`resourcePolicy\` for each replica. + + If this flag is set to false, the behavior is that each replica shares the same \`resourcePolicy\` as the source table. + This will prevent you from creating a new table which has an additional replica and a resource policy. + + This is a feature flag as the old behavior was technically incorrect but users may have come to depend on it.`, + introducedIn: { v2: 'V2NEXT' }, + recommendedValue: true, + }, + ////////////////////////////////////////////////////////////////////// [EC2_SUM_TIMEOUT_ENABLED]: { type: FlagType.BugFix,