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/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/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 { diff --git a/packages/aws-cdk/lib/api/hotswap-deployments.ts b/packages/aws-cdk/lib/api/hotswap-deployments.ts index 17db0805e555f..427561fce67a6 100644 --- a/packages/aws-cdk/lib/api/hotswap-deployments.ts +++ b/packages/aws-cdk/lib/api/hotswap-deployments.ts @@ -7,7 +7,7 @@ import { EvaluateCloudFormationTemplate } from './evaluate-cloudformation-templa import { print } from '../logging'; import { isHotswappableAppSyncChange } from './hotswap/appsync-mapping-templates'; import { isHotswappableCodeBuildProjectChange } from './hotswap/code-build-projects'; -import { ICON, ChangeHotswapResult, HotswapMode, HotswappableChange, NonHotswappableChange, HotswappableChangeCandidate, ClassifiedResourceChanges, reportNonHotswappableChange, reportNonHotswappableResource } from './hotswap/common'; +import { ICON, ChangeHotswapResult, HotswapMode, HotswappableChange, NonHotswappableChange, HotswappableChangeCandidate, HotswapPropertyOverrides, ClassifiedResourceChanges, reportNonHotswappableChange, reportNonHotswappableResource } from './hotswap/common'; import { isHotswappableEcsServiceChange } from './hotswap/ecs-services'; import { isHotswappableLambdaFunctionChange } from './hotswap/lambda-functions'; import { skipChangeForS3DeployCustomResourcePolicy, isHotswappableS3BucketDeploymentChange } from './hotswap/s3-bucket-deployments'; @@ -20,7 +20,10 @@ import { CloudFormationStack } from './util/cloudformation'; const pLimit: typeof import('p-limit') = require('p-limit'); type HotswapDetector = ( - logicalId: string, change: HotswappableChangeCandidate, evaluateCfnTemplate: EvaluateCloudFormationTemplate + logicalId: string, + change: HotswappableChangeCandidate, + evaluateCfnTemplate: EvaluateCloudFormationTemplate, + hotswapPropertyOverrides: HotswapPropertyOverrides, ) => 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); } }