From b8f02eca3445553df591721dcd0733fc0deb028b Mon Sep 17 00:00:00 2001 From: Christopher Rybicki Date: Wed, 22 Sep 2021 14:35:46 -0700 Subject: [PATCH 01/87] chore: add Chriscbr to mergify --- .mergify.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mergify.yml b/.mergify.yml index 97f3ce42a91be..993a25aee5269 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -6,7 +6,7 @@ pull_request_rules: label: add: [ contribution/core ] conditions: - - author~=^(eladb|RomainMuller|garnaat|nija-at|skinny85|rix0rrr|NGL321|Jerry-AWS|MrArnoldPalmer|NetaNir|iliapolo|njlynch|ericzbeard|ccfife|fulghum|pkandasamy91|SoManyHs|uttarasridhar|otaviomacedo|BenChaimberg|madeline-k|BryanPan342|kaizen3031593|comcalvi)$ + - author~=^(eladb|RomainMuller|garnaat|nija-at|skinny85|rix0rrr|NGL321|Jerry-AWS|MrArnoldPalmer|NetaNir|iliapolo|njlynch|ericzbeard|ccfife|fulghum|pkandasamy91|SoManyHs|uttarasridhar|otaviomacedo|BenChaimberg|madeline-k|BryanPan342|kaizen3031593|comcalvi|Chriscbr)$ - -label~="contribution/core" - name: automatic merge actions: From ee24046466f42efca4bf2b14ce9f344f174afa78 Mon Sep 17 00:00:00 2001 From: Nick Lynch Date: Thu, 21 Oct 2021 16:15:43 +0100 Subject: [PATCH 02/87] chore(individual-pkg-gen): strip redundant 'aws' from go package names (#17097) Currently, the published go alpha modules look like this: `github.com/aws/aws-cdk-go/awscdkawsfoobaralpha/v2` The redundant 'aws' in front of each service package name leads to a longer package name than necessary, on an already long name. This change explicitly sets the 'go' package name for each of the alpha modules, so they turn out like this: `github.com/aws/aws-cdk-go/awscdkfoobaralpha/v2` ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- tools/@aws-cdk/individual-pkg-gen/transform-packages.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/@aws-cdk/individual-pkg-gen/transform-packages.ts b/tools/@aws-cdk/individual-pkg-gen/transform-packages.ts index a5cbcb556ea1b..b56e39c788f2b 100644 --- a/tools/@aws-cdk/individual-pkg-gen/transform-packages.ts +++ b/tools/@aws-cdk/individual-pkg-gen/transform-packages.ts @@ -175,9 +175,11 @@ function transformPackageJson(pkg: any, source: string, destination: string, alp jsiiTargets.python.distName += '-alpha'; jsiiTargets.python.module += '_alpha'; // Typically, only our top-level packages have a Go target. - // moduleName is needed; packageName will be automatically derived by from the package name. + // packageName has unusable chars and redundant 'aws' stripped. + // This generates names like 'awscdkfoobaralpha' (rather than 'awscdkawsfoobaralpha'). jsiiTargets.go = { moduleName: 'github.com/aws/aws-cdk-go', + packageName: packageJson.name.replace('/aws-', '').replace(/[^a-z0-9.]/gi, '').toLowerCase(), }; const finalPackageJson = transformPackageJsonDependencies(packageJson, pkg, alphaPackages); From 86f85ce10f78b86133f9dab9851e56d03fb28cc0 Mon Sep 17 00:00:00 2001 From: Tatsuya Yamamoto Date: Fri, 22 Oct 2021 03:46:55 +0900 Subject: [PATCH 03/87] feat(iot): add the TopicRule L2 construct (#16681) I tried to implement aws-iot L2 Constructs. I did following: 1. add L2 construct 1. add unit tests 1. add integration test 1. test with deploying to my AWS account and sending MQTT. 1. update package.json resolves: #16602 I should do following for undrafting: - [x] write comments - [x] implement other actions Following is not implemented yet, but I will implements other PR. - Elasticsearch - Kinesis Firehose - Kinesis Stream - http - IoT Analytics - IoT Events - IoT SiteWise - kafka - Step Functions - [x] write README ---- ## Design ### TopicRule and IAction ![image](https://user-images.githubusercontent.com/11013683/136200920-9aa1aa58-2e9f-4a0d-a161-bbe251d02f7d.png) ### Implements of IAction ![image](https://user-images.githubusercontent.com/11013683/136201053-4f693683-3318-4fbf-9a7e-cd3f8ac1a93e.png) ---- *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-iot/README.md | 41 +++++- packages/@aws-cdk/aws-iot/lib/index.ts | 3 + packages/@aws-cdk/aws-iot/lib/iot-sql.ts | 75 +++++++++++ packages/@aws-cdk/aws-iot/lib/topic-rule.ts | 106 +++++++++++++++ packages/@aws-cdk/aws-iot/package.json | 6 +- .../test/integ.topic-rule.expected.json | 14 ++ .../@aws-cdk/aws-iot/test/integ.topic-rule.ts | 18 +++ packages/@aws-cdk/aws-iot/test/iot.test.ts | 6 - .../@aws-cdk/aws-iot/test/topic-rule.test.ts | 124 ++++++++++++++++++ 9 files changed, 384 insertions(+), 9 deletions(-) create mode 100644 packages/@aws-cdk/aws-iot/lib/iot-sql.ts create mode 100644 packages/@aws-cdk/aws-iot/lib/topic-rule.ts create mode 100644 packages/@aws-cdk/aws-iot/test/integ.topic-rule.expected.json create mode 100644 packages/@aws-cdk/aws-iot/test/integ.topic-rule.ts delete mode 100644 packages/@aws-cdk/aws-iot/test/iot.test.ts create mode 100644 packages/@aws-cdk/aws-iot/test/topic-rule.test.ts diff --git a/packages/@aws-cdk/aws-iot/README.md b/packages/@aws-cdk/aws-iot/README.md index 7334c9d4e108e..bbde9aae8a21d 100644 --- a/packages/@aws-cdk/aws-iot/README.md +++ b/packages/@aws-cdk/aws-iot/README.md @@ -9,8 +9,47 @@ > > [CFN Resources]: https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib +![cdk-constructs: Experimental](https://img.shields.io/badge/cdk--constructs-experimental-important.svg?style=for-the-badge) + +> The APIs of higher level constructs in this module are experimental and under active development. +> They are subject to non-backward compatible changes or removal in any future version. These are +> not subject to the [Semantic Versioning](https://semver.org/) model and breaking changes will be +> announced in the release notes. This means that while you may use them, you may need to update +> your source code when upgrading to a newer version of this package. + --- -This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project. +AWS IoT Core lets you connect billions of IoT devices and route trillions of +messages to AWS services without managing infrastructure. + +## Installation + +Install the module: + +```console +$ npm i @aws-cdk/aws-iot +``` + +Import it into your code: + +```ts +import * as iot from '@aws-cdk/aws-iot'; +``` + +## `TopicRule` + +The `TopicRule` construct defined Rules that give your devices the ability to +interact with AWS services. + +For example, to define a rule: + +```ts +new iot.TopicRule(stack, 'MyTopicRule', { + topicRuleName: 'MyRuleName', // optional property + sql: iot.IotSql.fromStringAsVer20160323( + "SELECT topic(2) as device_id, temperature FROM 'device/+/data'", + ), +}); +``` diff --git a/packages/@aws-cdk/aws-iot/lib/index.ts b/packages/@aws-cdk/aws-iot/lib/index.ts index 4f78a6cf531e3..18b6f2e03aaeb 100644 --- a/packages/@aws-cdk/aws-iot/lib/index.ts +++ b/packages/@aws-cdk/aws-iot/lib/index.ts @@ -1,2 +1,5 @@ +export * from './iot-sql'; +export * from './topic-rule'; + // AWS::IoT CloudFormation Resources: export * from './iot.generated'; diff --git a/packages/@aws-cdk/aws-iot/lib/iot-sql.ts b/packages/@aws-cdk/aws-iot/lib/iot-sql.ts new file mode 100644 index 0000000000000..c673552743364 --- /dev/null +++ b/packages/@aws-cdk/aws-iot/lib/iot-sql.ts @@ -0,0 +1,75 @@ +import { Construct } from 'constructs'; + +/** + * The type returned from the `bind()` method in {@link IotSql}. + */ +export interface IotSqlConfig { + /** + * The version of the SQL rules engine to use when evaluating the rule. + */ + readonly awsIotSqlVersion: string; + + /** + * The SQL statement used to query the topic. + */ + readonly sql: string; +} + +/** + * Defines AWS IoT SQL. + */ +export abstract class IotSql { + /** + * Uses the original SQL version built on 2015-10-08. + * + * @param sql The actual SQL-like syntax query + * @returns Instance of IotSql + */ + public static fromStringAsVer20151008(sql: string): IotSql { + return new IotSqlImpl('2015-10-08', sql); + } + + /** + * Uses the SQL version built on 2016-03-23. + * + * @param sql The actual SQL-like syntax query + * @returns Instance of IotSql + */ + public static fromStringAsVer20160323(sql: string): IotSql { + return new IotSqlImpl('2016-03-23', sql); + } + + /** + * Uses the most recent beta SQL version. If you use this version, it might + * introduce breaking changes to your rules. + * + * @param sql The actual SQL-like syntax query + * @returns Instance of IotSql + */ + public static fromStringAsVerNewestUnstable(sql: string): IotSql { + return new IotSqlImpl('beta', sql); + } + + /** + * Returns the IoT SQL configuration. + */ + public abstract bind(scope: Construct): IotSqlConfig; +} + + +class IotSqlImpl extends IotSql { + constructor(private readonly version: string, private readonly sql: string) { + super(); + + if (sql === '') { + throw new Error('IoT SQL string cannot be empty'); + } + } + + bind(_scope: Construct): IotSqlConfig { + return { + awsIotSqlVersion: this.version, + sql: this.sql, + }; + } +} diff --git a/packages/@aws-cdk/aws-iot/lib/topic-rule.ts b/packages/@aws-cdk/aws-iot/lib/topic-rule.ts new file mode 100644 index 0000000000000..17f121eb29ab3 --- /dev/null +++ b/packages/@aws-cdk/aws-iot/lib/topic-rule.ts @@ -0,0 +1,106 @@ +import { ArnFormat, Resource, Stack, IResource } from '@aws-cdk/core'; +import { Construct } from 'constructs'; +import { IotSql } from './iot-sql'; +import { CfnTopicRule } from './iot.generated'; + +/** + * Represents an AWS IoT Rule + */ +export interface ITopicRule extends IResource { + /** + * The value of the topic rule Amazon Resource Name (ARN), such as + * arn:aws:iot:us-east-2:123456789012:rule/rule_name + * + * @attribute + */ + readonly topicRuleArn: string; + + /** + * The name topic rule + * + * @attribute + */ + readonly topicRuleName: string; +} + +/** + * Properties for defining an AWS IoT Rule + */ +export interface TopicRuleProps { + /** + * The name of the rule. + * @default None + */ + readonly topicRuleName?: string; + + /** + * A simplified SQL syntax to filter messages received on an MQTT topic and push the data elsewhere. + * + * @see https://docs.aws.amazon.com/iot/latest/developerguide/iot-sql-reference.html + */ + readonly sql: IotSql; +} + +/** + * Defines an AWS IoT Rule in this stack. + */ +export class TopicRule extends Resource implements ITopicRule { + /** + * Import an existing AWS IoT Rule provided an ARN + * + * @param scope The parent creating construct (usually `this`). + * @param id The construct's name. + * @param topicRuleArn AWS IoT Rule ARN (i.e. arn:aws:iot:::rule/MyRule). + */ + public static fromTopicRuleArn(scope: Construct, id: string, topicRuleArn: string): ITopicRule { + const parts = Stack.of(scope).splitArn(topicRuleArn, ArnFormat.SLASH_RESOURCE_NAME); + if (!parts.resourceName) { + throw new Error(`Missing topic rule name in ARN: '${topicRuleArn}'`); + } + const resourceName = parts.resourceName; + + class Import extends Resource implements ITopicRule { + public readonly topicRuleArn = topicRuleArn; + public readonly topicRuleName = resourceName; + } + return new Import(scope, id, { + environmentFromArn: topicRuleArn, + }); + } + + /** + * Arn of this rule + * @attribute + */ + public readonly topicRuleArn: string; + + /** + * Name of this rule + * @attribute + */ + public readonly topicRuleName: string; + + constructor(scope: Construct, id: string, props: TopicRuleProps) { + super(scope, id, { + physicalName: props.topicRuleName, + }); + + const sqlConfig = props.sql.bind(this); + + const resource = new CfnTopicRule(this, 'Resource', { + ruleName: this.physicalName, + topicRulePayload: { + actions: [], + awsIotSqlVersion: sqlConfig.awsIotSqlVersion, + sql: sqlConfig.sql, + }, + }); + + this.topicRuleArn = this.getResourceArnAttribute(resource.attrArn, { + service: 'iot', + resource: 'rule', + resourceName: this.physicalName, + }); + this.topicRuleName = this.getResourceNameAttribute(resource.ref); + } +} diff --git a/packages/@aws-cdk/aws-iot/package.json b/packages/@aws-cdk/aws-iot/package.json index 9960168c78ec1..074ebd9c79435 100644 --- a/packages/@aws-cdk/aws-iot/package.json +++ b/packages/@aws-cdk/aws-iot/package.json @@ -74,9 +74,11 @@ "devDependencies": { "@aws-cdk/assertions": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", + "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^26.0.24" + "@types/jest": "^26.0.24", + "jest": "^26.6.3" }, "dependencies": { "@aws-cdk/core": "0.0.0", @@ -91,7 +93,7 @@ "node": ">= 10.13.0 <13 || >=13.7.0" }, "stability": "experimental", - "maturity": "cfn-only", + "maturity": "experimental", "awscdkio": { "announce": false }, diff --git a/packages/@aws-cdk/aws-iot/test/integ.topic-rule.expected.json b/packages/@aws-cdk/aws-iot/test/integ.topic-rule.expected.json new file mode 100644 index 0000000000000..cf4be2735229e --- /dev/null +++ b/packages/@aws-cdk/aws-iot/test/integ.topic-rule.expected.json @@ -0,0 +1,14 @@ +{ + "Resources": { + "TopicRule40A4EA44": { + "Type": "AWS::IoT::TopicRule", + "Properties": { + "TopicRulePayload": { + "Actions": [], + "AwsIotSqlVersion": "2015-10-08", + "Sql": "SELECT topic(2) as device_id FROM 'device/+/data'" + } + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-iot/test/integ.topic-rule.ts b/packages/@aws-cdk/aws-iot/test/integ.topic-rule.ts new file mode 100644 index 0000000000000..a06edc3c3f5e1 --- /dev/null +++ b/packages/@aws-cdk/aws-iot/test/integ.topic-rule.ts @@ -0,0 +1,18 @@ +/// !cdk-integ pragma:ignore-assets +import * as cdk from '@aws-cdk/core'; +import * as iot from '../lib'; + +const app = new cdk.App(); + +class TestStack extends cdk.Stack { + constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { + super(scope, id, props); + + new iot.TopicRule(this, 'TopicRule', { + sql: iot.IotSql.fromStringAsVer20151008("SELECT topic(2) as device_id FROM 'device/+/data'"), + }); + } +} + +new TestStack(app, 'test-stack'); +app.synth(); diff --git a/packages/@aws-cdk/aws-iot/test/iot.test.ts b/packages/@aws-cdk/aws-iot/test/iot.test.ts deleted file mode 100644 index 465c7bdea0693..0000000000000 --- a/packages/@aws-cdk/aws-iot/test/iot.test.ts +++ /dev/null @@ -1,6 +0,0 @@ -import '@aws-cdk/assertions'; -import {} from '../lib'; - -test('No tests are specified for this package', () => { - expect(true).toBe(true); -}); diff --git a/packages/@aws-cdk/aws-iot/test/topic-rule.test.ts b/packages/@aws-cdk/aws-iot/test/topic-rule.test.ts new file mode 100644 index 0000000000000..1dec8c3065a86 --- /dev/null +++ b/packages/@aws-cdk/aws-iot/test/topic-rule.test.ts @@ -0,0 +1,124 @@ +import { Template } from '@aws-cdk/assertions'; +import * as cdk from '@aws-cdk/core'; +import * as iot from '../lib'; + +test('Default property', () => { + const stack = new cdk.Stack(); + + new iot.TopicRule(stack, 'MyTopicRule', { + sql: iot.IotSql.fromStringAsVer20151008("SELECT topic(2) as device_id, temperature FROM 'device/+/data'"), + }); + + Template.fromStack(stack).hasResourceProperties('AWS::IoT::TopicRule', { + TopicRulePayload: { + Actions: [], + Sql: "SELECT topic(2) as device_id, temperature FROM 'device/+/data'", + }, + }); +}); + +test('can get topic rule name', () => { + const stack = new cdk.Stack(); + const rule = new iot.TopicRule(stack, 'MyTopicRule', { + sql: iot.IotSql.fromStringAsVer20151008("SELECT topic(2) as device_id, temperature FROM 'device/+/data'"), + }); + + new cdk.CfnResource(stack, 'Res', { + type: 'Test::Resource', + properties: { + TopicRuleName: rule.topicRuleName, + }, + }); + + Template.fromStack(stack).hasResourceProperties('Test::Resource', { + TopicRuleName: { Ref: 'MyTopicRule4EC2091C' }, + }); +}); + +test('can get topic rule arn', () => { + const stack = new cdk.Stack(); + const rule = new iot.TopicRule(stack, 'MyTopicRule', { + sql: iot.IotSql.fromStringAsVer20151008("SELECT topic(2) as device_id, temperature FROM 'device/+/data'"), + }); + + new cdk.CfnResource(stack, 'Res', { + type: 'Test::Resource', + properties: { + TopicRuleArn: rule.topicRuleArn, + }, + }); + + Template.fromStack(stack).hasResourceProperties('Test::Resource', { + TopicRuleArn: { + 'Fn::GetAtt': ['MyTopicRule4EC2091C', 'Arn'], + }, + }); +}); + +test('can set physical name', () => { + // GIVEN + const stack = new cdk.Stack(); + + // WHEN + new iot.TopicRule(stack, 'MyTopicRule', { + topicRuleName: 'PhysicalName', + sql: iot.IotSql.fromStringAsVer20151008("SELECT topic(2) as device_id, temperature FROM 'device/+/data'"), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::IoT::TopicRule', { + RuleName: 'PhysicalName', + }); +}); + +test.each([ + ['fromStringAsVer20151008', iot.IotSql.fromStringAsVer20151008, '2015-10-08'], + ['fromStringAsVer20160323', iot.IotSql.fromStringAsVer20160323, '2016-03-23'], + ['fromStringAsVerNewestUnstable', iot.IotSql.fromStringAsVerNewestUnstable, 'beta'], +])('can set sql with using %s', (_, factoryMethod, version) => { + const stack = new cdk.Stack(); + + new iot.TopicRule(stack, 'MyTopicRule', { + sql: factoryMethod("SELECT topic(2) as device_id, temperature FROM 'device/+/data'"), + }); + + Template.fromStack(stack).hasResourceProperties('AWS::IoT::TopicRule', { + TopicRulePayload: { + AwsIotSqlVersion: version, + Sql: "SELECT topic(2) as device_id, temperature FROM 'device/+/data'", + }, + }); +}); + +test.each([ + ['fromStringAsVer20151008', iot.IotSql.fromStringAsVer20151008], + ['fromStringAsVer20160323', iot.IotSql.fromStringAsVer20160323], + ['fromStringAsVerNewestUnstable', iot.IotSql.fromStringAsVerNewestUnstable], +])('Using %s fails when setting empty sql', (_, factoryMethod) => { + expect(() => { + factoryMethod(''); + }).toThrow('IoT SQL string cannot be empty'); +}); + +test('can import a TopicRule by ARN', () => { + const stack = new cdk.Stack(); + + const topicRuleArn = 'arn:aws:iot:ap-northeast-1:123456789012:rule/my-rule-name'; + + const topicRule = iot.TopicRule.fromTopicRuleArn(stack, 'TopicRuleFromArn', topicRuleArn); + + expect(topicRule).toMatchObject({ + topicRuleArn, + topicRuleName: 'my-rule-name', + }); +}); + +test('fails importing a TopicRule by ARN if the ARN is missing the name of the TopicRule', () => { + const stack = new cdk.Stack(); + + const topicRuleArn = 'arn:aws:iot:ap-northeast-1:123456789012:rule/'; + + expect(() => { + iot.TopicRule.fromTopicRuleArn(stack, 'TopicRuleFromArn', topicRuleArn); + }).toThrow("Missing topic rule name in ARN: 'arn:aws:iot:ap-northeast-1:123456789012:rule/'"); +}); From b0d5a573d1d545623713f86cbb185c0ed61d0330 Mon Sep 17 00:00:00 2001 From: Andreas Skyman Date: Thu, 21 Oct 2021 22:57:17 +0200 Subject: [PATCH 04/87] chore: Missing ; makes initialised test fail linting (#16637) The missing ; in the template makes the newly generated test file fail linting. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../v1/app/typescript/test/%name%.test.template.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/aws-cdk/lib/init-templates/v1/app/typescript/test/%name%.test.template.ts b/packages/aws-cdk/lib/init-templates/v1/app/typescript/test/%name%.test.template.ts index b98e4f0abee50..a574690020687 100644 --- a/packages/aws-cdk/lib/init-templates/v1/app/typescript/test/%name%.test.template.ts +++ b/packages/aws-cdk/lib/init-templates/v1/app/typescript/test/%name%.test.template.ts @@ -9,5 +9,5 @@ test('Empty Stack', () => { // THEN expectCDK(stack).to(matchTemplate({ "Resources": {} - }, MatchStyle.EXACT)) + }, MatchStyle.EXACT)); }); From 3617b70527516237955b8415fcfc8b58d3e23b3c Mon Sep 17 00:00:00 2001 From: Matt Berry Date: Thu, 21 Oct 2021 14:50:27 -0700 Subject: [PATCH 05/87] fix(custom-resources): Role Session Name can exceed maximum size (#16680) The provider used the physical resource id and the epoch time as the name of the assumed role session. Unfortunately, the maximum length of these two fields combined can exceed the 64 character limit on a role session name. The role session name is not extremely important, it's purely for human consumption. Nothing ensures that every assumed role session has a unique role session name. For a unique identifier, the session's access key identifier should be used instead. This change caps the generate role session name at 64 characters and moves the timestamp to the front, so that it is not the portion of the name that is truncated. https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-quotas.html ``` 2021-09-28T01:36:45.780Z fc8f6e02-d746-441b-b07c-5e2b836087a0 INFO Error [CredentialsError]: Missing credentials in config, if using AWS_CONFIG_FILE, set AWS_SDK_LOAD_CONFIG=1 at Request.extractError (/var/runtime/node_modules/aws-sdk/lib/protocol/query.js:50:29) at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:106:20) at Request.emit (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:78:10) at Request.emit (/var/runtime/node_modules/aws-sdk/lib/request.js:688:14) at Request.transition (/var/runtime/node_modules/aws-sdk/lib/request.js:22:10) at AcceptorStateMachine.runTo (/var/runtime/node_modules/aws-sdk/lib/state_machine.js:14:12) at /var/runtime/node_modules/aws-sdk/lib/state_machine.js:26:10 at Request. (/var/runtime/node_modules/aws-sdk/lib/request.js:38:9) at Request. (/var/runtime/node_modules/aws-sdk/lib/request.js:690:12) at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:116:18) { code: 'CredentialsError', time: 2021-09-28T01:36:45.659Z, requestId: '8aedc751-a552-449c-af2b-4566e3160d98', statusCode: 400, retryable: false, retryDelay: 38.712174099272744, originalError: { message: 'Could not load credentials from ChainableTemporaryCredentials', code: 'CredentialsError', time: 2021-09-28T01:36:45.659Z, requestId: '8aedc751-a552-449c-af2b-4566e3160d98', statusCode: 400, retryable: false, retryDelay: 38.712174099272744, originalError: { message: "1 validation error detected: Value 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-1632793004697' at 'roleSessionName' failed to satisfy constraint: Member must have length less than or equal to 64", code: 'ValidationError', time: 2021-09-28T01:36:45.657Z, requestId: '8aedc751-a552-449c-af2b-4566e3160d98', statusCode: 400, retryable: false, retryDelay: 38.712174099272744 } } } ``` ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../custom-resources/lib/aws-custom-resource/runtime/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/custom-resources/lib/aws-custom-resource/runtime/index.ts b/packages/@aws-cdk/custom-resources/lib/aws-custom-resource/runtime/index.ts index 68156b6412958..a805fc8c2bf4d 100644 --- a/packages/@aws-cdk/custom-resources/lib/aws-custom-resource/runtime/index.ts +++ b/packages/@aws-cdk/custom-resources/lib/aws-custom-resource/runtime/index.ts @@ -167,7 +167,7 @@ export async function handler(event: AWSLambda.CloudFormationCustomResourceEvent const params = { RoleArn: call.assumedRoleArn, - RoleSessionName: `${physicalResourceId}-${timestamp}`, + RoleSessionName: `${timestamp}-${physicalResourceId}`.substring(0, 64), }; AWS.config.credentials = new AWS.ChainableTemporaryCredentials({ From 5ba7f6ad13acad51c3c4280b9f2954acdd4a381c Mon Sep 17 00:00:00 2001 From: Ben Limmer Date: Thu, 21 Oct 2021 16:43:09 -0600 Subject: [PATCH 06/87] docs(iam): improve fromAwsManagedPolicyName documentation (#16737) This documentation was confusing to me. I kept reading it as "Do not include", even though it said "Do include". For clarity, this PR changes "Do include" to just "Include". ---- *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-iam/lib/managed-policy.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-iam/lib/managed-policy.ts b/packages/@aws-cdk/aws-iam/lib/managed-policy.ts index cc8bddc0e8a17..3fd1a936d4ab7 100644 --- a/packages/@aws-cdk/aws-iam/lib/managed-policy.ts +++ b/packages/@aws-cdk/aws-iam/lib/managed-policy.ts @@ -151,7 +151,7 @@ export class ManagedPolicy extends Resource implements IManagedPolicy { * For this managed policy, you only need to know the name to be able to use it. * * Some managed policy names start with "service-role/", some start with - * "job-function/", and some don't start with anything. Do include the + * "job-function/", and some don't start with anything. Include the * prefix when constructing this object. */ public static fromAwsManagedPolicyName(managedPolicyName: string): IManagedPolicy { From 131b4720362658ed237b9fd78c33ac8a98b92471 Mon Sep 17 00:00:00 2001 From: Alex Nelson Date: Thu, 21 Oct 2021 16:37:21 -0700 Subject: [PATCH 07/87] docs: corrected grammatical issues (#16809) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/@aws-cdk/pipelines/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/@aws-cdk/pipelines/README.md b/packages/@aws-cdk/pipelines/README.md index bd6525542920b..ac345c75f3776 100644 --- a/packages/@aws-cdk/pipelines/README.md +++ b/packages/@aws-cdk/pipelines/README.md @@ -38,7 +38,7 @@ with the same amount of code. The *CDK Pipelines* library takes care of the details. CDK Pipelines supports multiple *deployment engines* (see below), and comes with -a deployment engine that deployes CDK apps using AWS CodePipeline. To use the +a deployment engine that deploys CDK apps using AWS CodePipeline. To use the CodePipeline engine, define a `CodePipeline` construct. The following example creates a CodePipeline that deploys an application from GitHub: @@ -155,8 +155,8 @@ by adding the following to `cdk.json`: ## Provisioning the pipeline -To provision the pipeline you have defined, making sure the target environment -has been bootstrapped (see below), and then executing deploying the +To provision the pipeline you have defined, make sure the target environment +has been bootstrapped (see below), and then execute deploying the `PipelineStack` *once*. Afterwards, the pipeline will keep itself up-to-date. > **Important**: be sure to `git commit` and `git push` before deploying the @@ -175,7 +175,7 @@ $ cdk deploy PipelineStack ``` Administrative permissions to the account are only necessary up until -this point. We recommend you shed access to these credentials after doing this. +this point. We recommend you remove access to these credentials after doing this. ### Working on the pipeline From 985f7b9ce364097e9f91fa669e4158793e067afd Mon Sep 17 00:00:00 2001 From: Dan Cavallaro Date: Thu, 21 Oct 2021 20:31:20 -0400 Subject: [PATCH 08/87] docs(custom-resource): correcting links to S3File example code (#16822) Was reading the custom-resource documentation this morning (https://docs.aws.amazon.com/cdk/api/latest/docs/custom-resources-readme.html#s3file) and realized that both the S3File and S3Assert sections linked to the S3Assert sample code. Fixed the S3File links to point to the right files, and verified that they looked correct in the rendered Markdown. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/@aws-cdk/custom-resources/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/custom-resources/README.md b/packages/@aws-cdk/custom-resources/README.md index 8583e04bc087f..90892fb7906c7 100644 --- a/packages/@aws-cdk/custom-resources/README.md +++ b/packages/@aws-cdk/custom-resources/README.md @@ -301,8 +301,8 @@ This module includes a few examples for custom resource implementations: Provisions an object in an S3 bucket with textual contents. See the source code for the -[construct](https://github.com/aws/aws-cdk/blob/master/packages/%40aws-cdk/custom-resources/test/provider-framework/integration-test-fixtures/s3-assert.ts) and -[handler](https://github.com/aws/aws-cdk/blob/master/packages/%40aws-cdk/custom-resources/test/provider-framework/integration-test-fixtures/s3-assert-handler/index.py). +[construct](https://github.com/aws/aws-cdk/blob/master/packages/%40aws-cdk/custom-resources/test/provider-framework/integration-test-fixtures/s3-file.ts) and +[handler](https://github.com/aws/aws-cdk/blob/master/packages/%40aws-cdk/custom-resources/test/provider-framework/integration-test-fixtures/s3-file-handler/index.ts). The following example will create the file `folder/file1.txt` inside `myBucket` with the contents `hello!`. From f4dc54aef09d3b3e63fbd2efd35b084d8b8fa5d8 Mon Sep 17 00:00:00 2001 From: Jerry Kindall <52084730+Jerry-AWS@users.noreply.github.com> Date: Thu, 21 Oct 2021 18:24:15 -0700 Subject: [PATCH 09/87] docs: fix typo (#16833) otional -> optional ---- *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-events-targets/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-events-targets/README.md b/packages/@aws-cdk/aws-events-targets/README.md index a5c8fde1d9d98..76d25eab83dd3 100644 --- a/packages/@aws-cdk/aws-events-targets/README.md +++ b/packages/@aws-cdk/aws-events-targets/README.md @@ -65,7 +65,7 @@ const queue = new sqs.Queue(this, 'Queue'); rule.addTarget(new targets.LambdaFunction(fn, { deadLetterQueue: queue, // Optional: add a dead letter queue - maxEventAge: cdk.Duration.hours(2), // Otional: set the maxEventAge retry policy + maxEventAge: cdk.Duration.hours(2), // Optional: set the maxEventAge retry policy retryAttempts: 2, // Optional: set the max number of retry attempts })); ``` From 672acba9e532776832565d0fb91a59f261d6a466 Mon Sep 17 00:00:00 2001 From: tmokmss Date: Fri, 22 Oct 2021 11:16:17 +0900 Subject: [PATCH 10/87] docs(applicationautoscaling): fix wrong description for EnableScalingProps (#16863) `EnableScalingProps` has no relation to DynamoDB. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../aws-applicationautoscaling/lib/base-scalable-attribute.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-applicationautoscaling/lib/base-scalable-attribute.ts b/packages/@aws-cdk/aws-applicationautoscaling/lib/base-scalable-attribute.ts index 95d2a19c8a17d..6bb821240c6ff 100644 --- a/packages/@aws-cdk/aws-applicationautoscaling/lib/base-scalable-attribute.ts +++ b/packages/@aws-cdk/aws-applicationautoscaling/lib/base-scalable-attribute.ts @@ -86,7 +86,7 @@ export abstract class BaseScalableAttribute extends CoreConstruct { } /** - * Properties for enabling DynamoDB capacity scaling + * Properties for enabling Application Auto Scaling */ export interface EnableScalingProps { /** From 54ca9105194767c6d8401c7f439ff7919c225b4a Mon Sep 17 00:00:00 2001 From: Julian Michel Date: Fri, 22 Oct 2021 06:01:34 +0200 Subject: [PATCH 11/87] docs(core): fix CfnMapping example (#16882) The CloudFormation intrinsic function `Fn::FindInMap` only supports alphanumeric characters as name. However, the `CfnMapping` examples in the README file contain hyphens in the name field. This causes an error when the code is deployed. I changed the structure of the examples to create examples that can be deployed in AWS. Fixes #16866. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/@aws-cdk/core/README.md | 35 ++++++++++++++++++-------------- packages/aws-cdk-lib/README.md | 35 ++++++++++++++++++-------------- 2 files changed, 40 insertions(+), 30 deletions(-) diff --git a/packages/@aws-cdk/core/README.md b/packages/@aws-cdk/core/README.md index a6d4d2efc5a9b..1090d893c508d 100644 --- a/packages/@aws-cdk/core/README.md +++ b/packages/@aws-cdk/core/README.md @@ -753,16 +753,19 @@ CloudFormation [mappings][cfn-mappings] are created and queried using the ```ts const regionTable = new CfnMapping(this, 'RegionTable', { mapping: { - regionName: { - 'us-east-1': 'US East (N. Virginia)', - 'us-east-2': 'US East (Ohio)', + 'us-east-1': { + regionName: 'US East (N. Virginia)', + // ... + }, + 'us-east-2': { + regionName: 'US East (Ohio)', // ... }, // ... } }); -regionTable.findInMap('regionName', Aws.REGION); +regionTable.findInMap(Aws.REGION, 'regionName') ``` This will yield the following template: @@ -770,9 +773,10 @@ This will yield the following template: ```yaml Mappings: RegionTable: - regionName: - us-east-1: US East (N. Virginia) - us-east-2: US East (Ohio) + us-east-1: + regionName: US East (N. Virginia) + us-east-2: + regionName: US East (Ohio) ``` Mappings can also be synthesized "lazily"; lazy mappings will only render a "Mappings" @@ -787,24 +791,25 @@ call to `findInMap` will be able to resolve the value during synthesis and simpl ```ts const regionTable = new CfnMapping(this, 'RegionTable', { mapping: { - regionName: { - 'us-east-1': 'US East (N. Virginia)', - 'us-east-2': 'US East (Ohio)', + 'us-east-1': { + regionName: 'US East (N. Virginia)', + }, + 'us-east-2': { + regionName: 'US East (Ohio)', }, }, lazy: true, }); -regionTable.findInMap('regionName', 'us-east-2'); +regionTable.findInMap('us-east-2', 'regionName'); ``` On the other hand, the following code will produce the "Mappings" section shown above, -since the second-level key is an unresolved token. The call to `findInMap` will return a -token that resolves to `{ Fn::FindInMap: [ 'RegionTable', 'regionName', { Ref: AWS::Region -} ] }`. +since the top-level key is an unresolved token. The call to `findInMap` will return a token that resolves to +`{ "Fn::FindInMap": [ "RegionTable", { "Ref": "AWS::Region" }, "regionName" ] }`. ```ts -regionTable.findInMap('regionName', Aws.REGION); +regionTable.findInMap(Aws.REGION, 'regionName'); ``` [cfn-mappings]: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/mappings-section-structure.html diff --git a/packages/aws-cdk-lib/README.md b/packages/aws-cdk-lib/README.md index 48d4cd65f93a5..5d225ce542aa5 100644 --- a/packages/aws-cdk-lib/README.md +++ b/packages/aws-cdk-lib/README.md @@ -786,16 +786,19 @@ CloudFormation [mappings][cfn-mappings] are created and queried using the ```ts const regionTable = new CfnMapping(this, 'RegionTable', { mapping: { - regionName: { - 'us-east-1': 'US East (N. Virginia)', - 'us-east-2': 'US East (Ohio)', + 'us-east-1': { + regionName: 'US East (N. Virginia)', + // ... + }, + 'us-east-2': { + regionName: 'US East (Ohio)', // ... }, // ... } }); -regionTable.findInMap('regionName', Aws.REGION); +regionTable.findInMap(Aws.REGION, 'regionName') ``` This will yield the following template: @@ -803,9 +806,10 @@ This will yield the following template: ```yaml Mappings: RegionTable: - regionName: - us-east-1: US East (N. Virginia) - us-east-2: US East (Ohio) + us-east-1: + regionName: US East (N. Virginia) + us-east-2: + regionName: US East (Ohio) ``` Mappings can also be synthesized "lazily"; lazy mappings will only render a "Mappings" @@ -820,24 +824,25 @@ call to `findInMap` will be able to resolve the value during synthesis and simpl ```ts const regionTable = new CfnMapping(this, 'RegionTable', { mapping: { - regionName: { - 'us-east-1': 'US East (N. Virginia)', - 'us-east-2': 'US East (Ohio)', + 'us-east-1': { + regionName: 'US East (N. Virginia)', + }, + 'us-east-2': { + regionName: 'US East (Ohio)', }, }, lazy: true, }); -regionTable.findInMap('regionName', 'us-east-2'); +regionTable.findInMap('us-east-2', 'regionName'); ``` On the other hand, the following code will produce the "Mappings" section shown above, -since the second-level key is an unresolved token. The call to `findInMap` will return a -token that resolves to `{ Fn::FindInMap: [ 'RegionTable', 'regionName', { Ref: AWS::Region -} ] }`. +since the top-level key is an unresolved token. The call to `findInMap` will return a token that resolves to +`{ "Fn::FindInMap": [ "RegionTable", { "Ref": "AWS::Region" }, "regionName" ] }`. ```ts -regionTable.findInMap('regionName', Aws.REGION); +regionTable.findInMap(Aws.REGION, 'regionName'); ``` [cfn-mappings]: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/mappings-section-structure.html From 5f7c58bc9b4acc36a197e6ebebceda9923a50ec3 Mon Sep 17 00:00:00 2001 From: Kyle Wiest Date: Thu, 21 Oct 2021 21:56:08 -0700 Subject: [PATCH 12/87] docs: fix README - change Construct to Stage (#17079) A Stage is meant to hold collections of Stacks as a unit of deployment. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/@aws-cdk/core/README.md | 2 +- packages/aws-cdk-lib/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/core/README.md b/packages/@aws-cdk/core/README.md index 1090d893c508d..79ac6e6bb3e4d 100644 --- a/packages/@aws-cdk/core/README.md +++ b/packages/@aws-cdk/core/README.md @@ -48,7 +48,7 @@ logical application. You can then treat that new unit the same way you used to be able to treat a single stack: by instantiating it multiple times for different instances of your application. -You can define a custom subclass of `Construct`, holding one or more +You can define a custom subclass of `Stage`, holding one or more `Stack`s, to represent a single logical instance of your application. As a final note: `Stack`s are not a unit of reuse. They describe physical diff --git a/packages/aws-cdk-lib/README.md b/packages/aws-cdk-lib/README.md index 5d225ce542aa5..40fc7c0d880af 100644 --- a/packages/aws-cdk-lib/README.md +++ b/packages/aws-cdk-lib/README.md @@ -81,7 +81,7 @@ logical application. You can then treat that new unit the same way you used to be able to treat a single stack: by instantiating it multiple times for different instances of your application. -You can define a custom subclass of `Construct`, holding one or more +You can define a custom subclass of `Stage`, holding one or more `Stack`s, to represent a single logical instance of your application. As a final note: `Stack`s are not a unit of reuse. They describe physical From d7aceec9fe2cad0f13f012000a60c06c06e0705c Mon Sep 17 00:00:00 2001 From: Mattia <5013654+mattiamatrix@users.noreply.github.com> Date: Fri, 22 Oct 2021 06:49:50 +0100 Subject: [PATCH 13/87] chore(aws-kinesisanalytics-flink): add support to Flink 1.13 (#17019) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support to Flink 1.13 in construct `@aws-cdk/aws-kinesisanalytics-flink ยป Application` This fixes #16985 ---- *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-kinesisanalytics-flink/README.md | 2 +- packages/@aws-cdk/aws-kinesisanalytics-flink/lib/types.ts | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/aws-kinesisanalytics-flink/README.md b/packages/@aws-cdk/aws-kinesisanalytics-flink/README.md index 5322ff28027f7..830b59a2c7053 100644 --- a/packages/@aws-cdk/aws-kinesisanalytics-flink/README.md +++ b/packages/@aws-cdk/aws-kinesisanalytics-flink/README.md @@ -59,7 +59,7 @@ import * as logs from '@aws-cdk/aws-logs'; const flinkApp = new flink.Application(this, 'Application', { code: flink.ApplicationCode.fromBucket(bucket, 'my-app.jar'), - runtime: file.Runtime.FLINK_1_11, + runtime: file.Runtime.FLINK_1_13, checkpointingEnabled: true, // default is true checkpointInterval: cdk.Duration.seconds(30), // default is 1 minute minPauseBetweenCheckpoints: cdk.Duration.seconds(10), // default is 5 seconds diff --git a/packages/@aws-cdk/aws-kinesisanalytics-flink/lib/types.ts b/packages/@aws-cdk/aws-kinesisanalytics-flink/lib/types.ts index b92d55cb48518..02e56eee10966 100644 --- a/packages/@aws-cdk/aws-kinesisanalytics-flink/lib/types.ts +++ b/packages/@aws-cdk/aws-kinesisanalytics-flink/lib/types.ts @@ -37,7 +37,7 @@ export enum MetricsLevel { * configuration. */ export interface PropertyGroups { - readonly [propertyId: string]: {[mapKey: string]: string}; + readonly [propertyId: string]: { [mapKey: string]: string }; } /** @@ -53,6 +53,9 @@ export class Runtime { /** Flink Version 1.11 */ public static readonly FLINK_1_11 = Runtime.of('FLINK-1_11'); + /** Flink Version 1.13 */ + public static readonly FLINK_1_13 = Runtime.of('FLINK-1_13'); + /** Create a new Runtime with with an arbitrary Flink version string */ public static of(value: string) { return new Runtime(value); From 0520ca2a7ac695115df7cb43e1c0aececd6802ed Mon Sep 17 00:00:00 2001 From: Almas Sapargali Date: Fri, 22 Oct 2021 12:41:57 +0600 Subject: [PATCH 14/87] docs(amplify): fix files example in BuildSpec.fromObjectToYaml (#16701) passing `files: '**/*'` to artifacts doesn't work. It needs to be an array. ---- *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-amplify/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-amplify/README.md b/packages/@aws-cdk/aws-amplify/README.md index a706cb73bb39b..472846ea276b6 100644 --- a/packages/@aws-cdk/aws-amplify/README.md +++ b/packages/@aws-cdk/aws-amplify/README.md @@ -55,7 +55,8 @@ const amplifyApp = new amplify.App(this, 'MyApp', { }, artifacts: { baseDirectory: 'public', - files: '**/*' + files: + - '**/*' } } }) From a0d4ee75ff6cdd0f1e4dba1273b9ff754da777db Mon Sep 17 00:00:00 2001 From: Calvin Combs <66279577+comcalvi@users.noreply.github.com> Date: Fri, 22 Oct 2021 00:39:25 -0700 Subject: [PATCH 15/87] chore(cli): stop hard-coding partition to 'aws' in hotswapping (#17085) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/aws-cdk/lib/api/hotswap-deployments.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/aws-cdk/lib/api/hotswap-deployments.ts b/packages/aws-cdk/lib/api/hotswap-deployments.ts index 138adf904c992..19b8405a7de19 100644 --- a/packages/aws-cdk/lib/api/hotswap-deployments.ts +++ b/packages/aws-cdk/lib/api/hotswap-deployments.ts @@ -35,8 +35,7 @@ export async function tryHotswapDeployment( parameters: assetParams, account: resolvedEnv.account, region: resolvedEnv.region, - // ToDo make this better: - partition: 'aws', + partition: (await sdk.currentAccount()).partition, // ToDo make this better: urlSuffix: 'amazonaws.com', listStackResources, From c74b0127af95f8e86b95a0be2f2c6cb30fab1103 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Fri, 22 Oct 2021 11:56:08 +0200 Subject: [PATCH 16/87] fix(core): `DefaultSynthesizer` deployments are never skipped (#17099) The `DefaultSynthesizer` always adds an SSM parameter with the bootstrap stack version, so that it can check that the bootstrap stack has a recent enough version. Unfortunately, the CDK CLI will refuse to short-circuit any deployment that uses SSM parameters, because it can't tell if the parameter has changed, and so it has to pessimize. Adding a magic marker to the description of the parameter will now exempt it from the check. Fixes #16959. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../stack-synthesizers/default-synthesizer.ts | 2 +- .../new-style-synthesis.test.ts | 1 + packages/@aws-cdk/cx-api/lib/cxapi.ts | 11 +++++++- .../test/blueprint/stack-deployment.test.ts | 4 +-- .../integ.newpipeline-with-vpc.expected.json | 2 +- .../test/integ.newpipeline.expected.json | 2 +- .../integ.pipeline-security.expected.json | 2 +- ...ne-with-assets-single-upload.expected.json | 2 +- .../integ.pipeline-with-assets.expected.json | 2 +- .../test/integ.pipeline.expected.json | 2 +- packages/aws-cdk/lib/api/deploy-stack.ts | 10 ++++--- .../aws-cdk/lib/api/util/cloudformation.ts | 13 ++++++--- .../aws-cdk/test/util/cloudformation.test.ts | 27 +++++++++++++++++-- 13 files changed, 61 insertions(+), 19 deletions(-) diff --git a/packages/@aws-cdk/core/lib/stack-synthesizers/default-synthesizer.ts b/packages/@aws-cdk/core/lib/stack-synthesizers/default-synthesizer.ts index 5c4072c3efc5c..aae69e36ef24e 100644 --- a/packages/@aws-cdk/core/lib/stack-synthesizers/default-synthesizer.ts +++ b/packages/@aws-cdk/core/lib/stack-synthesizers/default-synthesizer.ts @@ -600,7 +600,7 @@ function addBootstrapVersionRule(stack: Stack, requiredVersion: number, bootstra const param = new CfnParameter(stack, 'BootstrapVersion', { type: 'AWS::SSM::Parameter::Value', - description: 'Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store.', + description: `Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. ${cxapi.SSMPARAM_NO_INVALIDATE}`, default: bootstrapStackVersionSsmParameter, }); diff --git a/packages/@aws-cdk/core/test/stack-synthesis/new-style-synthesis.test.ts b/packages/@aws-cdk/core/test/stack-synthesis/new-style-synthesis.test.ts index 1528e91205f80..3a8d8c1e60b31 100644 --- a/packages/@aws-cdk/core/test/stack-synthesis/new-style-synthesis.test.ts +++ b/packages/@aws-cdk/core/test/stack-synthesis/new-style-synthesis.test.ts @@ -70,6 +70,7 @@ describe('new style synthesis', () => { const template = app.synth().getStackByName('Stack').template; expect(template?.Parameters?.BootstrapVersion?.Type).toEqual('AWS::SSM::Parameter::Value'); expect(template?.Parameters?.BootstrapVersion?.Default).toEqual('/cdk-bootstrap/hnb659fds/version'); + expect(template?.Parameters?.BootstrapVersion?.Description).toContain(cxapi.SSMPARAM_NO_INVALIDATE); const assertions = template?.Rules?.CheckBootstrapVersion?.Assertions ?? []; expect(assertions.length).toEqual(1); diff --git a/packages/@aws-cdk/cx-api/lib/cxapi.ts b/packages/@aws-cdk/cx-api/lib/cxapi.ts index 33d83e74ea45c..9b179e9a71b5f 100644 --- a/packages/@aws-cdk/cx-api/lib/cxapi.ts +++ b/packages/@aws-cdk/cx-api/lib/cxapi.ts @@ -31,4 +31,13 @@ export const CLI_VERSION_ENV = 'CDK_CLI_VERSION'; /** * If a context value is an object with this key, it indicates an error */ -export const PROVIDER_ERROR_KEY = '$providerError'; \ No newline at end of file +export const PROVIDER_ERROR_KEY = '$providerError'; + + +/** + * This SSM parameter does not invalidate the template + * + * If this string occurs in the description of an SSM parameter, the CLI + * will not assume that the stack must always be redeployed. + */ +export const SSMPARAM_NO_INVALIDATE = '[cdk:skip]'; \ No newline at end of file diff --git a/packages/@aws-cdk/pipelines/test/blueprint/stack-deployment.test.ts b/packages/@aws-cdk/pipelines/test/blueprint/stack-deployment.test.ts index ee9d5b29240ce..68ca1f20a20b6 100644 --- a/packages/@aws-cdk/pipelines/test/blueprint/stack-deployment.test.ts +++ b/packages/@aws-cdk/pipelines/test/blueprint/stack-deployment.test.ts @@ -31,7 +31,7 @@ describe('templateUrl', () => { const sd = StageDeployment.fromStage(stage); // THEN - expect(sd.stacks[0].templateUrl).toBe('https://cdk-hnb659fds-assets-111-us-east-1.s3.us-east-1.amazonaws.com/4ef627170a212f66f5d1d9240d967ef306f4820ff9cb05b3a7ec703df6af6c3e.json'); + expect(sd.stacks[0].templateUrl).toBe('https://cdk-hnb659fds-assets-111-us-east-1.s3.us-east-1.amazonaws.com/93ae4de94f81d0905c37db64b7304f5d65233ca4d9581d3a32215743c9bb92dd.json'); }); test('without region', () => { @@ -43,7 +43,7 @@ describe('templateUrl', () => { const sd = StageDeployment.fromStage(stage); // THEN - expect(sd.stacks[0].templateUrl).toBe('https://cdk-hnb659fds-assets-111-.s3.amazonaws.com/$%7BAWS::Region%7D/4ef627170a212f66f5d1d9240d967ef306f4820ff9cb05b3a7ec703df6af6c3e.json'); + expect(sd.stacks[0].templateUrl).toBe('https://cdk-hnb659fds-assets-111-.s3.amazonaws.com/$%7BAWS::Region%7D/93ae4de94f81d0905c37db64b7304f5d65233ca4d9581d3a32215743c9bb92dd.json'); }); }); diff --git a/packages/@aws-cdk/pipelines/test/integ.newpipeline-with-vpc.expected.json b/packages/@aws-cdk/pipelines/test/integ.newpipeline-with-vpc.expected.json index e0075942e6069..80a17d7243cb1 100644 --- a/packages/@aws-cdk/pipelines/test/integ.newpipeline-with-vpc.expected.json +++ b/packages/@aws-cdk/pipelines/test/integ.newpipeline-with-vpc.expected.json @@ -2368,7 +2368,7 @@ "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." + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" } }, "Rules": { diff --git a/packages/@aws-cdk/pipelines/test/integ.newpipeline.expected.json b/packages/@aws-cdk/pipelines/test/integ.newpipeline.expected.json index 07e65b9bd643f..935ad4ce5136a 100644 --- a/packages/@aws-cdk/pipelines/test/integ.newpipeline.expected.json +++ b/packages/@aws-cdk/pipelines/test/integ.newpipeline.expected.json @@ -2303,7 +2303,7 @@ "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." + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" } }, "Rules": { diff --git a/packages/@aws-cdk/pipelines/test/integ.pipeline-security.expected.json b/packages/@aws-cdk/pipelines/test/integ.pipeline-security.expected.json index b72a78754a1d2..3d808a0f31767 100644 --- a/packages/@aws-cdk/pipelines/test/integ.pipeline-security.expected.json +++ b/packages/@aws-cdk/pipelines/test/integ.pipeline-security.expected.json @@ -2366,7 +2366,7 @@ "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." + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" } }, "Rules": { diff --git a/packages/@aws-cdk/pipelines/test/integ.pipeline-with-assets-single-upload.expected.json b/packages/@aws-cdk/pipelines/test/integ.pipeline-with-assets-single-upload.expected.json index 8250f113b53e3..85f20ecf8995f 100644 --- a/packages/@aws-cdk/pipelines/test/integ.pipeline-with-assets-single-upload.expected.json +++ b/packages/@aws-cdk/pipelines/test/integ.pipeline-with-assets-single-upload.expected.json @@ -1519,7 +1519,7 @@ "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." + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" } }, "Rules": { diff --git a/packages/@aws-cdk/pipelines/test/integ.pipeline-with-assets.expected.json b/packages/@aws-cdk/pipelines/test/integ.pipeline-with-assets.expected.json index c2e4cddc58aef..e236dbdb569ac 100644 --- a/packages/@aws-cdk/pipelines/test/integ.pipeline-with-assets.expected.json +++ b/packages/@aws-cdk/pipelines/test/integ.pipeline-with-assets.expected.json @@ -1576,7 +1576,7 @@ "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." + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" } }, "Rules": { diff --git a/packages/@aws-cdk/pipelines/test/integ.pipeline.expected.json b/packages/@aws-cdk/pipelines/test/integ.pipeline.expected.json index 32a0a50bd90d5..0f158a1dffdf5 100644 --- a/packages/@aws-cdk/pipelines/test/integ.pipeline.expected.json +++ b/packages/@aws-cdk/pipelines/test/integ.pipeline.expected.json @@ -1299,7 +1299,7 @@ "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." + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" } }, "Rules": { diff --git a/packages/aws-cdk/lib/api/deploy-stack.ts b/packages/aws-cdk/lib/api/deploy-stack.ts index f58f441560e3e..6b5afe9673ead 100644 --- a/packages/aws-cdk/lib/api/deploy-stack.ts +++ b/packages/aws-cdk/lib/api/deploy-stack.ts @@ -14,7 +14,7 @@ import { CfnEvaluationException } from './hotswap/evaluate-cloudformation-templa import { ToolkitInfo } from './toolkit-info'; import { changeSetHasNoChanges, CloudFormationStack, TemplateParameters, waitForChangeSet, - waitForStackDeploy, waitForStackDelete, ParameterValues, + waitForStackDeploy, waitForStackDelete, ParameterValues, ParameterChanges, } from './util/cloudformation'; import { StackActivityMonitor, StackActivityProgress } from './util/cloudformation/stack-activity-monitor'; @@ -466,7 +466,7 @@ export async function destroyStack(options: DestroyStackOptions) { async function canSkipDeploy( deployStackOptions: DeployStackOptions, cloudFormationStack: CloudFormationStack, - parameterChanges: boolean): Promise { + parameterChanges: ParameterChanges): Promise { const deployName = deployStackOptions.deployName || deployStackOptions.stack.stackName; debug(`${deployName}: checking if we can skip deploy`); @@ -509,7 +509,11 @@ async function canSkipDeploy( // Parameters have changed if (parameterChanges) { - debug(`${deployName}: parameters have changed`); + if (parameterChanges === 'ssm') { + debug(`${deployName}: some parameters come from SSM so we have to assume they may have changed`); + } else { + debug(`${deployName}: parameters have changed`); + } return false; } diff --git a/packages/aws-cdk/lib/api/util/cloudformation.ts b/packages/aws-cdk/lib/api/util/cloudformation.ts index 19db988fdc15e..b3b5660d727c4 100644 --- a/packages/aws-cdk/lib/api/util/cloudformation.ts +++ b/packages/aws-cdk/lib/api/util/cloudformation.ts @@ -1,3 +1,4 @@ +import { SSMPARAM_NO_INVALIDATE } from '@aws-cdk/cx-api'; import { CloudFormation } from 'aws-sdk'; import { debug } from '../../logging'; import { deserializeStructure } from '../../serialize'; @@ -11,6 +12,7 @@ export type Template = { interface TemplateParameter { Type: string; Default?: any; + Description?: string; [key: string]: any; } @@ -424,11 +426,12 @@ export class ParameterValues { /** * Whether this set of parameter updates will change the actual stack values */ - public hasChanges(currentValues: Record): boolean { + public hasChanges(currentValues: Record): ParameterChanges { // If any of the parameters are SSM parameters, deploying must always happen - // because we can't predict what the values will be. - if (Object.values(this.formalParams).some(p => p.Type.startsWith('AWS::SSM::Parameter::'))) { - return true; + // because we can't predict what the values will be. We will allow some + // parameters to opt out of this check by having a magic string in their description. + if (Object.values(this.formalParams).some(p => p.Type.startsWith('AWS::SSM::Parameter::') && !p.Description?.includes(SSMPARAM_NO_INVALIDATE))) { + return 'ssm'; } // Otherwise we're dirty if: @@ -445,3 +448,5 @@ export class ParameterValues { return false; } } + +export type ParameterChanges = boolean | 'ssm'; \ No newline at end of file diff --git a/packages/aws-cdk/test/util/cloudformation.test.ts b/packages/aws-cdk/test/util/cloudformation.test.ts index c8c034ba23f67..40a748d50ea37 100644 --- a/packages/aws-cdk/test/util/cloudformation.test.ts +++ b/packages/aws-cdk/test/util/cloudformation.test.ts @@ -1,3 +1,4 @@ +import { SSMPARAM_NO_INVALIDATE } from '@aws-cdk/cx-api'; import { CloudFormationStack, TemplateParameters } from '../../lib/api/util/cloudformation'; import { MockedObject, MockSdkProvider, SyncHandlerSubsetOf } from './mock-sdk'; @@ -81,10 +82,32 @@ test('if a parameter is retrieved from SSM, the parameters always count as chang const oldValues = { Foo: '/Some/Key' }; // If we don't pass a new value - expect(params.updateExisting({}, oldValues).hasChanges(oldValues)).toEqual(true); + expect(params.updateExisting({}, oldValues).hasChanges(oldValues)).toEqual('ssm'); // If we do pass a new value but it's the same as the old one - expect(params.updateExisting({ Foo: '/Some/Key' }, oldValues).hasChanges(oldValues)).toEqual(true); + expect(params.updateExisting({ Foo: '/Some/Key' }, oldValues).hasChanges(oldValues)).toEqual('ssm'); +}); + +test('if a parameter is retrieved from SSM, the parameters doesnt count as changed if it has the magic marker', () => { + const params = TemplateParameters.fromTemplate({ + Parameters: { + Foo: { + Type: 'AWS::SSM::Parameter::Name', + Default: '/Some/Key', + Description: `blabla ${SSMPARAM_NO_INVALIDATE}`, + }, + }, + }); + const oldValues = { Foo: '/Some/Key' }; + + // If we don't pass a new value + expect(params.updateExisting({}, oldValues).hasChanges(oldValues)).toEqual(false); + + // If we do pass a new value but it's the same as the old one + expect(params.updateExisting({ Foo: '/Some/Key' }, oldValues).hasChanges(oldValues)).toEqual(false); + + // If we do pass a new value and it's different + expect(params.updateExisting({ Foo: '/OTHER/Key' }, oldValues).hasChanges(oldValues)).toEqual(true); }); test('empty string is a valid update value', () => { From 260df31c1117f60a7a92f7845e4e15386225b5c6 Mon Sep 17 00:00:00 2001 From: Nick Lynch Date: Fri, 22 Oct 2021 15:58:15 +0100 Subject: [PATCH 17/87] chore: include RELEASE_NOTES in packed distribution (#17118) We now create and generate a `RELEASE_NOTES.md` file as part of our build, with the intent to use it for our GitHub release publishing. See (#16942) and https://github.com/cdklabs/aws-delivlib/pull/1044. What I missed is that after the build, we pack, and then only include what ends up in `./dist` in the final build artifact that goes to publishing. This fix includes the release notes in the dist folder so it will be picked up and used by the release process. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- pack.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pack.sh b/pack.sh index d270fb28271c5..86c29bacbd48c 100755 --- a/pack.sh +++ b/pack.sh @@ -92,8 +92,9 @@ cat > ${distdir}/build.json < Date: Fri, 22 Oct 2021 19:18:45 +0200 Subject: [PATCH 18/87] chore(codebuild): make examples compile (#17123) ---- *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-codebuild/README.md | 81 ++++++++++++------- .../lib/untrusted-code-boundary-policy.ts | 3 +- 2 files changed, 52 insertions(+), 32 deletions(-) diff --git a/packages/@aws-cdk/aws-codebuild/README.md b/packages/@aws-cdk/aws-codebuild/README.md index d4b31c1bf91db..ff73599bca8e4 100644 --- a/packages/@aws-cdk/aws-codebuild/README.md +++ b/packages/@aws-cdk/aws-codebuild/README.md @@ -30,7 +30,7 @@ $ npm i @aws-cdk/aws-codebuild Import it into your code: -```ts +```ts nofixture import * as codebuild from '@aws-cdk/aws-codebuild'; ``` @@ -56,7 +56,6 @@ CodeBuild!`: Use an AWS CodeCommit repository as the source of this build: ```ts -import * as codebuild from '@aws-cdk/aws-codebuild'; import * as codecommit from '@aws-cdk/aws-codecommit'; const repository = new codecommit.Repository(this, 'MyRepo', { repositoryName: 'foo' }); @@ -70,10 +69,8 @@ new codebuild.Project(this, 'MyFirstCodeCommitProject', { Create a CodeBuild project with an S3 bucket as the source: ```ts -import * as codebuild from '@aws-cdk/aws-codebuild'; -import * as s3 from '@aws-cdk/aws-s3'; - const bucket = new s3.Bucket(this, 'MyBucket'); + new codebuild.Project(this, 'MyProject', { source: codebuild.Source.s3({ bucket: bucket, @@ -140,7 +137,9 @@ const gitHubSource = codebuild.Source.gitHub({ CodeBuild Projects can produce Artifacts and upload them to S3. For example: ```ts -const project = codebuild.Project(stack, 'MyProject', { +declare const bucket: s3.Bucket; + +const project = new codebuild.Project(this, 'MyProject', { buildSpec: codebuild.BuildSpec.fromObject({ version: '0.2', }), @@ -193,7 +192,7 @@ new codebuild.Project(this, 'Project', { owner: 'awslabs', repo: 'aws-cdk', }), - cache: codebuild.Cache.bucket(new Bucket(this, 'Bucket')) + cache: codebuild.Cache.bucket(new s3.Bucket(this, 'Bucket')) }); ``` @@ -214,7 +213,7 @@ new codebuild.Project(this, 'Project', { }), // Enable Docker AND custom caching - cache: codebuild.Cache.local(LocalCacheMode.DOCKER_LAYER, LocalCacheMode.CUSTOM) + cache: codebuild.Cache.local(codebuild.LocalCacheMode.DOCKER_LAYER, codebuild.LocalCacheMode.CUSTOM) }); ``` @@ -260,6 +259,8 @@ Note that the `WindowsBuildImage` version of the static methods accepts an optio which can be either `WindowsImageType.STANDARD`, the default, or `WindowsImageType.SERVER_2019`: ```ts +declare const ecrRepository: ecr.Repository; + new codebuild.Project(this, 'Project', { environment: { buildImage: codebuild.WindowsBuildImage.fromEcrRepository(ecrRepository, 'v1.0', codebuild.WindowsImageType.SERVER_2019), @@ -269,7 +270,7 @@ new codebuild.Project(this, 'Project', { objectKey: 'path/to/cert.pem', }, }, - ... + // ... }) ``` @@ -296,7 +297,7 @@ new codebuild.Project(this, 'Project', { environment: { buildImage: codebuild.LinuxGpuBuildImage.DLC_TENSORFLOW_2_1_0_INFERENCE, }, - ... + // ... }) ``` @@ -315,7 +316,7 @@ new codebuild.Project(this, 'Project', { buildImage: codebuild.LinuxGpuBuildImage.awsDeepLearningContainersImage( 'tensorflow-inference', '2.1.0-gpu-py36-cu101-ubuntu18.04', '123456789012'), }, - ... + // ... }) ``` @@ -331,10 +332,9 @@ By default, logs will go to cloudwatch. new codebuild.Project(this, 'Project', { logging: { cloudWatch: { - logGroup: new cloudwatch.LogGroup(this, `MyLogGroup`), + logGroup: new logs.LogGroup(this, `MyLogGroup`), } }, - ... }) ``` @@ -347,7 +347,6 @@ new codebuild.Project(this, 'Project', { bucket: new s3.Bucket(this, `LogBucket`) } }, - ... }) ``` @@ -358,7 +357,7 @@ like GitHub: ```ts new codebuild.GitHubSourceCredentials(this, 'CodeBuildGitHubCreds', { - accessToken: cdk.SecretValue.secretsManager('my-token'), + accessToken: SecretValue.secretsManager('my-token'), }); // GitHub Enterprise is almost the same, // except the class is called GitHubEnterpriseSourceCredentials @@ -368,8 +367,8 @@ and BitBucket: ```ts new codebuild.BitBucketSourceCredentials(this, 'CodeBuildBitBucketCreds', { - username: cdk.SecretValue.secretsManager('my-bitbucket-creds', { jsonField: 'username' }), - password: cdk.SecretValue.secretsManager('my-bitbucket-creds', { jsonField: 'password' }), + username: SecretValue.secretsManager('my-bitbucket-creds', { jsonField: 'username' }), + password: SecretValue.secretsManager('my-bitbucket-creds', { jsonField: 'password' }), }); ``` @@ -409,8 +408,10 @@ if you'd rather not have those permissions added, you can opt out of it when creating the project: ```ts +declare const source: codebuild.Source; + const project = new codebuild.Project(this, 'Project', { - // ... + source, grantReportGroupPermissions: false, }); ``` @@ -419,10 +420,13 @@ Alternatively, you can specify an ARN of an existing resource group, instead of a simple name, in your buildspec: ```ts +declare const source: codebuild.Source; + // create a new ReportGroup const reportGroup = new codebuild.ReportGroup(this, 'ReportGroup'); const project = new codebuild.Project(this, 'Project', { + source, buildSpec: codebuild.BuildSpec.fromObject({ // ... reports: { @@ -438,6 +442,9 @@ const project = new codebuild.Project(this, 'Project', { If you do that, you need to grant the project's role permissions to write reports to that report group: ```ts +declare const project: codebuild.Project; +declare const reportGroup: codebuild.ReportGroup; + reportGroup.grantWrite(project); ``` @@ -456,8 +463,12 @@ project as a AWS CloudWatch event rule target: ```ts // start build when a commit is pushed +import * as codecommit from '@aws-cdk/aws-codecommit'; import * as targets from '@aws-cdk/aws-events-targets'; +declare const codeCommitRepository: codecommit.Repository; +declare const project: codebuild.Project; + codeCommitRepository.onCommit('OnCommit', { target: new targets.CodeBuildProject(project), }); @@ -469,6 +480,10 @@ To define Amazon CloudWatch event rules for build projects, use one of the `onXx methods: ```ts +import * as targets from '@aws-cdk/aws-events-targets'; +declare const fn: lambda.Function; +declare const project: codebuild.Project; + const rule = project.onStateChange('BuildStateChange', { target: new targets.LambdaFunction(fn) }); @@ -480,7 +495,11 @@ To define CodeStar Notification rules for Projects, use one of the `notifyOnXxx( They are very similar to `onXxx()` methods for CloudWatch events: ```ts -const target = new chatbot.SlackChannelConfiguration(stack, 'MySlackChannel', { +import * as chatbot from '@aws-cdk/aws-chatbot'; + +declare const project: codebuild.Project; + +const target = new chatbot.SlackChannelConfiguration(this, 'MySlackChannel', { slackChannelConfigurationName: 'YOUR_CHANNEL_NAME', slackWorkspaceId: 'YOUR_SLACK_WORKSPACE_ID', slackChannelId: 'YOUR_SLACK_CHANNEL_ID', @@ -495,6 +514,10 @@ CodeBuild Projects can get their sources from multiple places, and produce multiple outputs. For example: ```ts +import * as codecommit from '@aws-cdk/aws-codecommit'; +declare const repo: codecommit.Repository; +declare const bucket: s3.Bucket; + const project = new codebuild.Project(this, 'MyProject', { secondarySources: [ codebuild.Source.codeCommit({ @@ -586,6 +609,8 @@ to access the resources that it needs by using the For example: ```ts +declare const loadBalancer: elbv2.ApplicationLoadBalancer; + const vpc = new ec2.Vpc(this, 'MyVPC'); const project = new codebuild.Project(this, 'MyProject', { vpc: vpc, @@ -608,7 +633,7 @@ The only supported file system type is `EFS`. For example: ```ts -new codebuild.Project(stack, 'MyProject', { +new codebuild.Project(this, 'MyProject', { buildSpec: codebuild.BuildSpec.fromObject({ version: '0.2', }), @@ -635,9 +660,9 @@ It returns an object containing the batch service role that was created, or `undefined` if batch builds could not be enabled, for example if the project was imported. ```ts -import * as codebuild from '@aws-cdk/aws-codebuild'; +declare const source: codebuild.Source; -const project = new codebuild.Project(this, 'MyProject', { ... }); +const project = new codebuild.Project(this, 'MyProject', { source, }); if (project.enableBatchBuilds()) { console.log('Batch builds were enabled'); @@ -652,9 +677,7 @@ The default is 60 minutes. An example of overriding the default follows. ```ts -import * as codebuild from '@aws-cdk/aws-codebuild'; - -new codebuild.Project(stack, 'MyProject', { +new codebuild.Project(this, 'MyProject', { timeout: Duration.minutes(90) }); ``` @@ -665,9 +688,7 @@ As an example, to allow your Project to queue for up to thirty (30) minutes befo use the following code. ```ts -import * as codebuild from '@aws-cdk/aws-codebuild'; - -new codebuild.Project(stack, 'MyProject', { +new codebuild.Project(this, 'MyProject', { queuedTimeout: Duration.minutes(30) }); ``` @@ -679,9 +700,7 @@ It is possible to limit the maximum concurrent builds to value between 1 and the By default there is no explicit limit. ```ts -import * as codebuild from '@aws-cdk/aws-codebuild'; - -new codebuild.Project(stack, 'MyProject', { +new codebuild.Project(this, 'MyProject', { concurrentBuildLimit: 1 }); ``` diff --git a/packages/@aws-cdk/aws-codebuild/lib/untrusted-code-boundary-policy.ts b/packages/@aws-cdk/aws-codebuild/lib/untrusted-code-boundary-policy.ts index 229cb547e7c1f..1a94c521fc08a 100644 --- a/packages/@aws-cdk/aws-codebuild/lib/untrusted-code-boundary-policy.ts +++ b/packages/@aws-cdk/aws-codebuild/lib/untrusted-code-boundary-policy.ts @@ -39,7 +39,8 @@ export interface UntrustedCodeBoundaryPolicyProps { * * @example * - * iam.PermissionsBoundary.of(project).apply(new UntrustedCodeBoundaryPolicy(this, 'Boundary')); + * declare const project: codebuild.Project; + * iam.PermissionsBoundary.of(project).apply(new codebuild.UntrustedCodeBoundaryPolicy(this, 'Boundary')); */ export class UntrustedCodeBoundaryPolicy extends iam.ManagedPolicy { constructor(scope: Construct, id: string, props: UntrustedCodeBoundaryPolicyProps = {}) { From 06838e66db0c9a48e2aa7da1e7707fda335bb62c Mon Sep 17 00:00:00 2001 From: Tatsuya Yamamoto Date: Sat, 23 Oct 2021 03:41:59 +0900 Subject: [PATCH 19/87] feat(iot): create new aws-iot-actions module (#17112) I'm trying to implement aws-iot L2 Constructs. This PR is the next step of #16681 refar: - https://github.com/aws/aws-cdk/pull/16681#discussion_r733912215 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../@aws-cdk/aws-iot-actions/.eslintrc.js | 3 + packages/@aws-cdk/aws-iot-actions/.gitignore | 19 ++ packages/@aws-cdk/aws-iot-actions/.npmignore | 28 +++ packages/@aws-cdk/aws-iot-actions/LICENSE | 201 ++++++++++++++++++ packages/@aws-cdk/aws-iot-actions/NOTICE | 2 + packages/@aws-cdk/aws-iot-actions/README.md | 20 ++ .../@aws-cdk/aws-iot-actions/jest.config.js | 2 + .../@aws-cdk/aws-iot-actions/lib/index.ts | 2 + .../@aws-cdk/aws-iot-actions/package.json | 97 +++++++++ packages/aws-cdk-lib/package.json | 1 + packages/decdk/package.json | 1 + packages/monocdk/package.json | 1 + 12 files changed, 377 insertions(+) create mode 100644 packages/@aws-cdk/aws-iot-actions/.eslintrc.js create mode 100644 packages/@aws-cdk/aws-iot-actions/.gitignore create mode 100644 packages/@aws-cdk/aws-iot-actions/.npmignore create mode 100644 packages/@aws-cdk/aws-iot-actions/LICENSE create mode 100644 packages/@aws-cdk/aws-iot-actions/NOTICE create mode 100644 packages/@aws-cdk/aws-iot-actions/README.md create mode 100644 packages/@aws-cdk/aws-iot-actions/jest.config.js create mode 100644 packages/@aws-cdk/aws-iot-actions/lib/index.ts create mode 100644 packages/@aws-cdk/aws-iot-actions/package.json diff --git a/packages/@aws-cdk/aws-iot-actions/.eslintrc.js b/packages/@aws-cdk/aws-iot-actions/.eslintrc.js new file mode 100644 index 0000000000000..2658ee8727166 --- /dev/null +++ b/packages/@aws-cdk/aws-iot-actions/.eslintrc.js @@ -0,0 +1,3 @@ +const baseConfig = require('@aws-cdk/cdk-build-tools/config/eslintrc'); +baseConfig.parserOptions.project = __dirname + '/tsconfig.json'; +module.exports = baseConfig; diff --git a/packages/@aws-cdk/aws-iot-actions/.gitignore b/packages/@aws-cdk/aws-iot-actions/.gitignore new file mode 100644 index 0000000000000..d8a8561d50885 --- /dev/null +++ b/packages/@aws-cdk/aws-iot-actions/.gitignore @@ -0,0 +1,19 @@ +*.js +*.js.map +*.d.ts +tsconfig.json +node_modules +*.generated.ts +dist +.jsii + +.LAST_BUILD +.nyc_output +coverage +nyc.config.js +.LAST_PACKAGE +*.snk +!.eslintrc.js +!jest.config.js + +junit.xml \ No newline at end of file diff --git a/packages/@aws-cdk/aws-iot-actions/.npmignore b/packages/@aws-cdk/aws-iot-actions/.npmignore new file mode 100644 index 0000000000000..aaabf1df59065 --- /dev/null +++ b/packages/@aws-cdk/aws-iot-actions/.npmignore @@ -0,0 +1,28 @@ +# Don't include original .ts files when doing `npm pack` +*.ts +!*.d.ts +coverage +.nyc_output +*.tgz + +dist +.LAST_PACKAGE +.LAST_BUILD +!*.js + +# Include .jsii +!.jsii + +*.snk + +*.tsbuildinfo + +tsconfig.json +.eslintrc.js +jest.config.js + +# exclude cdk artifacts +**/cdk.out +junit.xml +test/ +!*.lit.ts \ No newline at end of file diff --git a/packages/@aws-cdk/aws-iot-actions/LICENSE b/packages/@aws-cdk/aws-iot-actions/LICENSE new file mode 100644 index 0000000000000..28e4bdcec77ec --- /dev/null +++ b/packages/@aws-cdk/aws-iot-actions/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2018-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/@aws-cdk/aws-iot-actions/NOTICE b/packages/@aws-cdk/aws-iot-actions/NOTICE new file mode 100644 index 0000000000000..5fc3826926b5b --- /dev/null +++ b/packages/@aws-cdk/aws-iot-actions/NOTICE @@ -0,0 +1,2 @@ +AWS Cloud Development Kit (AWS CDK) +Copyright 2018-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. diff --git a/packages/@aws-cdk/aws-iot-actions/README.md b/packages/@aws-cdk/aws-iot-actions/README.md new file mode 100644 index 0000000000000..1c098d25eb3de --- /dev/null +++ b/packages/@aws-cdk/aws-iot-actions/README.md @@ -0,0 +1,20 @@ +# Actions for AWS IoT Rule + + +--- + +![cdk-constructs: Experimental](https://img.shields.io/badge/cdk--constructs-experimental-important.svg?style=for-the-badge) + +> The APIs of higher level constructs in this module are experimental and under active development. +> They are subject to non-backward compatible changes or removal in any future version. These are +> not subject to the [Semantic Versioning](https://semver.org/) model and breaking changes will be +> announced in the release notes. This means that while you may use them, you may need to update +> your source code when upgrading to a newer version of this package. + +--- + + + +This library contains integration classes to send data to any number of +supported AWS Services. Instances of these classes should be passed to +`TopicRule` defined in `@aws-cdk/aws-iot`. diff --git a/packages/@aws-cdk/aws-iot-actions/jest.config.js b/packages/@aws-cdk/aws-iot-actions/jest.config.js new file mode 100644 index 0000000000000..3a2fd93a1228a --- /dev/null +++ b/packages/@aws-cdk/aws-iot-actions/jest.config.js @@ -0,0 +1,2 @@ +const baseConfig = require('@aws-cdk/cdk-build-tools/config/jest.config'); +module.exports = baseConfig; diff --git a/packages/@aws-cdk/aws-iot-actions/lib/index.ts b/packages/@aws-cdk/aws-iot-actions/lib/index.ts new file mode 100644 index 0000000000000..3e4b0ef0a73d4 --- /dev/null +++ b/packages/@aws-cdk/aws-iot-actions/lib/index.ts @@ -0,0 +1,2 @@ +// this is placeholder for monocdk +export const dummy = true; diff --git a/packages/@aws-cdk/aws-iot-actions/package.json b/packages/@aws-cdk/aws-iot-actions/package.json new file mode 100644 index 0000000000000..76878637e0430 --- /dev/null +++ b/packages/@aws-cdk/aws-iot-actions/package.json @@ -0,0 +1,97 @@ +{ + "name": "@aws-cdk/aws-iot-actions", + "version": "0.0.0", + "description": "Receipt rule actions for AWS IoT", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "jsii": { + "outdir": "dist", + "targets": { + "java": { + "package": "software.amazon.awscdk.services.iot.actions", + "maven": { + "groupId": "software.amazon.awscdk", + "artifactId": "iot-actions" + } + }, + "dotnet": { + "namespace": "Amazon.CDK.AWS.IoT.Actions", + "packageId": "Amazon.CDK.AWS.IoT.Actions", + "iconUrl": "https://raw.githubusercontent.com/aws/aws-cdk/master/logo/default-256-dark.png" + }, + "python": { + "distName": "aws-cdk.aws-iot-actions", + "module": "aws_cdk.aws_iot_actions", + "classifiers": [ + "Framework :: AWS CDK", + "Framework :: AWS CDK :: 1" + ] + } + }, + "projectReferences": true + }, + "repository": { + "type": "git", + "url": "https://github.com/aws/aws-cdk.git", + "directory": "packages/@aws-cdk/aws-iot-actions" + }, + "scripts": { + "build": "cdk-build", + "watch": "cdk-watch", + "lint": "cdk-lint", + "test": "cdk-test", + "integ": "cdk-integ", + "pkglint": "pkglint -f", + "package": "cdk-package", + "awslint": "cdk-awslint", + "build+test+package": "yarn build+test && yarn package", + "build+test": "yarn build && yarn test", + "compat": "cdk-compat", + "rosetta:extract": "yarn --silent jsii-rosetta extract", + "build+extract": "yarn build && yarn rosetta:extract", + "build+test+extract": "yarn build+test && yarn rosetta:extract" + }, + "cdk-build": { + "env": { + "AWSLINT_BASE_CONSTRUCT": true + } + }, + "keywords": [ + "aws", + "cdk", + "constructs", + "iot", + "actions" + ], + "author": { + "name": "Amazon Web Services", + "url": "https://aws.amazon.com", + "organization": true + }, + "license": "Apache-2.0", + "devDependencies": { + "@aws-cdk/assertions": "0.0.0", + "@aws-cdk/cdk-build-tools": "0.0.0", + "@aws-cdk/cdk-integ-tools": "0.0.0", + "@aws-cdk/pkglint": "0.0.0", + "@types/jest": "^26.0.24", + "constructs": "^3.3.69", + "jest": "^26.6.3" + }, + "dependencies": { + }, + "homepage": "https://github.com/aws/aws-cdk", + "peerDependencies": { + }, + "engines": { + "node": ">= 10.13.0 <13 || >=13.7.0" + }, + "stability": "experimental", + "maturity": "experimental", + "awscdkio": { + "announce": false + }, + "publishConfig": { + "tag": "latest" + } +} diff --git a/packages/aws-cdk-lib/package.json b/packages/aws-cdk-lib/package.json index ad2aeeace6cd1..de4d8379cac35 100644 --- a/packages/aws-cdk-lib/package.json +++ b/packages/aws-cdk-lib/package.json @@ -231,6 +231,7 @@ "@aws-cdk/aws-imagebuilder": "0.0.0", "@aws-cdk/aws-inspector": "0.0.0", "@aws-cdk/aws-iot": "0.0.0", + "@aws-cdk/aws-iot-actions": "0.0.0", "@aws-cdk/aws-iot1click": "0.0.0", "@aws-cdk/aws-iotanalytics": "0.0.0", "@aws-cdk/aws-iotcoredeviceadvisor": "0.0.0", diff --git a/packages/decdk/package.json b/packages/decdk/package.json index 8a87b4a7001f8..6a0a0eb5c0baa 100644 --- a/packages/decdk/package.json +++ b/packages/decdk/package.json @@ -134,6 +134,7 @@ "@aws-cdk/aws-imagebuilder": "0.0.0", "@aws-cdk/aws-inspector": "0.0.0", "@aws-cdk/aws-iot": "0.0.0", + "@aws-cdk/aws-iot-actions": "0.0.0", "@aws-cdk/aws-iot1click": "0.0.0", "@aws-cdk/aws-iotanalytics": "0.0.0", "@aws-cdk/aws-iotcoredeviceadvisor": "0.0.0", diff --git a/packages/monocdk/package.json b/packages/monocdk/package.json index 526eb3ce967b3..7e0b967fe70ab 100644 --- a/packages/monocdk/package.json +++ b/packages/monocdk/package.json @@ -228,6 +228,7 @@ "@aws-cdk/aws-imagebuilder": "0.0.0", "@aws-cdk/aws-inspector": "0.0.0", "@aws-cdk/aws-iot": "0.0.0", + "@aws-cdk/aws-iot-actions": "0.0.0", "@aws-cdk/aws-iot1click": "0.0.0", "@aws-cdk/aws-iotanalytics": "0.0.0", "@aws-cdk/aws-iotcoredeviceadvisor": "0.0.0", From 924045daad403b7814bedc536675c37e00e2bf53 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Sat, 23 Oct 2021 16:16:26 +0200 Subject: [PATCH 20/87] chore(codebuild): add forgotten rosetta fixture (#17129) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../aws-codebuild/rosetta/default.ts-fixture | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 packages/@aws-cdk/aws-codebuild/rosetta/default.ts-fixture diff --git a/packages/@aws-cdk/aws-codebuild/rosetta/default.ts-fixture b/packages/@aws-cdk/aws-codebuild/rosetta/default.ts-fixture new file mode 100644 index 0000000000000..12926b4e95060 --- /dev/null +++ b/packages/@aws-cdk/aws-codebuild/rosetta/default.ts-fixture @@ -0,0 +1,19 @@ +// Fixture with packages imported, but nothing else +import { Construct } from 'constructs'; +import { Stack, Duration, SecretValue } from '@aws-cdk/core'; +import codebuild = require('@aws-cdk/aws-codebuild'); +import iam = require('@aws-cdk/aws-iam'); +import ec2 = require('@aws-cdk/aws-ec2'); +import lambda = require('@aws-cdk/aws-lambda'); +import * as s3 from '@aws-cdk/aws-s3'; +import * as elbv2 from '@aws-cdk/aws-elasticloadbalancingv2'; +import * as ecr from '@aws-cdk/aws-ecr'; +import * as logs from '@aws-cdk/aws-logs'; + +class Fixture extends Stack { + constructor(scope: Construct, id: string) { + super(scope, id); + + /// here + } +} From ab627c69e9edac82b1fd07d2c9ee1b05f7dc3166 Mon Sep 17 00:00:00 2001 From: Adam Ruka Date: Mon, 25 Oct 2021 02:44:42 -0700 Subject: [PATCH 21/87] fix(rds): using both Instance imports & exports for Postgres fails deployment (#17060) Our CDK code was assuming that all instance engines that support S3 imports & exports must use the same Role if both functions are enabled at the same time. However, it turns out that's true only for Oracle and SQL Server, but not for Postgres - in fact, Postgres has the exact opposite requirement, and will fail deployment if the same Role is used for both. Change our code to only use a single Role if the engine is Oracle or SQL Server. Fixes #16757 ---- *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-rds/lib/cluster.ts | 2 +- packages/@aws-cdk/aws-rds/lib/instance.ts | 13 +- packages/@aws-cdk/aws-rds/lib/private/util.ts | 4 +- .../integ.instance-s3-postgres.expected.json | 601 ++++++++++++++++++ .../test/integ.instance-s3-postgres.ts | 20 + 5 files changed, 631 insertions(+), 9 deletions(-) create mode 100644 packages/@aws-cdk/aws-rds/test/integ.instance-s3-postgres.expected.json create mode 100644 packages/@aws-cdk/aws-rds/test/integ.instance-s3-postgres.ts diff --git a/packages/@aws-cdk/aws-rds/lib/cluster.ts b/packages/@aws-cdk/aws-rds/lib/cluster.ts index ad5a2201c759c..15f9e60215ebc 100644 --- a/packages/@aws-cdk/aws-rds/lib/cluster.ts +++ b/packages/@aws-cdk/aws-rds/lib/cluster.ts @@ -327,7 +327,7 @@ abstract class DatabaseClusterNew extends DatabaseClusterBase { }), ]; - let { s3ImportRole, s3ExportRole } = setupS3ImportExport(this, props); + let { s3ImportRole, s3ExportRole } = setupS3ImportExport(this, props, /* combineRoles */ false); // bind the engine to the Cluster const clusterEngineBindConfig = props.engine.bindToCluster(this, { s3ImportRole, diff --git a/packages/@aws-cdk/aws-rds/lib/instance.ts b/packages/@aws-cdk/aws-rds/lib/instance.ts index 8d285b7375006..3349d15fb5c97 100644 --- a/packages/@aws-cdk/aws-rds/lib/instance.ts +++ b/packages/@aws-cdk/aws-rds/lib/instance.ts @@ -576,7 +576,6 @@ export interface DatabaseInstanceNewProps { /** * Role that will be associated with this DB instance to enable S3 export. - * This feature is only supported by the Microsoft SQL Server and Oracle engines. * * This property must not be used if `s3ExportBuckets` is used. * @@ -591,7 +590,6 @@ export interface DatabaseInstanceNewProps { /** * S3 buckets that you want to load data into. - * This feature is only supported by the Microsoft SQL Server and Oracle engines. * * This property must not be used if `s3ExportRole` is used. * @@ -847,7 +845,10 @@ abstract class DatabaseInstanceSource extends DatabaseInstanceNew implements IDa this.multiUserRotationApplication = props.engine.multiUserRotationApplication; this.engine = props.engine; - let { s3ImportRole, s3ExportRole } = setupS3ImportExport(this, props, true); + const engineType = props.engine.engineType; + // only Oracle and SQL Server require the import and export Roles to be the same + const combineRoles = engineType.startsWith('oracle-') || engineType.startsWith('sqlserver-'); + let { s3ImportRole, s3ExportRole } = setupS3ImportExport(this, props, combineRoles); const engineConfig = props.engine.bindToInstance(this, { ...props, s3ImportRole, @@ -866,8 +867,8 @@ abstract class DatabaseInstanceSource extends DatabaseInstanceNew implements IDa if (!engineFeatures?.s3Export) { throw new Error(`Engine '${engineDescription(props.engine)}' does not support S3 export`); } - // Only add the export role and feature if they are different from the import role & feature. - if (s3ImportRole !== s3ExportRole || engineFeatures.s3Import !== engineFeatures?.s3Export) { + // only add the export feature if it's different from the import feature + if (engineFeatures.s3Import !== engineFeatures?.s3Export) { instanceAssociatedRoles.push({ roleArn: s3ExportRole.roleArn, featureName: engineFeatures?.s3Export }); } } @@ -883,7 +884,7 @@ abstract class DatabaseInstanceSource extends DatabaseInstanceNew implements IDa allowMajorVersionUpgrade: props.allowMajorVersionUpgrade, dbName: props.databaseName, dbParameterGroupName: instanceParameterGroupConfig?.parameterGroupName, - engine: props.engine.engineType, + engine: engineType, engineVersion: props.engine.engineVersion?.fullVersion, licenseModel: props.licenseModel, timezone: props.timezone, diff --git a/packages/@aws-cdk/aws-rds/lib/private/util.ts b/packages/@aws-cdk/aws-rds/lib/private/util.ts index c142a903bad7a..1664647c92bd8 100644 --- a/packages/@aws-cdk/aws-rds/lib/private/util.ts +++ b/packages/@aws-cdk/aws-rds/lib/private/util.ts @@ -31,14 +31,14 @@ export interface DatabaseS3ImportExportProps { * Validates the S3 import/export props and returns the import/export roles, if any. * If `combineRoles` is true, will reuse the import role for export (or vice versa) if possible. * - * Notably, `combineRoles` is (by default) set to true for instances, but false for clusters. + * Notably, `combineRoles` is set to true for instances, but false for clusters. * This is because the `combineRoles` functionality is most applicable to instances and didn't exist * for the initial clusters implementation. To maintain backwards compatibility, it is set to false for clusters. */ export function setupS3ImportExport( scope: Construct, props: DatabaseS3ImportExportProps, - combineRoles?: boolean): { s3ImportRole?: iam.IRole, s3ExportRole?: iam.IRole } { + combineRoles: boolean): { s3ImportRole?: iam.IRole, s3ExportRole?: iam.IRole } { let s3ImportRole = props.s3ImportRole; let s3ExportRole = props.s3ExportRole; diff --git a/packages/@aws-cdk/aws-rds/test/integ.instance-s3-postgres.expected.json b/packages/@aws-cdk/aws-rds/test/integ.instance-s3-postgres.expected.json new file mode 100644 index 0000000000000..2a55df00bab2c --- /dev/null +++ b/packages/@aws-cdk/aws-rds/test/integ.instance-s3-postgres.expected.json @@ -0,0 +1,601 @@ +{ + "Resources": { + "VPCB9E5F0B4": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default", + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-rds-instance-s3-postgres-integ/VPC" + } + ] + } + }, + "VPCPublicSubnet1SubnetB4246D30": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "CidrBlock": "10.0.0.0/18", + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "AvailabilityZone": "test-region-1a", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "aws-cdk-rds-instance-s3-postgres-integ/VPC/PublicSubnet1" + } + ] + } + }, + "VPCPublicSubnet1RouteTableFEE4B781": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-rds-instance-s3-postgres-integ/VPC/PublicSubnet1" + } + ] + } + }, + "VPCPublicSubnet1RouteTableAssociation0B0896DC": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VPCPublicSubnet1RouteTableFEE4B781" + }, + "SubnetId": { + "Ref": "VPCPublicSubnet1SubnetB4246D30" + } + } + }, + "VPCPublicSubnet1DefaultRoute91CEF279": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VPCPublicSubnet1RouteTableFEE4B781" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VPCIGWB7E252D3" + } + }, + "DependsOn": [ + "VPCVPCGW99B986DC" + ] + }, + "VPCPublicSubnet1EIP6AD938E8": { + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-rds-instance-s3-postgres-integ/VPC/PublicSubnet1" + } + ] + } + }, + "VPCPublicSubnet1NATGatewayE0556630": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "SubnetId": { + "Ref": "VPCPublicSubnet1SubnetB4246D30" + }, + "AllocationId": { + "Fn::GetAtt": [ + "VPCPublicSubnet1EIP6AD938E8", + "AllocationId" + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-rds-instance-s3-postgres-integ/VPC/PublicSubnet1" + } + ] + } + }, + "VPCPublicSubnet2Subnet74179F39": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "CidrBlock": "10.0.64.0/18", + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "AvailabilityZone": "test-region-1b", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "aws-cdk-rds-instance-s3-postgres-integ/VPC/PublicSubnet2" + } + ] + } + }, + "VPCPublicSubnet2RouteTable6F1A15F1": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-rds-instance-s3-postgres-integ/VPC/PublicSubnet2" + } + ] + } + }, + "VPCPublicSubnet2RouteTableAssociation5A808732": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VPCPublicSubnet2RouteTable6F1A15F1" + }, + "SubnetId": { + "Ref": "VPCPublicSubnet2Subnet74179F39" + } + } + }, + "VPCPublicSubnet2DefaultRouteB7481BBA": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VPCPublicSubnet2RouteTable6F1A15F1" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VPCIGWB7E252D3" + } + }, + "DependsOn": [ + "VPCVPCGW99B986DC" + ] + }, + "VPCPrivateSubnet1Subnet8BCA10E0": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "CidrBlock": "10.0.128.0/18", + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "AvailabilityZone": "test-region-1a", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "aws-cdk-rds-instance-s3-postgres-integ/VPC/PrivateSubnet1" + } + ] + } + }, + "VPCPrivateSubnet1RouteTableBE8A6027": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-rds-instance-s3-postgres-integ/VPC/PrivateSubnet1" + } + ] + } + }, + "VPCPrivateSubnet1RouteTableAssociation347902D1": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VPCPrivateSubnet1RouteTableBE8A6027" + }, + "SubnetId": { + "Ref": "VPCPrivateSubnet1Subnet8BCA10E0" + } + } + }, + "VPCPrivateSubnet1DefaultRouteAE1D6490": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VPCPrivateSubnet1RouteTableBE8A6027" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "VPCPublicSubnet1NATGatewayE0556630" + } + } + }, + "VPCPrivateSubnet2SubnetCFCDAA7A": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "CidrBlock": "10.0.192.0/18", + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "AvailabilityZone": "test-region-1b", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "aws-cdk-rds-instance-s3-postgres-integ/VPC/PrivateSubnet2" + } + ] + } + }, + "VPCPrivateSubnet2RouteTable0A19E10E": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-rds-instance-s3-postgres-integ/VPC/PrivateSubnet2" + } + ] + } + }, + "VPCPrivateSubnet2RouteTableAssociation0C73D413": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VPCPrivateSubnet2RouteTable0A19E10E" + }, + "SubnetId": { + "Ref": "VPCPrivateSubnet2SubnetCFCDAA7A" + } + } + }, + "VPCPrivateSubnet2DefaultRouteF4F5CFD2": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VPCPrivateSubnet2RouteTable0A19E10E" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "VPCPublicSubnet1NATGatewayE0556630" + } + } + }, + "VPCIGWB7E252D3": { + "Type": "AWS::EC2::InternetGateway", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-rds-instance-s3-postgres-integ/VPC" + } + ] + } + }, + "VPCVPCGW99B986DC": { + "Type": "AWS::EC2::VPCGatewayAttachment", + "Properties": { + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "InternetGatewayId": { + "Ref": "VPCIGWB7E252D3" + } + } + }, + "ImportBucketBAF3A8E9": { + "Type": "AWS::S3::Bucket", + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "ExportBucket4E99310E": { + "Type": "AWS::S3::Bucket", + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "InstanceSubnetGroupF2CBA54F": { + "Type": "AWS::RDS::DBSubnetGroup", + "Properties": { + "DBSubnetGroupDescription": "Subnet group for Instance database", + "SubnetIds": [ + { + "Ref": "VPCPrivateSubnet1Subnet8BCA10E0" + }, + { + "Ref": "VPCPrivateSubnet2SubnetCFCDAA7A" + } + ] + } + }, + "InstanceSecurityGroupB4E5FA83": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Security group for Instance database", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "InstanceS3ImportRole30959D06": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "rds.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "InstanceS3ImportRoleDefaultPolicy297F292A": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetObject*", + "s3:GetBucket*", + "s3:List*" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "ImportBucketBAF3A8E9", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "ImportBucketBAF3A8E9", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "InstanceS3ImportRoleDefaultPolicy297F292A", + "Roles": [ + { + "Ref": "InstanceS3ImportRole30959D06" + } + ] + } + }, + "InstanceS3ExportRole9891C2F7": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "rds.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "InstanceS3ExportRoleDefaultPolicy62C930BC": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetObject*", + "s3:GetBucket*", + "s3:List*", + "s3:DeleteObject*", + "s3:PutObject", + "s3:Abort*" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "ExportBucket4E99310E", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "ExportBucket4E99310E", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "InstanceS3ExportRoleDefaultPolicy62C930BC", + "Roles": [ + { + "Ref": "InstanceS3ExportRole9891C2F7" + } + ] + } + }, + "InstanceSecret478E0A47": { + "Type": "AWS::SecretsManager::Secret", + "Properties": { + "Description": { + "Fn::Join": [ + "", + [ + "Generated by the CDK for stack: ", + { + "Ref": "AWS::StackName" + } + ] + ] + }, + "GenerateSecretString": { + "ExcludeCharacters": " %+~`#$&*()|[]{}:;<>?!'/@\"\\", + "GenerateStringKey": "password", + "PasswordLength": 30, + "SecretStringTemplate": "{\"username\":\"postgres\"}" + } + } + }, + "InstanceSecretAttachment83BEE581": { + "Type": "AWS::SecretsManager::SecretTargetAttachment", + "Properties": { + "SecretId": { + "Ref": "InstanceSecret478E0A47" + }, + "TargetId": { + "Ref": "InstanceC1063A87" + }, + "TargetType": "AWS::RDS::DBInstance" + } + }, + "InstanceC1063A87": { + "Type": "AWS::RDS::DBInstance", + "Properties": { + "DBInstanceClass": "db.m5.large", + "AllocatedStorage": "100", + "AssociatedRoles": [ + { + "FeatureName": "s3Import", + "RoleArn": { + "Fn::GetAtt": [ + "InstanceS3ImportRole30959D06", + "Arn" + ] + } + }, + { + "FeatureName": "s3Export", + "RoleArn": { + "Fn::GetAtt": [ + "InstanceS3ExportRole9891C2F7", + "Arn" + ] + } + } + ], + "CopyTagsToSnapshot": true, + "DBSubnetGroupName": { + "Ref": "InstanceSubnetGroupF2CBA54F" + }, + "EnableIAMDatabaseAuthentication": true, + "Engine": "postgres", + "EngineVersion": "11.12", + "MasterUsername": { + "Fn::Join": [ + "", + [ + "{{resolve:secretsmanager:", + { + "Ref": "InstanceSecret478E0A47" + }, + ":SecretString:username::}}" + ] + ] + }, + "MasterUserPassword": { + "Fn::Join": [ + "", + [ + "{{resolve:secretsmanager:", + { + "Ref": "InstanceSecret478E0A47" + }, + ":SecretString:password::}}" + ] + ] + }, + "MultiAZ": false, + "PubliclyAccessible": true, + "StorageType": "gp2", + "VPCSecurityGroups": [ + { + "Fn::GetAtt": [ + "InstanceSecurityGroupB4E5FA83", + "GroupId" + ] + } + ] + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-rds/test/integ.instance-s3-postgres.ts b/packages/@aws-cdk/aws-rds/test/integ.instance-s3-postgres.ts new file mode 100644 index 0000000000000..e07501039549b --- /dev/null +++ b/packages/@aws-cdk/aws-rds/test/integ.instance-s3-postgres.ts @@ -0,0 +1,20 @@ +import * as ec2 from '@aws-cdk/aws-ec2'; +import * as s3 from '@aws-cdk/aws-s3'; +import * as cdk from '@aws-cdk/core'; +import * as rds from '../lib'; + +const app = new cdk.App(); +const stack = new cdk.Stack(app, 'aws-cdk-rds-instance-s3-postgres-integ'); + +new rds.DatabaseInstance(stack, 'Instance', { + engine: rds.DatabaseInstanceEngine.postgres({ version: rds.PostgresEngineVersion.VER_11_12 }), + vpc: new ec2.Vpc(stack, 'VPC', { maxAzs: 2, natGateways: 1 }), + multiAz: false, + publiclyAccessible: true, + iamAuthentication: true, + s3ImportBuckets: [new s3.Bucket(stack, 'ImportBucket', { removalPolicy: cdk.RemovalPolicy.DESTROY })], + s3ExportBuckets: [new s3.Bucket(stack, 'ExportBucket', { removalPolicy: cdk.RemovalPolicy.DESTROY })], + removalPolicy: cdk.RemovalPolicy.DESTROY, +}); + +app.synth(); From e063fbd3a31bdce046b2598e4a429c45d016f055 Mon Sep 17 00:00:00 2001 From: flemjame-at-amazon <57235867+flemjame-at-amazon@users.noreply.github.com> Date: Mon, 25 Oct 2021 09:47:16 -0400 Subject: [PATCH 22/87] feat(route53): Expose VpcEndpointServiceDomainName domain name as a property (#16458) I want to be able to read the domain name associated with the object. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../lib/vpc-endpoint-service-domain-name.ts | 11 ++++++++--- .../vpc-endpoint-service-domain-name.test.ts | 16 ++++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk/aws-route53/lib/vpc-endpoint-service-domain-name.ts b/packages/@aws-cdk/aws-route53/lib/vpc-endpoint-service-domain-name.ts index 9098503b625f4..862a63e26e6d1 100644 --- a/packages/@aws-cdk/aws-route53/lib/vpc-endpoint-service-domain-name.ts +++ b/packages/@aws-cdk/aws-route53/lib/vpc-endpoint-service-domain-name.ts @@ -46,6 +46,11 @@ export class VpcEndpointServiceDomainName extends CoreConstruct { // Track all domain names created, so someone doesn't accidentally associate two domains with a single service private static readonly endpointServicesMap: { [endpointService: string]: string} = {}; + /** + * The domain name associated with the private DNS configuration + */ + public domainName: string; + // The way this class works is by using three custom resources and a TxtRecord in conjunction // The first custom resource tells the VPC endpoint service to use the given DNS name // The VPC endpoint service will then say: @@ -58,16 +63,16 @@ export class VpcEndpointServiceDomainName extends CoreConstruct { const serviceUniqueId = Names.nodeUniqueId(props.endpointService.node); const serviceId = props.endpointService.vpcEndpointServiceId; - const privateDnsName = props.domainName; + this.domainName = props.domainName; // Make sure a user doesn't accidentally add multiple domains this.validateProps(props); - VpcEndpointServiceDomainName.endpointServicesMap[serviceUniqueId] = privateDnsName; + VpcEndpointServiceDomainName.endpointServicesMap[serviceUniqueId] = this.domainName; VpcEndpointServiceDomainName.endpointServices.push(props.endpointService); // Enable Private DNS on the endpoint service and retrieve the AWS-generated configuration - const privateDnsConfiguration = this.getPrivateDnsConfiguration(serviceUniqueId, serviceId, privateDnsName); + const privateDnsConfiguration = this.getPrivateDnsConfiguration(serviceUniqueId, serviceId, this.domainName); // Tell AWS to verify that this account owns the domain attached to the service this.verifyPrivateDnsConfiguration(privateDnsConfiguration, props.publicHostedZone); diff --git a/packages/@aws-cdk/aws-route53/test/vpc-endpoint-service-domain-name.test.ts b/packages/@aws-cdk/aws-route53/test/vpc-endpoint-service-domain-name.test.ts index 35b7ac9c67596..506a25e2a26df 100644 --- a/packages/@aws-cdk/aws-route53/test/vpc-endpoint-service-domain-name.test.ts +++ b/packages/@aws-cdk/aws-route53/test/vpc-endpoint-service-domain-name.test.ts @@ -264,4 +264,20 @@ test('throws if creating multiple domains for a single service', () => { publicHostedZone: zone, }); }).toThrow(/Cannot create a VpcEndpointServiceDomainName for service/); +}); + + +test('endpoint domain name property equals input domain name', () => { + // GIVEN + vpces = new VpcEndpointService(stack, 'NameTest', { + vpcEndpointServiceLoadBalancers: [nlb], + }); + + const dn = new VpcEndpointServiceDomainName(stack, 'EndpointDomain', { + endpointService: vpces, + domainName: 'name-test.aws-cdk.dev', + publicHostedZone: zone, + }); + expect(dn.domainName).toEqual('name-test.aws-cdk.dev'); + }); \ No newline at end of file From f1e244b331f95253030bae0525775683b5a350c4 Mon Sep 17 00:00:00 2001 From: Mina Asham Date: Mon, 25 Oct 2021 16:43:16 +0200 Subject: [PATCH 23/87] feat(ec2): look up VPC from different regions (#16728) - Currently Vpc.fromLookup will default to the Stack's region, when needing to lookup Stack's from other regions (e.g. for VPC peering) this doesn't work and the only other work around is a custom resource - The lookup provider already supports passing a region and works fine if you pass one that's not the Stack's inferred region, so just propagate that option to the top level - Fixes #10208 ---- *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-ec2/lib/vpc-lookup.ts | 7 +++++++ packages/@aws-cdk/aws-ec2/lib/vpc.ts | 6 ++++++ .../aws-ec2/test/vpc.from-lookup.test.ts | 18 ++++++++++++++++++ 3 files changed, 31 insertions(+) diff --git a/packages/@aws-cdk/aws-ec2/lib/vpc-lookup.ts b/packages/@aws-cdk/aws-ec2/lib/vpc-lookup.ts index 3f9f49dba2540..8db845763dd0e 100644 --- a/packages/@aws-cdk/aws-ec2/lib/vpc-lookup.ts +++ b/packages/@aws-cdk/aws-ec2/lib/vpc-lookup.ts @@ -48,4 +48,11 @@ export interface VpcLookupOptions { * @default aws-cdk:subnet-name */ readonly subnetGroupNameTag?: string; + + /** + * Optional to override inferred region + * + * @default Current stack's environment region + */ + readonly region?: string; } diff --git a/packages/@aws-cdk/aws-ec2/lib/vpc.ts b/packages/@aws-cdk/aws-ec2/lib/vpc.ts index b8194eb161c1d..64f3bb46f14c8 100644 --- a/packages/@aws-cdk/aws-ec2/lib/vpc.ts +++ b/packages/@aws-cdk/aws-ec2/lib/vpc.ts @@ -1118,9 +1118,15 @@ export class Vpc extends VpcBase { filter.isDefault = options.isDefault ? 'true' : 'false'; } + const overrides: {[key: string]: string} = {}; + if (options.region) { + overrides.region = options.region; + } + const attributes: cxapi.VpcContextResponse = ContextProvider.getValue(scope, { provider: cxschema.ContextProvider.VPC_PROVIDER, props: { + ...overrides, filter, returnAsymmetricSubnets: true, subnetGroupNameTag: options.subnetGroupNameTag, diff --git a/packages/@aws-cdk/aws-ec2/test/vpc.from-lookup.test.ts b/packages/@aws-cdk/aws-ec2/test/vpc.from-lookup.test.ts index 4ad08203a525e..30c0ab1cf2a80 100644 --- a/packages/@aws-cdk/aws-ec2/test/vpc.from-lookup.test.ts +++ b/packages/@aws-cdk/aws-ec2/test/vpc.from-lookup.test.ts @@ -250,6 +250,24 @@ describe('vpc from lookup', () => { restoreContextProvider(previous); }); + test('passes account and region', () => { + const previous = mockVpcContextProviderWith({ + vpcId: 'vpc-1234', + subnetGroups: [], + }, options => { + expect(options.region).toEqual('region-1234'); + }); + + const stack = new Stack(); + const vpc = Vpc.fromLookup(stack, 'Vpc', { + vpcId: 'vpc-1234', + region: 'region-1234', + }); + + expect(vpc.vpcId).toEqual('vpc-1234'); + + restoreContextProvider(previous); + }); }); }); From 8d0c555d048c07518c89e69951a1e9f21ba99bd7 Mon Sep 17 00:00:00 2001 From: Naseem <24660299+naseemkullah@users.noreply.github.com> Date: Mon, 25 Oct 2021 11:36:21 -0400 Subject: [PATCH 24/87] feat(cloudfront): add amplify managed cache policy (#16880) ---- *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-cloudfront/lib/cache-policy.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-cloudfront/lib/cache-policy.ts b/packages/@aws-cdk/aws-cloudfront/lib/cache-policy.ts index d0dad353a8727..533ccbd5d78b9 100644 --- a/packages/@aws-cdk/aws-cloudfront/lib/cache-policy.ts +++ b/packages/@aws-cdk/aws-cloudfront/lib/cache-policy.ts @@ -85,9 +85,13 @@ export interface CachePolicyProps { * A Cache Policy configuration. * * @resource AWS::CloudFront::CachePolicy + * @link https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/using-managed-cache-policies.html */ export class CachePolicy extends Resource implements ICachePolicy { - + /** + * This policy is designed for use with an origin that is an AWS Amplify web app. + */ + public static readonly AMPLIFY = CachePolicy.fromManagedCachePolicy('2e54312d-136d-493c-8eb9-b001f22f67d2'); /** * Optimize cache efficiency by minimizing the values that CloudFront includes in the cache key. * Query strings and cookies are not included in the cache key, and only the normalized 'Accept-Encoding' header is included. From 7b31376e6349440f7b215d6e11c3dd900d50df34 Mon Sep 17 00:00:00 2001 From: Lukas Fruntke Date: Mon, 25 Oct 2021 18:28:33 +0200 Subject: [PATCH 25/87] feat(ec2): add vpcArn to IVpc and Vpc (#16666) fixes #16493 introduces context aware ARN for VPC, dervied from the current stack. This allows easier referencing compared to constructing the ARN from the vpc id. ---- *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-ec2/README.md | 2 +- packages/@aws-cdk/aws-ec2/lib/vpc.ts | 35 +++++++++++++++++++++- packages/@aws-cdk/aws-ec2/test/vpc.test.ts | 7 ++++- 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk/aws-ec2/README.md b/packages/@aws-cdk/aws-ec2/README.md index eecc6f3857da4..7b00a026bf871 100644 --- a/packages/@aws-cdk/aws-ec2/README.md +++ b/packages/@aws-cdk/aws-ec2/README.md @@ -744,7 +744,7 @@ By default, a new security group is created and logging is enabled. Moreover, a authorize all users to the VPC CIDR is created. To customize authorization rules, set the `authorizeAllUsersToVpcCidr` prop to `false` -and use `addaddAuthorizationRule()`: +and use `addAuthorizationRule()`: ```ts fixture=client-vpn const endpoint = vpc.addClientVpnEndpoint('Endpoint', { diff --git a/packages/@aws-cdk/aws-ec2/lib/vpc.ts b/packages/@aws-cdk/aws-ec2/lib/vpc.ts index 64f3bb46f14c8..cd70f71582718 100644 --- a/packages/@aws-cdk/aws-ec2/lib/vpc.ts +++ b/packages/@aws-cdk/aws-ec2/lib/vpc.ts @@ -1,7 +1,7 @@ import * as cxschema from '@aws-cdk/cloud-assembly-schema'; import { Annotations, ConcreteDependable, ContextProvider, DependableTrait, IConstruct, - IDependable, IResource, Lazy, Resource, Stack, Token, Tags, Names, + IDependable, IResource, Lazy, Resource, Stack, Token, Tags, Names, Arn, } from '@aws-cdk/core'; import * as cxapi from '@aws-cdk/cx-api'; import { Construct, Node } from 'constructs'; @@ -78,6 +78,12 @@ export interface IVpc extends IResource { */ readonly vpcId: string; + /** + * ARN for this VPC + * @attribute + */ + readonly vpcArn: string; + /** * CIDR range for this VPC * @@ -357,6 +363,11 @@ abstract class VpcBase extends Resource implements IVpc { */ public abstract readonly vpcId: string; + /** + * Arn of this VPC + */ + public abstract readonly vpcArn: string; + /** * CIDR range for this VPC */ @@ -1153,6 +1164,11 @@ export class Vpc extends VpcBase { */ public readonly vpcId: string; + /** + * @attribute + */ + public readonly vpcArn: string; + /** * @attribute */ @@ -1283,6 +1299,11 @@ export class Vpc extends VpcBase { this.availabilityZones = this.availabilityZones.slice(0, maxAZs); this.vpcId = this.resource.ref; + this.vpcArn = Arn.format({ + service: 'ec2', + resource: 'vpc', + resourceName: this.vpcId, + }, stack); const defaultSubnet = props.natGateways === 0 ? Vpc.DEFAULT_SUBNETS_NO_NAT : Vpc.DEFAULT_SUBNETS; this.subnetConfiguration = ifUndefined(props.subnetConfiguration, defaultSubnet); @@ -1859,6 +1880,7 @@ function ifUndefined(value: T | undefined, defaultValue: T): T { class ImportedVpc extends VpcBase { public readonly vpcId: string; + public readonly vpcArn: string; public readonly publicSubnets: ISubnet[]; public readonly privateSubnets: ISubnet[]; public readonly isolatedSubnets: ISubnet[]; @@ -1870,6 +1892,11 @@ class ImportedVpc extends VpcBase { super(scope, id); this.vpcId = props.vpcId; + this.vpcArn = Arn.format({ + service: 'ec2', + resource: 'vpc', + resourceName: this.vpcId, + }, Stack.of(this)); this.cidr = props.vpcCidrBlock; this.availabilityZones = props.availabilityZones; this._vpnGatewayId = props.vpnGatewayId; @@ -1903,6 +1930,7 @@ class ImportedVpc extends VpcBase { class LookedUpVpc extends VpcBase { public readonly vpcId: string; + public readonly vpcArn: string; public readonly internetConnectivityEstablished: IDependable = new ConcreteDependable(); public readonly availabilityZones: string[]; public readonly publicSubnets: ISubnet[]; @@ -1914,6 +1942,11 @@ class LookedUpVpc extends VpcBase { super(scope, id); this.vpcId = props.vpcId; + this.vpcArn = Arn.format({ + service: 'ec2', + resource: 'vpc', + resourceName: this.vpcId, + }, Stack.of(this)); this.cidr = props.vpcCidrBlock; this._vpnGatewayId = props.vpnGatewayId; this.incompleteSubnetDefinition = isIncomplete; diff --git a/packages/@aws-cdk/aws-ec2/test/vpc.test.ts b/packages/@aws-cdk/aws-ec2/test/vpc.test.ts index 90942056865c7..eedc950ab584b 100644 --- a/packages/@aws-cdk/aws-ec2/test/vpc.test.ts +++ b/packages/@aws-cdk/aws-ec2/test/vpc.test.ts @@ -36,7 +36,12 @@ describe('vpc', () => { const stack = getTestStack(); const vpc = new Vpc(stack, 'TheVPC'); expect(stack.resolve(vpc.vpcId)).toEqual({ Ref: 'TheVPC92636AB0' }); + }); + test('vpc.vpcArn returns a token to the VPC ID', () => { + const stack = getTestStack(); + const vpc = new Vpc(stack, 'TheVPC'); + expect(stack.resolve(vpc.vpcArn)).toEqual({ 'Fn::Join': ['', ['arn:', { Ref: 'AWS::Partition' }, ':ec2:us-east-1:123456789012:vpc/', { Ref: 'TheVPC92636AB0' }]] }); }); test('it uses the correct network range', () => { @@ -1786,4 +1791,4 @@ function hasTags(expectedTags: Array<{Key: string, Value: string}>): (props: any throw e; } }; -} +} \ No newline at end of file From 443a23e8c1e0de97f6ae05a3e451b0407165a447 Mon Sep 17 00:00:00 2001 From: Julian Michel Date: Mon, 25 Oct 2021 19:20:46 +0200 Subject: [PATCH 26/87] feat(ec2): add X2g instances (for RDS) (#17081) Add support for X2g instances. Announcements: - https://aws.amazon.com/about-aws/whats-new/2021/09/amazon-aurora-supports-aws-graviton2-based-x2g-instances/ - https://aws.amazon.com/about-aws/whats-new/2021/09/amazon-rds-x2g-mysql-mariadb-postgresql/ X2g instances are only supported in RDS. They are not available in EC2. RDS uses instances types from module EC2. Therefore, X2g should be added in EC2 (see skinny85's [comment](https://github.com/aws/aws-cdk/issues/16948#issuecomment-946254267)). Closes #16948. ---- *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-ec2/lib/instance-types.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/packages/@aws-cdk/aws-ec2/lib/instance-types.ts b/packages/@aws-cdk/aws-ec2/lib/instance-types.ts index 1b778fee66e6e..97d3d03e55219 100644 --- a/packages/@aws-cdk/aws-ec2/lib/instance-types.ts +++ b/packages/@aws-cdk/aws-ec2/lib/instance-types.ts @@ -372,6 +372,20 @@ export enum InstanceClass { */ X1E = 'x1e', + /** + * Memory-intensive instances, 2nd generation with Graviton2 processors + * + * This instance type can be used only in RDS. It is not supported in EC2. + */ + MEMORY_INTENSIVE_2_GRAVITON2 = 'x2g', + + /** + * Memory-intensive instances, 2nd generation with Graviton2 processors + * + * This instance type can be used only in RDS. It is not supported in EC2. + */ + X2G = 'x2g', + /** * Memory-intensive instances, 2nd generation with Graviton2 processors and local NVME drive */ From 691d3771d32002b3cd4cb1221af92762b749e716 Mon Sep 17 00:00:00 2001 From: Lukas Fruntke Date: Mon, 25 Oct 2021 20:12:51 +0200 Subject: [PATCH 27/87] feat(ec2): add region parameter for UserData via addS3DownloadCommand (#16667) Allow the specification of a region in `addS3DownloadCommand()` in the UserData helper. Fixes #8287 ---- *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-ec2/README.md | 1 + packages/@aws-cdk/aws-ec2/lib/user-data.ts | 10 +++- .../@aws-cdk/aws-ec2/test/userdata.test.ts | 59 +++++++++++++++++++ 3 files changed, 68 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/aws-ec2/README.md b/packages/@aws-cdk/aws-ec2/README.md index 7b00a026bf871..f450e29dfcf20 100644 --- a/packages/@aws-cdk/aws-ec2/README.md +++ b/packages/@aws-cdk/aws-ec2/README.md @@ -1110,6 +1110,7 @@ const instance = new ec2.Instance(this, 'Instance', { const localPath = instance.userData.addS3DownloadCommand({ bucket:asset.bucket, bucketKey:asset.s3ObjectKey, + region: 'us-east-1', // Optional }); instance.userData.addExecuteFileCommand({ filePath:localPath, diff --git a/packages/@aws-cdk/aws-ec2/lib/user-data.ts b/packages/@aws-cdk/aws-ec2/lib/user-data.ts index 9b835744b3a6e..14b94d2d2ad4a 100644 --- a/packages/@aws-cdk/aws-ec2/lib/user-data.ts +++ b/packages/@aws-cdk/aws-ec2/lib/user-data.ts @@ -37,6 +37,12 @@ export interface S3DownloadOptions { */ readonly localFile?: string; + /** + * The region of the S3 Bucket (needed for access via VPC Gateway) + * @default none + */ + readonly region?: string + } /** @@ -156,7 +162,7 @@ class LinuxUserData extends UserData { const localPath = ( params.localFile && params.localFile.length !== 0 ) ? params.localFile : `/tmp/${ params.bucketKey }`; this.addCommands( `mkdir -p $(dirname '${localPath}')`, - `aws s3 cp '${s3Path}' '${localPath}'`, + `aws s3 cp '${s3Path}' '${localPath}'` + (params.region !== undefined ? ` --region ${params.region}` : ''), ); return localPath; @@ -215,7 +221,7 @@ class WindowsUserData extends UserData { const localPath = ( params.localFile && params.localFile.length !== 0 ) ? params.localFile : `C:/temp/${ params.bucketKey }`; this.addCommands( `mkdir (Split-Path -Path '${localPath}' ) -ea 0`, - `Read-S3Object -BucketName '${params.bucket.bucketName}' -key '${params.bucketKey}' -file '${localPath}' -ErrorAction Stop`, + `Read-S3Object -BucketName '${params.bucket.bucketName}' -key '${params.bucketKey}' -file '${localPath}' -ErrorAction Stop` + (params.region !== undefined ? ` -Region ${params.region}` : ''), ); return localPath; } diff --git a/packages/@aws-cdk/aws-ec2/test/userdata.test.ts b/packages/@aws-cdk/aws-ec2/test/userdata.test.ts index 272ad60a84b00..e2596d8699abd 100644 --- a/packages/@aws-cdk/aws-ec2/test/userdata.test.ts +++ b/packages/@aws-cdk/aws-ec2/test/userdata.test.ts @@ -85,6 +85,35 @@ describe('user data', () => { 'Read-S3Object -BucketName \'test2\' -key \'filename2.bat\' -file \'c:\\test\\location\\otherScript.bat\' -ErrorAction Stop', ); + }); + test('can windows userdata download S3 files with given region', () => { + // GIVEN + const stack = new Stack(); + const userData = ec2.UserData.forWindows(); + const bucket = Bucket.fromBucketName( stack, 'testBucket', 'test' ); + const bucket2 = Bucket.fromBucketName( stack, 'testBucket2', 'test2' ); + + // WHEN + userData.addS3DownloadCommand({ + bucket, + bucketKey: 'filename.bat', + region: 'us-east-1', + } ); + userData.addS3DownloadCommand({ + bucket: bucket2, + bucketKey: 'filename2.bat', + localFile: 'c:\\test\\location\\otherScript.bat', + region: 'us-east-1', + } ); + + // THEN + const rendered = userData.render(); + expect(rendered).toEqual('mkdir (Split-Path -Path \'C:/temp/filename.bat\' ) -ea 0\n' + + 'Read-S3Object -BucketName \'test\' -key \'filename.bat\' -file \'C:/temp/filename.bat\' -ErrorAction Stop -Region us-east-1\n' + + 'mkdir (Split-Path -Path \'c:\\test\\location\\otherScript.bat\' ) -ea 0\n' + + 'Read-S3Object -BucketName \'test2\' -key \'filename2.bat\' -file \'c:\\test\\location\\otherScript.bat\' -ErrorAction Stop -Region us-east-1', + ); + }); test('can windows userdata execute files', () => { // GIVEN @@ -189,6 +218,36 @@ describe('user data', () => { 'aws s3 cp \'s3://test2/filename2.sh\' \'c:\\test\\location\\otherScript.sh\'', ); + }); + test('can linux userdata download S3 files from specific region', () => { + // GIVEN + const stack = new Stack(); + const userData = ec2.UserData.forLinux(); + const bucket = Bucket.fromBucketName( stack, 'testBucket', 'test' ); + const bucket2 = Bucket.fromBucketName( stack, 'testBucket2', 'test2' ); + + // WHEN + userData.addS3DownloadCommand({ + bucket, + bucketKey: 'filename.sh', + region: 'us-east-1', + } ); + userData.addS3DownloadCommand({ + bucket: bucket2, + bucketKey: 'filename2.sh', + localFile: 'c:\\test\\location\\otherScript.sh', + region: 'us-east-1', + } ); + + // THEN + const rendered = userData.render(); + expect(rendered).toEqual('#!/bin/bash\n' + + 'mkdir -p $(dirname \'/tmp/filename.sh\')\n' + + 'aws s3 cp \'s3://test/filename.sh\' \'/tmp/filename.sh\' --region us-east-1\n' + + 'mkdir -p $(dirname \'c:\\test\\location\\otherScript.sh\')\n' + + 'aws s3 cp \'s3://test2/filename2.sh\' \'c:\\test\\location\\otherScript.sh\' --region us-east-1', + ); + }); test('can linux userdata execute files', () => { // GIVEN From bdf30c696b04b26a8e41548839d5c4cf61d471cc Mon Sep 17 00:00:00 2001 From: Kyle Roach Date: Mon, 25 Oct 2021 19:06:25 +0000 Subject: [PATCH 28/87] fix(redshift): cluster uses key ARN instead of key ID (#17108) Field was incorrectly using key arn instead of id. Fixes #17032 ---- *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-redshift/lib/cluster.ts | 2 +- .../aws-redshift/test/cluster.test.ts | 5 +-- .../test/integ.database.expected.json | 38 +++++++++++++++++++ .../aws-redshift/test/integ.database.ts | 2 + 4 files changed, 42 insertions(+), 5 deletions(-) diff --git a/packages/@aws-cdk/aws-redshift/lib/cluster.ts b/packages/@aws-cdk/aws-redshift/lib/cluster.ts index a94bfa31b7fb5..a43b6f6993c72 100644 --- a/packages/@aws-cdk/aws-redshift/lib/cluster.ts +++ b/packages/@aws-cdk/aws-redshift/lib/cluster.ts @@ -483,7 +483,7 @@ export class Cluster extends ClusterBase { dbName: props.defaultDatabaseName || 'default_db', publiclyAccessible: props.publiclyAccessible || false, // Encryption - kmsKeyId: props.encryptionKey && props.encryptionKey.keyArn, + kmsKeyId: props.encryptionKey?.keyId, encrypted: props.encrypted ?? true, }); diff --git a/packages/@aws-cdk/aws-redshift/test/cluster.test.ts b/packages/@aws-cdk/aws-redshift/test/cluster.test.ts index a1091815a30c1..d771e8e66b0de 100644 --- a/packages/@aws-cdk/aws-redshift/test/cluster.test.ts +++ b/packages/@aws-cdk/aws-redshift/test/cluster.test.ts @@ -249,10 +249,7 @@ test('create an encrypted cluster with custom KMS key', () => { // THEN Template.fromStack(stack).hasResourceProperties('AWS::Redshift::Cluster', { KmsKeyId: { - 'Fn::GetAtt': [ - 'Key961B73FD', - 'Arn', - ], + Ref: 'Key961B73FD', }, }); }); diff --git a/packages/@aws-cdk/aws-redshift/test/integ.database.expected.json b/packages/@aws-cdk/aws-redshift/test/integ.database.expected.json index 16d60bb08c0d0..4cfb1faea5118 100644 --- a/packages/@aws-cdk/aws-redshift/test/integ.database.expected.json +++ b/packages/@aws-cdk/aws-redshift/test/integ.database.expected.json @@ -580,6 +580,41 @@ "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" }, + "customkmskey377C6F9A": { + "Type": "AWS::KMS::Key", + "Properties": { + "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": "Delete", + "DeletionPolicy": "Delete" + }, "ClusterSubnetsDCFA5CB7": { "Type": "AWS::Redshift::ClusterSubnetGroup", "Properties": { @@ -680,6 +715,9 @@ "Ref": "ClusterSubnetsDCFA5CB7" }, "Encrypted": true, + "KmsKeyId": { + "Ref": "customkmskey377C6F9A" + }, "NumberOfNodes": 2, "PubliclyAccessible": true, "VpcSecurityGroupIds": [ diff --git a/packages/@aws-cdk/aws-redshift/test/integ.database.ts b/packages/@aws-cdk/aws-redshift/test/integ.database.ts index 3a3b955a2b5aa..6e4893c0c0089 100644 --- a/packages/@aws-cdk/aws-redshift/test/integ.database.ts +++ b/packages/@aws-cdk/aws-redshift/test/integ.database.ts @@ -1,6 +1,7 @@ #!/usr/bin/env node /// !cdk-integ pragma:ignore-assets import * as ec2 from '@aws-cdk/aws-ec2'; +import * as kms from '@aws-cdk/aws-kms'; import * as cdk from '@aws-cdk/core'; import * as constructs from 'constructs'; import * as redshift from '../lib'; @@ -28,6 +29,7 @@ const cluster = new redshift.Cluster(stack, 'Cluster', { }, defaultDatabaseName: databaseName, publiclyAccessible: true, + encryptionKey: new kms.Key(stack, 'custom-kms-key'), }); const databaseOptions = { From 3eab4279f7fbd7ce4ec9d99dd822dd8d30d22ca3 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Mon, 25 Oct 2021 21:58:56 +0200 Subject: [PATCH 29/87] chore(cli): make integ tests v2-aware (#17122) Integ tests for v2 requires installing different packages and switching off some tests that don't make sense. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/aws-cdk/test/integ/cli/app/app.js | 49 ++++-- .../test/integ/cli/app/nested-stack.js | 14 +- .../test/integ/cli/bootstrapping.integtest.ts | 39 +++-- .../aws-cdk/test/integ/cli/cli.integtest.ts | 155 +++++++++--------- packages/aws-cdk/test/integ/helpers/cdk.ts | 49 ++++-- .../aws-cdk/test/integ/run-against-dist.bash | 2 + 6 files changed, 183 insertions(+), 125 deletions(-) diff --git a/packages/aws-cdk/test/integ/cli/app/app.js b/packages/aws-cdk/test/integ/cli/app/app.js index 205d7014503dc..450662ac268e0 100644 --- a/packages/aws-cdk/test/integ/cli/app/app.js +++ b/packages/aws-cdk/test/integ/cli/app/app.js @@ -1,14 +1,28 @@ const path = require('path'); -const cdk = require('@aws-cdk/core'); -const ec2 = require('@aws-cdk/aws-ec2'); -const ssm = require('@aws-cdk/aws-ssm'); -const iam = require('@aws-cdk/aws-iam'); -const sns = require('@aws-cdk/aws-sns'); -const lambda = require('@aws-cdk/aws-lambda'); -const docker = require('@aws-cdk/aws-ecr-assets'); -const core = require('@aws-cdk/core') + +var constructs = require('constructs'); +if (process.env.PACKAGE_LAYOUT_VERSION === '1') { + var cdk = require('@aws-cdk/core'); + var ec2 = require('@aws-cdk/aws-ec2'); + var ssm = require('@aws-cdk/aws-ssm'); + var iam = require('@aws-cdk/aws-iam'); + var sns = require('@aws-cdk/aws-sns'); + var lambda = require('@aws-cdk/aws-lambda'); + var docker = require('@aws-cdk/aws-ecr-assets'); +} else { + var cdk = require('aws-cdk-lib'); + var { + aws_ec2: ec2, + aws_ssm: ssm, + aws_iam: iam, + aws_sns: sns, + aws_lambda: lambda, + aws_ecr_assets: docker + } = require('aws-cdk-lib'); +} + +const { Annotations } = cdk; const { StackWithNestedStack, StackWithNestedStackUsingParameters } = require('./nested-stack'); -const { Annotations } = require('@aws-cdk/core'); const stackPrefix = process.env.STACK_NAME_PREFIX; if (!stackPrefix) { @@ -48,11 +62,11 @@ class YourStack extends cdk.Stack { class StackUsingContext extends cdk.Stack { constructor(parent, id, props) { super(parent, id, props); - new core.CfnResource(this, 'Handle', { + new cdk.CfnResource(this, 'Handle', { type: 'AWS::CloudFormation::WaitConditionHandle' }); - new core.CfnOutput(this, 'Output', { + new cdk.CfnOutput(this, 'Output', { value: this.availabilityZones, }); } @@ -167,7 +181,7 @@ class MissingSSMParameterStack extends cdk.Stack { constructor(parent, id, props) { super(parent, id, props); - const parameterName = this.node.tryGetContext('test:ssm-parameter-name'); + const parameterName = constructs.Node.of(this).tryGetContext('test:ssm-parameter-name'); if (parameterName) { const param = getSsmParameterValue(this, parameterName); new iam.Role(this, 'PhonyRole', { assumedBy: new iam.AccountPrincipal(param) }); @@ -199,7 +213,7 @@ class DockerStack extends cdk.Stack { // Add at least a single resource (WaitConditionHandle), otherwise this stack will never // be deployed (and its assets never built) - new core.CfnResource(this, 'Handle', { + new cdk.CfnResource(this, 'Handle', { type: 'AWS::CloudFormation::WaitConditionHandle' }); } @@ -216,7 +230,7 @@ class DockerStackWithCustomFile extends cdk.Stack { // Add at least a single resource (WaitConditionHandle), otherwise this stack will never // be deployed (and its assets never built) - new core.CfnResource(this, 'Handle', { + new cdk.CfnResource(this, 'Handle', { type: 'AWS::CloudFormation::WaitConditionHandle' }); } @@ -228,7 +242,7 @@ class FailedStack extends cdk.Stack { super(parent, id, props); // fails on 'Property PolicyDocument cannot be empty'. - new core.CfnResource(this, 'EmptyPolicy', { + new cdk.CfnResource(this, 'EmptyPolicy', { type: 'AWS::IAM::Policy' }) @@ -243,9 +257,10 @@ class DefineVpcStack extends cdk.Stack { constructor(parent, id, props) { super(parent, id, props); - new ec2.Vpc(this, 'VPC', { + const vpc = new ec2.Vpc(this, 'VPC', { maxAzs: 1, - }).node.applyAspect(new cdk.Tag(VPC_TAG_NAME, VPC_TAG_VALUE)); + }) + cdk.Aspects.of(vpc).add(new cdk.Tag(VPC_TAG_NAME, VPC_TAG_VALUE)); } } diff --git a/packages/aws-cdk/test/integ/cli/app/nested-stack.js b/packages/aws-cdk/test/integ/cli/app/nested-stack.js index 3b3125963679b..87a45bb64b036 100644 --- a/packages/aws-cdk/test/integ/cli/app/nested-stack.js +++ b/packages/aws-cdk/test/integ/cli/app/nested-stack.js @@ -1,6 +1,14 @@ -const cfn = require('@aws-cdk/aws-cloudformation'); -const sns = require('@aws-cdk/aws-sns'); -const { Stack, CfnParameter } = require('@aws-cdk/core'); +if (process.env.PACKAGE_LAYOUT_VERSION === '1') { + var cfn = require('@aws-cdk/aws-cloudformation'); + var sns = require('@aws-cdk/aws-sns'); + var { Stack, CfnParameter } = require('@aws-cdk/core'); +} else { + var { + aws_cloudformation: cfn, + aws_sns: sns, + } = require('aws-cdk-lib'); + var { Stack, CfnParameter } = require('aws-cdk-lib'); +} class StackWithNestedStack extends Stack { constructor(scope, id) { diff --git a/packages/aws-cdk/test/integ/cli/bootstrapping.integtest.ts b/packages/aws-cdk/test/integ/cli/bootstrapping.integtest.ts index 6fce054dbbf10..d7716a2ac3e70 100644 --- a/packages/aws-cdk/test/integ/cli/bootstrapping.integtest.ts +++ b/packages/aws-cdk/test/integ/cli/bootstrapping.integtest.ts @@ -1,6 +1,6 @@ import * as fs from 'fs'; import * as path from 'path'; -import { randomString, withDefaultFixture } from '../helpers/cdk'; +import { MAJOR_VERSION, randomString, withDefaultFixture } from '../helpers/cdk'; import { integTest } from '../helpers/test-helpers'; const timeout = process.env.CODEBUILD_BUILD_ID ? // if the process is running in CodeBuild @@ -129,22 +129,27 @@ integTest('deploy old style synthesis to new style bootstrap', withDefaultFixtur }); })); -integTest('deploying new style synthesis to old style bootstrap fails', withDefaultFixture(async (fixture) => { - const bootstrapStackName = fixture.bootstrapStackName; - - await fixture.cdkBootstrapLegacy({ - toolkitStackName: bootstrapStackName, - }); - - // Deploy stack that uses file assets, this fails because the bootstrap stack - // is version checked. - await expect(fixture.cdkDeploy('lambda', { - options: [ - '--toolkit-stack-name', bootstrapStackName, - '--context', '@aws-cdk/core:newStyleStackSynthesis=1', - ], - })).rejects.toThrow('exited with error'); -})); +if (MAJOR_VERSION === '1') { + // For v2, the default bootstrap is the modern bootstrap, so this test is predicated on invalid + // assumptions. + + integTest('deploying new style synthesis to old style bootstrap fails', withDefaultFixture(async (fixture) => { + const bootstrapStackName = fixture.bootstrapStackName; + + await fixture.cdkBootstrapLegacy({ + toolkitStackName: bootstrapStackName, + }); + + // Deploy stack that uses file assets, this fails because the bootstrap stack + // is version checked. + await expect(fixture.cdkDeploy('lambda', { + options: [ + '--toolkit-stack-name', bootstrapStackName, + '--context', '@aws-cdk/core:newStyleStackSynthesis=1', + ], + })).rejects.toThrow('exited with error'); + })); +} integTest('can create a legacy bootstrap stack with --public-access-block-configuration=false', withDefaultFixture(async (fixture) => { const bootstrapStackName = fixture.bootstrapStackName; diff --git a/packages/aws-cdk/test/integ/cli/cli.integtest.ts b/packages/aws-cdk/test/integ/cli/cli.integtest.ts index 873e3a1787ee5..127734a136491 100644 --- a/packages/aws-cdk/test/integ/cli/cli.integtest.ts +++ b/packages/aws-cdk/test/integ/cli/cli.integtest.ts @@ -2,7 +2,7 @@ import { promises as fs } from 'fs'; import * as os from 'os'; import * as path from 'path'; import { retry, sleep } from '../helpers/aws'; -import { cloneDirectory, shell, withDefaultFixture } from '../helpers/cdk'; +import { cloneDirectory, MAJOR_VERSION, shell, withDefaultFixture } from '../helpers/cdk'; import { integTest } from '../helpers/test-helpers'; jest.setTimeout(600 * 1000); @@ -40,7 +40,7 @@ integTest('Termination protection', withDefaultFixture(async (fixture) => { integTest('cdk synth', withDefaultFixture(async (fixture) => { await fixture.cdk(['synth', fixture.fullStackName('test-1')]); - expect(fixture.template('test-1')).toEqual({ + expect(fixture.template('test-1')).toEqual(expect.objectContaining({ Resources: { topic69831491: { Type: 'AWS::SNS::Topic', @@ -49,10 +49,10 @@ integTest('cdk synth', withDefaultFixture(async (fixture) => { }, }, }, - }); + })); await fixture.cdk(['synth', fixture.fullStackName('test-2')], { verbose: false }); - expect(fixture.template('test-2')).toEqual({ + expect(fixture.template('test-2')).toEqual(expect.objectContaining({ Resources: { topic152D84A37: { Type: 'AWS::SNS::Topic', @@ -67,8 +67,7 @@ integTest('cdk synth', withDefaultFixture(async (fixture) => { }, }, }, - }); - + })); })); integTest('ssm parameter provider error', withDefaultFixture(async (fixture) => { @@ -223,12 +222,12 @@ integTest('deploy with parameters', withDefaultFixture(async (fixture) => { StackName: stackArn, }); - expect(response.Stacks?.[0].Parameters).toEqual([ + expect(response.Stacks?.[0].Parameters).toContainEqual( { ParameterKey: 'TopicNameParam', ParameterValue: `${fixture.stackNamePrefix}bazinga`, }, - ]); + ); })); integTest('update to stack in ROLLBACK_COMPLETE state will delete stack and create a new one', withDefaultFixture(async (fixture) => { @@ -262,12 +261,12 @@ integTest('update to stack in ROLLBACK_COMPLETE state will delete stack and crea // THEN expect (stackArn).not.toEqual(newStackArn); // new stack was created expect(newStackResponse.Stacks?.[0].StackStatus).toEqual('CREATE_COMPLETE'); - expect(newStackResponse.Stacks?.[0].Parameters).toEqual([ + expect(newStackResponse.Stacks?.[0].Parameters).toContainEqual( { ParameterKey: 'TopicNameParam', ParameterValue: `${fixture.stackNamePrefix}allgood`, }, - ]); + ); })); integTest('stack in UPDATE_ROLLBACK_COMPLETE state can be updated', withDefaultFixture(async (fixture) => { @@ -313,12 +312,12 @@ integTest('stack in UPDATE_ROLLBACK_COMPLETE state can be updated', withDefaultF // THEN expect(response.Stacks?.[0].StackStatus).toEqual('UPDATE_COMPLETE'); - expect(response.Stacks?.[0].Parameters).toEqual([ + expect(response.Stacks?.[0].Parameters).toContainEqual( { ParameterKey: 'TopicNameParam', ParameterValue: `${fixture.stackNamePrefix}allgood`, }, - ]); + ); })); integTest('deploy with wildcard and parameters', withDefaultFixture(async (fixture) => { @@ -348,16 +347,18 @@ integTest('deploy with parameters multi', withDefaultFixture(async (fixture) => StackName: stackArn, }); - expect(response.Stacks?.[0].Parameters).toEqual([ + expect(response.Stacks?.[0].Parameters).toContainEqual( { ParameterKey: 'DisplayNameParam', ParameterValue: paramVal1, }, + ); + expect(response.Stacks?.[0].Parameters).toContainEqual( { ParameterKey: 'OtherDisplayNameParam', ParameterValue: paramVal2, }, - ]); + ); })); integTest('deploy with notification ARN', withDefaultFixture(async (fixture) => { @@ -382,82 +383,86 @@ integTest('deploy with notification ARN', withDefaultFixture(async (fixture) => } })); -integTest('deploy with role', withDefaultFixture(async (fixture) => { - const roleName = `${fixture.stackNamePrefix}-test-role`; - - await deleteRole(); - - const createResponse = await fixture.aws.iam('createRole', { - RoleName: roleName, - AssumeRolePolicyDocument: JSON.stringify({ - Version: '2012-10-17', - Statement: [{ - Action: 'sts:AssumeRole', - Principal: { Service: 'cloudformation.amazonaws.com' }, - Effect: 'Allow', - }, { - Action: 'sts:AssumeRole', - Principal: { AWS: (await fixture.aws.sts('getCallerIdentity', {})).Arn }, - Effect: 'Allow', - }], - }), - }); - const roleArn = createResponse.Role.Arn; - try { - await fixture.aws.iam('putRolePolicy', { +if (MAJOR_VERSION === '1') { + // NOTE: this doesn't currently work with modern-style synthesis, as the bootstrap + // role by default will not have permission to iam:PassRole the created role. + integTest('deploy with role', withDefaultFixture(async (fixture) => { + const roleName = `${fixture.stackNamePrefix}-test-role`; + + await deleteRole(); + + const createResponse = await fixture.aws.iam('createRole', { RoleName: roleName, - PolicyName: 'DefaultPolicy', - PolicyDocument: JSON.stringify({ + AssumeRolePolicyDocument: JSON.stringify({ Version: '2012-10-17', Statement: [{ - Action: '*', - Resource: '*', + Action: 'sts:AssumeRole', + Principal: { Service: 'cloudformation.amazonaws.com' }, + Effect: 'Allow', + }, { + Action: 'sts:AssumeRole', + Principal: { AWS: (await fixture.aws.sts('getCallerIdentity', {})).Arn }, Effect: 'Allow', }], }), }); + const roleArn = createResponse.Role.Arn; + try { + await fixture.aws.iam('putRolePolicy', { + RoleName: roleName, + PolicyName: 'DefaultPolicy', + PolicyDocument: JSON.stringify({ + Version: '2012-10-17', + Statement: [{ + Action: '*', + Resource: '*', + Effect: 'Allow', + }], + }), + }); - await retry(fixture.output, 'Trying to assume fresh role', retry.forSeconds(300), async () => { - await fixture.aws.sts('assumeRole', { - RoleArn: roleArn, - RoleSessionName: 'testing', + await retry(fixture.output, 'Trying to assume fresh role', retry.forSeconds(300), async () => { + await fixture.aws.sts('assumeRole', { + RoleArn: roleArn, + RoleSessionName: 'testing', + }); }); - }); - // In principle, the role has replicated from 'us-east-1' to wherever we're testing. - // Give it a little more sleep to make sure CloudFormation is not hitting a box - // that doesn't have it yet. - await sleep(5000); + // In principle, the role has replicated from 'us-east-1' to wherever we're testing. + // Give it a little more sleep to make sure CloudFormation is not hitting a box + // that doesn't have it yet. + await sleep(5000); - await fixture.cdkDeploy('test-2', { - options: ['--role-arn', roleArn], - }); + await fixture.cdkDeploy('test-2', { + options: ['--role-arn', roleArn], + }); - // Immediately delete the stack again before we delete the role. - // - // Since roles are sticky, if we delete the role before the stack, subsequent DeleteStack - // operations will fail when CloudFormation tries to assume the role that's already gone. - await fixture.cdkDestroy('test-2'); + // Immediately delete the stack again before we delete the role. + // + // Since roles are sticky, if we delete the role before the stack, subsequent DeleteStack + // operations will fail when CloudFormation tries to assume the role that's already gone. + await fixture.cdkDestroy('test-2'); - } finally { - await deleteRole(); - } + } finally { + await deleteRole(); + } - async function deleteRole() { - try { - for (const policyName of (await fixture.aws.iam('listRolePolicies', { RoleName: roleName })).PolicyNames) { - await fixture.aws.iam('deleteRolePolicy', { - RoleName: roleName, - PolicyName: policyName, - }); + async function deleteRole() { + try { + for (const policyName of (await fixture.aws.iam('listRolePolicies', { RoleName: roleName })).PolicyNames) { + await fixture.aws.iam('deleteRolePolicy', { + RoleName: roleName, + PolicyName: policyName, + }); + } + await fixture.aws.iam('deleteRole', { RoleName: roleName }); + } catch (e) { + if (e.message.indexOf('cannot be found') > -1) { return; } + throw e; } - await fixture.aws.iam('deleteRole', { RoleName: roleName }); - } catch (e) { - if (e.message.indexOf('cannot be found') > -1) { return; } - throw e; } - } -})); + })); +} integTest('cdk diff', withDefaultFixture(async (fixture) => { const diff1 = await fixture.cdk(['diff', fixture.fullStackName('test-1')]); @@ -734,7 +739,7 @@ integTest('templates on disk contain metadata resource, also in nested assemblie expect(JSON.parse(templateContents).Resources.CDKMetadata).toBeTruthy(); // Load template from nested assembly - const nestedTemplateContents = await fixture.shell(['cat', 'cdk.out/assembly-*-stage/*-stage-StackInStage.template.json']); + const nestedTemplateContents = await fixture.shell(['cat', 'cdk.out/assembly-*-stage/*StackInStage*.template.json']); expect(JSON.parse(nestedTemplateContents).Resources.CDKMetadata).toBeTruthy(); })); diff --git a/packages/aws-cdk/test/integ/helpers/cdk.ts b/packages/aws-cdk/test/integ/helpers/cdk.ts index 4a09f43063600..edf996ba36ed6 100644 --- a/packages/aws-cdk/test/integ/helpers/cdk.ts +++ b/packages/aws-cdk/test/integ/helpers/cdk.ts @@ -12,10 +12,23 @@ const REGIONS = process.env.AWS_REGIONS ? process.env.AWS_REGIONS.split(',') : [process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION ?? 'us-east-1']; -const FRAMEWORK_VERSION = process.env.FRAMEWORK_VERSION; +const FRAMEWORK_VERSION = process.env.FRAMEWORK_VERSION ?? '*'; + +export let MAJOR_VERSION = FRAMEWORK_VERSION.split('.')[0]; +if (MAJOR_VERSION === '*') { + if (process.env.REPO_ROOT) { + // eslint-disable-next-line @typescript-eslint/no-require-imports + const releaseJson = require(path.resolve(process.env.REPO_ROOT, 'release.json')); + MAJOR_VERSION = `${releaseJson.majorVersion}`; + } else { + // eslint-disable-next-line no-console + console.error('[WARNING] Have to guess at major version. Guessing version 1 to not break anything, but this should not happen'); + MAJOR_VERSION = '1'; + } +} process.stdout.write(`Using regions: ${REGIONS}\n`); -process.stdout.write(`Using framework version: ${FRAMEWORK_VERSION}\n`); +process.stdout.write(`Using framework version: ${FRAMEWORK_VERSION} (major version ${MAJOR_VERSION})\n`); const REGION_POOL = new ResourcePool(REGIONS); @@ -63,17 +76,26 @@ export function withCdkApp(block: (context: let success = true; try { - const version = FRAMEWORK_VERSION ?? '*'; - await installNpmPackages(fixture, { - '@aws-cdk/core': version, - '@aws-cdk/aws-sns': version, - '@aws-cdk/aws-iam': version, - '@aws-cdk/aws-lambda': version, - '@aws-cdk/aws-ssm': version, - '@aws-cdk/aws-ecr-assets': version, - '@aws-cdk/aws-cloudformation': version, - '@aws-cdk/aws-ec2': version, - }); + const installationVersion = FRAMEWORK_VERSION; + + if (MAJOR_VERSION === '1') { + await installNpmPackages(fixture, { + '@aws-cdk/core': installationVersion, + '@aws-cdk/aws-sns': installationVersion, + '@aws-cdk/aws-iam': installationVersion, + '@aws-cdk/aws-lambda': installationVersion, + '@aws-cdk/aws-ssm': installationVersion, + '@aws-cdk/aws-ecr-assets': installationVersion, + '@aws-cdk/aws-cloudformation': installationVersion, + '@aws-cdk/aws-ec2': installationVersion, + 'constructs': '^3', + }); + } else { + await installNpmPackages(fixture, { + 'aws-cdk-lib': installationVersion, + 'constructs': '^10', + }); + } await ensureBootstrapped(fixture); @@ -377,6 +399,7 @@ export class TestFixture { AWS_REGION: this.aws.region, AWS_DEFAULT_REGION: this.aws.region, STACK_NAME_PREFIX: this.stackNamePrefix, + PACKAGE_LAYOUT_VERSION: MAJOR_VERSION, ...options.modEnv, }, }); diff --git a/packages/aws-cdk/test/integ/run-against-dist.bash b/packages/aws-cdk/test/integ/run-against-dist.bash index 0d5dc245df5e7..84162031f5068 100644 --- a/packages/aws-cdk/test/integ/run-against-dist.bash +++ b/packages/aws-cdk/test/integ/run-against-dist.bash @@ -4,6 +4,8 @@ npmws=/tmp/cdk-rundist rm -rf $npmws mkdir -p $npmws +set -x + # This script must create 1 or 2 traps, and the 'trap' command will replace # the previous trap, so get some 'dynamic traps' mechanism in place TRAPS=() From c36c73fa428a302af412d8bbb8ef30f746ba2ec8 Mon Sep 17 00:00:00 2001 From: kaizen3031593 <36202692+kaizen3031593@users.noreply.github.com> Date: Mon, 25 Oct 2021 16:52:08 -0400 Subject: [PATCH 30/87] docs(stepfunctions-tasks): make examples compile (#17143) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../aws-stepfunctions-tasks/README.md | 100 ++++++++++-------- .../lib/sagemaker/base-types.ts | 8 +- .../rosetta/default.ts-fixture | 24 +---- .../rosetta/with-batch-job.ts-fixture | 38 ------- 4 files changed, 64 insertions(+), 106 deletions(-) delete mode 100644 packages/@aws-cdk/aws-stepfunctions-tasks/rosetta/with-batch-job.ts-fixture diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/README.md b/packages/@aws-cdk/aws-stepfunctions-tasks/README.md index a0f47ee7519c1..cedf89eefe07c 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/README.md +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/README.md @@ -110,9 +110,10 @@ The following example provides the field named `input` as the input to the `Task state that runs a Lambda function. ```ts +declare const fn: lambda.Function; const submitJob = new tasks.LambdaInvoke(this, 'Invoke Handler', { lambdaFunction: fn, - inputPath: '$.input' + inputPath: '$.input', }); ``` @@ -130,9 +131,10 @@ as well as other metadata. The following example assigns the output from the Task to a field named `result` ```ts +declare const fn: lambda.Function; const submitJob = new tasks.LambdaInvoke(this, 'Invoke Handler', { lambdaFunction: fn, - outputPath: '$.Payload.result' + outputPath: '$.Payload.result', }); ``` @@ -149,6 +151,7 @@ The following example extracts the output payload of a Lambda function Task and it with some static values and the state name from the context object. ```ts +declare const fn: lambda.Function; new tasks.LambdaInvoke(this, 'Invoke Handler', { lambdaFunction: fn, resultSelector: { @@ -159,7 +162,7 @@ new tasks.LambdaInvoke(this, 'Invoke Handler', { }, stateName: sfn.JsonPath.stringAt('$$.State.Name'), }, -}) +}); ``` ### ResultPath @@ -174,9 +177,10 @@ The following example adds the item from calling DynamoDB's `getItem` API to the input and passes it to the next state. ```ts +declare const myTable: dynamodb.Table; new tasks.DynamoPutItem(this, 'PutItem', { item: { - MessageId: tasks.DynamoAttributeValue.fromString('message-id') + MessageId: tasks.DynamoAttributeValue.fromString('message-id'), }, table: myTable, resultPath: `$.Item`, @@ -199,6 +203,7 @@ The following example provides the field named `input` as the input to the Lambd and invokes it asynchronously. ```ts +declare const fn: lambda.Function; const submitJob = new tasks.LambdaInvoke(this, 'Invoke Handler', { lambdaFunction: fn, payload: sfn.TaskInput.fromJsonPathAt('$.input'), @@ -258,14 +263,14 @@ const publishMessage = new tasks.SnsPublish(this, 'Publish message', { }); const wait = new sfn.Wait(this, 'Wait', { - time: sfn.WaitTime.secondsPath('$.waitSeconds') + time: sfn.WaitTime.secondsPath('$.waitSeconds'), }); new sfn.StateMachine(this, 'StateMachine', { definition: convertToSeconds .next(createMessage) .next(publishMessage) - .next(wait) + .next(wait), }); ``` @@ -286,15 +291,13 @@ Previous-generation REST APIs currently offer more features. More details can be The `CallApiGatewayRestApiEndpoint` calls the REST API endpoint. ```ts -import * as sfn from '@aws-cdk/aws-stepfunctions'; -import * as tasks from `@aws-cdk/aws-stepfunctions-tasks`; - -const restApi = new apigateway.RestApi(stack, 'MyRestApi'); +import * as apigateway from '@aws-cdk/aws-apigateway'; +const restApi = new apigateway.RestApi(this, 'MyRestApi'); -const invokeTask = new tasks.CallApiGatewayRestApiEndpoint(stack, 'Call REST API', { +const invokeTask = new tasks.CallApiGatewayRestApiEndpoint(this, 'Call REST API', { api: restApi, stageName: 'prod', - method: HttpMethod.GET, + method: tasks.HttpMethod.GET, }); ``` @@ -303,15 +306,13 @@ const invokeTask = new tasks.CallApiGatewayRestApiEndpoint(stack, 'Call REST API The `CallApiGatewayHttpApiEndpoint` calls the HTTP API endpoint. ```ts -import * as sfn from '@aws-cdk/aws-stepfunctions'; -import * as tasks from `@aws-cdk/aws-stepfunctions-tasks`; - -const httpApi = new apigatewayv2.HttpApi(stack, 'MyHttpApi'); +import * as apigatewayv2 from '@aws-cdk/aws-apigatewayv2'; +const httpApi = new apigatewayv2.HttpApi(this, 'MyHttpApi'); -const invokeTask = new tasks.CallApiGatewayHttpApiEndpoint(stack, 'Call HTTP API', { +const invokeTask = new tasks.CallApiGatewayHttpApiEndpoint(this, 'Call HTTP API', { apiId: httpApi.apiId, - apiStack: cdk.Stack.of(httpApi), - method: HttpMethod.GET, + apiStack: Stack.of(httpApi), + method: tasks.HttpMethod.GET, }); ``` @@ -324,6 +325,7 @@ You can use Step Functions' AWS SDK integrations to call any of the over two hun directly from your state machine, giving you access to over nine thousand API actions. ```ts +declare const myBucket: s3.Bucket; const getObject = new tasks.CallAwsService(this, 'GetObject', { service: 's3', action: 'getObject', @@ -348,7 +350,7 @@ const listBuckets = new tasks.CallAwsService(this, 'ListBuckets', { service: 's3', action: 'ListBuckets', iamResources: ['*'], - iamAction: 's3:ListAllMyBuckets' + iamAction: 's3:ListAllMyBuckets', }); ``` @@ -416,11 +418,15 @@ Step Functions supports [Batch](https://docs.aws.amazon.com/step-functions/lates The [SubmitJob](https://docs.aws.amazon.com/batch/latest/APIReference/API_SubmitJob.html) API submits an AWS Batch job from a job definition. -```ts fixture=with-batch-job +```ts +import * as batch from '@aws-cdk/aws-batch'; +declare const batchJobDefinition: batch.JobDefinition; +declare const batchQueue: batch.JobQueue; + const task = new tasks.BatchSubmitJob(this, 'Submit Job', { - jobDefinitionArn: batchJobDefinitionArn, + jobDefinitionArn: batchJobDefinition.jobDefinitionArn, jobName: 'MyJob', - jobQueueArn: batchQueueArn, + jobQueueArn: batchQueue.jobQueueArn, }); ``` @@ -471,6 +477,7 @@ Read more about calling DynamoDB APIs [here](https://docs.aws.amazon.com/step-fu The [GetItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_GetItem.html) operation returns a set of attributes for the item with the given primary key. ```ts +declare const myTable: dynamodb.Table; new tasks.DynamoGetItem(this, 'Get Item', { key: { messageId: tasks.DynamoAttributeValue.fromString('message-007') }, table: myTable, @@ -482,6 +489,7 @@ new tasks.DynamoGetItem(this, 'Get Item', { The [PutItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html) operation creates a new item, or replaces an old item with a new item. ```ts +declare const myTable: dynamodb.Table; new tasks.DynamoPutItem(this, 'PutItem', { item: { MessageId: tasks.DynamoAttributeValue.fromString('message-007'), @@ -497,6 +505,7 @@ new tasks.DynamoPutItem(this, 'PutItem', { The [DeleteItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DeleteItem.html) operation deletes a single item in a table by primary key. ```ts +declare const myTable: dynamodb.Table; new tasks.DynamoDeleteItem(this, 'DeleteItem', { key: { MessageId: tasks.DynamoAttributeValue.fromString('message-007') }, table: myTable, @@ -510,6 +519,7 @@ The [UpdateItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/ to the table if it does not already exist. ```ts +declare const myTable: dynamodb.Table; new tasks.DynamoUpdateItem(this, 'UpdateItem', { key: { MessageId: tasks.DynamoAttributeValue.fromString('message-007') @@ -547,8 +557,6 @@ The latest ACTIVE revision of the passed task definition is used for running the The following example runs a job from a task definition on EC2 ```ts -import * as ecs from '@aws-cdk/aws-ecs'; - const vpc = ec2.Vpc.fromLookup(this, 'Vpc', { isDefault: true, }); @@ -579,7 +587,7 @@ const runTask = new tasks.EcsRunTask(this, 'Run', { ecs.PlacementStrategy.randomly(), ], placementConstraints: [ - ecs.PlacementConstraint.memberOf('blieptuut') + ecs.PlacementConstraint.memberOf('blieptuut'), ], }), }); @@ -602,8 +610,6 @@ task definition is used for running the task. Learn more about The following example runs a job from a task definition on Fargate ```ts -import * as ecs from '@aws-cdk/aws-ecs'; - const vpc = ec2.Vpc.fromLookup(this, 'Vpc', { isDefault: true, }); @@ -648,7 +654,6 @@ Creates and starts running a cluster (job flow). Corresponds to the [`runJobFlow`](https://docs.aws.amazon.com/emr/latest/APIReference/API_RunJobFlow.html) API in EMR. ```ts - const clusterRole = new iam.Role(this, 'ClusterRole', { assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'), }); @@ -689,7 +694,8 @@ and 256 inclusive, where the default concurrency of 1 means no step concurrency ```ts new tasks.EmrCreateCluster(this, 'Create Cluster', { - // ... + instances: {}, + name: sfn.TaskInput.fromJsonPathAt('$.ClusterName').value, stepConcurrencyLevel: 10, }); ``` @@ -715,7 +721,7 @@ Corresponds to the [`terminateJobFlows`](https://docs.aws.amazon.com/emr/latest/ ```ts new tasks.EmrTerminateCluster(this, 'Task', { - clusterId: 'ClusterId' + clusterId: 'ClusterId', }); ``` @@ -793,17 +799,15 @@ The following code snippet includes a Task state that uses eks:call to list the ```ts import * as eks from '@aws-cdk/aws-eks'; -import * as sfn from '@aws-cdk/aws-stepfunctions'; -import * as tasks from '@aws-cdk/aws-stepfunctions-tasks'; const myEksCluster = new eks.Cluster(this, 'my sample cluster', { version: eks.KubernetesVersion.V1_18, clusterName: 'myEksCluster', }); -new tasks.EksCall(stack, 'Call a EKS Endpoint', { +new tasks.EksCall(this, 'Call a EKS Endpoint', { cluster: myEksCluster, - httpMethod: MethodType.GET, + httpMethod: tasks.HttpMethods.GET, httpPath: '/api/v1/namespaces/default/pods', }); ``` @@ -824,14 +828,12 @@ The following code snippet includes a Task state that uses events:putevents to s ```ts import * as events from '@aws-cdk/aws-events'; -import * as sfn from '@aws-cdk/aws-stepfunctions'; -import * as tasks from '@aws-cdk/aws-stepfunctions-tasks'; -const myEventBus = events.EventBus(stack, 'EventBus', { +const myEventBus = new events.EventBus(this, 'EventBus', { eventBusName: 'MyEventBus1', }); -new tasks.EventBridgePutEvents(stack, 'Send an event to EventBridge', { +new tasks.EventBridgePutEvents(this, 'Send an event to EventBridge', { entries: [{ detail: sfn.TaskInput.fromObject({ Message: 'Hello from Step Functions!', @@ -855,8 +857,8 @@ new tasks.GlueStartJobRun(this, 'Task', { arguments: sfn.TaskInput.fromObject({ key: 'value', }), - timeout: cdk.Duration.minutes(30), - notifyDelayAfter: cdk.Duration.minutes(5), + timeout: Duration.minutes(30), + notifyDelayAfter: Duration.minutes(5), }); ``` @@ -884,6 +886,7 @@ The following snippet invokes a Lambda Function with the state input as the payl by referencing the `$` path. ```ts +declare const fn: lambda.Function; new tasks.LambdaInvoke(this, 'Invoke with state input', { lambdaFunction: fn, }); @@ -899,6 +902,7 @@ The following snippet invokes a Lambda Function by referencing the `$.Payload` p to reference the output of a Lambda executed before it. ```ts +declare const fn: lambda.Function; new tasks.LambdaInvoke(this, 'Invoke with empty object as payload', { lambdaFunction: fn, payload: sfn.TaskInput.fromObject({}), @@ -915,6 +919,7 @@ The following snippet invokes a Lambda and sets the task output to only include the Lambda function response. ```ts +declare const fn: lambda.Function; new tasks.LambdaInvoke(this, 'Invoke and set function response as task output', { lambdaFunction: fn, outputPath: '$.Payload', @@ -927,6 +932,7 @@ Lambda function ARN directly in the "Resource" string, but it conflicts with the integrationPattern, invocationType, clientContext, and qualifier properties. ```ts +declare const fn: lambda.Function; new tasks.LambdaInvoke(this, 'Invoke and combine function response with task input', { lambdaFunction: fn, payloadResponseOnly: true, @@ -945,6 +951,7 @@ The following snippet invokes a Lambda with the task token as part of the input to the Lambda. ```ts +declare const fn: lambda.Function; new tasks.LambdaInvoke(this, 'Invoke with callback', { lambdaFunction: fn, integrationPattern: sfn.IntegrationPattern.WAIT_FOR_TASK_TOKEN, @@ -998,11 +1005,11 @@ new tasks.SageMakerCreateTrainingJob(this, 'TrainSagemaker', { }, resourceConfig: { instanceCount: 1, - instanceType: new ec2.InstanceType(JsonPath.stringAt('$.InstanceType')), - volumeSize: cdk.Size.gibibytes(50), + instanceType: new ec2.InstanceType(sfn.JsonPath.stringAt('$.InstanceType')), + volumeSize: Size.gibibytes(50), }, // optional: default is 1 instance of EC2 `M4.XLarge` with `10GB` volume stoppingCondition: { - maxRuntime: cdk.Duration.hours(2), + maxRuntime: Duration.hours(2), }, // optional: default is 1 hour }); ``` @@ -1017,7 +1024,7 @@ new tasks.SageMakerCreateTransformJob(this, 'Batch Inference', { modelName: 'MyModelName', modelClientOptions: { invocationsMaxRetries: 3, // default is 0 - invocationsTimeout: cdk.Duration.minutes(5), // default is 60 seconds + invocationsTimeout: Duration.minutes(5), // default is 60 seconds }, transformInput: { transformDataSource: { @@ -1111,7 +1118,7 @@ const task1 = new tasks.SnsPublish(this, 'Publish1', { }, pic: { // BINARY must be explicitly set - type: MessageAttributeDataType.BINARY, + dataType: tasks.MessageAttributeDataType.BINARY, value: sfn.JsonPath.stringAt('$.pic'), }, people: { @@ -1170,6 +1177,7 @@ via the `associateWithParent` property. This allows the Step Functions UI to lin executions from parent executions, making it easier to trace execution flow across state machines. ```ts +declare const child: sfn.StateMachine; const task = new tasks.StepFunctionsStartExecution(this, 'ChildTask', { stateMachine: child, associateWithParent: true, diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/lib/sagemaker/base-types.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/lib/sagemaker/base-types.ts index 10c35d847ecd1..e11a04c111856 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/lib/sagemaker/base-types.ts +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/lib/sagemaker/base-types.ts @@ -206,8 +206,12 @@ export interface ResourceConfig { /** * ML compute instance type. * - * @example To provide an instance type from the task input, write - * `new ec2.InstanceType(sfn.JsonPath.stringAt('$.path.to.instanceType'))`, where the value in the task input is an EC2 instance type prepended with "ml.". + * To provide an instance type from the task input, supply an instance type in the following way + * where the value in the task input is an EC2 instance type prepended with "ml.": + * + * ```ts + * new ec2.InstanceType(sfn.JsonPath.stringAt('$.path.to.instanceType')); + * ``` * @see https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_ResourceConfig.html#sagemaker-Type-ResourceConfig-InstanceType * * @default ec2.InstanceType(ec2.InstanceClass.M4, ec2.InstanceType.XLARGE) diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/rosetta/default.ts-fixture b/packages/@aws-cdk/aws-stepfunctions-tasks/rosetta/default.ts-fixture index 11558a599e5f4..927b8e5fd6886 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/rosetta/default.ts-fixture +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/rosetta/default.ts-fixture @@ -1,8 +1,9 @@ // Fixture with packages imported, but nothing else -import * as cdk from '@aws-cdk/core'; +import { Duration, RemovalPolicy, Size, Stack } from '@aws-cdk/core'; import { Construct } from 'constructs'; -import * as ddb from '@aws-cdk/aws-dynamodb'; +import * as dynamodb from '@aws-cdk/aws-dynamodb'; import * as ec2 from '@aws-cdk/aws-ec2'; +import * as ecs from '@aws-cdk/aws-ecs'; import * as iam from '@aws-cdk/aws-iam'; import * as lambda from '@aws-cdk/aws-lambda'; import * as s3 from '@aws-cdk/aws-s3'; @@ -11,27 +12,10 @@ import * as sns from '@aws-cdk/aws-sns'; import * as sqs from '@aws-cdk/aws-sqs'; import * as tasks from '@aws-cdk/aws-stepfunctions-tasks'; -class Fixture extends cdk.Stack { +class Fixture extends Stack { constructor(scope: Construct, id: string) { super(scope, id); - const fn = new lambda.Function(this, 'lambdaFunction', { - code: lambda.Code.fromInline(`exports.handler = async () => { - return { "hello world"}; - `), - runtime: lambda.Runtime.NODEJS_12_X, - handler: 'index.handler', - }); - - const myTable = new ddb.Table(this, 'Messages', { - tableName: 'my-table', - partitionKey: { - name: 'MessageId', - type: ddb.AttributeType.STRING, - }, - removalPolicy: cdk.RemovalPolicy.DESTROY, - }); - /// here } } diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/rosetta/with-batch-job.ts-fixture b/packages/@aws-cdk/aws-stepfunctions-tasks/rosetta/with-batch-job.ts-fixture deleted file mode 100644 index 47672ba140841..0000000000000 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/rosetta/with-batch-job.ts-fixture +++ /dev/null @@ -1,38 +0,0 @@ -// Fixture with packages imported, but nothing else -import { Stack } from '@aws-cdk/core'; -import { Construct } from 'constructs'; -import * as sfn from '@aws-cdk/aws-stepfunctions'; -import * as tasks from '@aws-cdk/aws-stepfunctions-tasks'; -import * as batch from '@aws-cdk/aws-batch'; -import * as ec2 from '@aws-cdk/aws-ec2'; -import * as ecs from '@aws-cdk/aws-ecs'; -import * as path from 'path'; - -class Fixture extends Stack { - constructor(scope: Construct, id: string) { - super(scope, id); - - const vpc = ec2.Vpc.fromLookup(this, 'Vpc', { - isDefault: true, - }); - - const batchQueue = new batch.JobQueue(this, 'JobQueue', { - computeEnvironments: [ - { - order: 1, - computeEnvironment: new batch.ComputeEnvironment(this, 'ComputeEnv', { - computeResources: { vpc }, - }), - }, - ], - }); - - const batchJobDefinition = new batch.JobDefinition(this, 'JobDefinition', { - container: { - image: ecs.ContainerImage.fromAsset(path.resolve(__dirname, 'batchjob-image')), - }, - }); - - /// here - } -} From 8343beccbee06f453b63387f54768b320fe01339 Mon Sep 17 00:00:00 2001 From: Michael Sambol Date: Mon, 25 Oct 2021 14:45:10 -0700 Subject: [PATCH 31/87] feat(synthetics): add syn-nodejs-puppeteer-3.3 runtime (#17132) ---- *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-synthetics/README.md | 6 +- .../@aws-cdk/aws-synthetics/lib/runtime.ts | 10 ++ .../test/integ.canary.expected.json | 167 ++++++++++++++++++ .../aws-synthetics/test/integ.canary.ts | 10 ++ 4 files changed, 190 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk/aws-synthetics/README.md b/packages/@aws-cdk/aws-synthetics/README.md index ba0482d3aa263..7f7665e02238c 100644 --- a/packages/@aws-cdk/aws-synthetics/README.md +++ b/packages/@aws-cdk/aws-synthetics/README.md @@ -127,7 +127,7 @@ new synthetics.Canary(this, 'Inline Canary', { code: synthetics.Code.fromInline('/* Synthetics handler code */'), handler: 'index.handler', // must be 'index.handler' }), - runtime: synthetics.Runtime.SYNTHETICS_NODEJS_PUPPETEER_3_1, + runtime: synthetics.Runtime.SYNTHETICS_NODEJS_PUPPETEER_3_3, }); // To supply the code from your local filesystem: @@ -136,7 +136,7 @@ new synthetics.Canary(this, 'Asset Canary', { code: synthetics.Code.fromAsset(path.join(__dirname, 'canary')), handler: 'index.handler', // must end with '.handler' }), - runtime: synthetics.Runtime.SYNTHETICS_NODEJS_PUPPETEER_3_1, + runtime: synthetics.Runtime.SYNTHETICS_NODEJS_PUPPETEER_3_3, }); // To supply the code from a S3 bucket: @@ -147,7 +147,7 @@ new synthetics.Canary(this, 'Bucket Canary', { code: synthetics.Code.fromBucket(bucket, 'canary.zip'), handler: 'index.handler', // must end with '.handler' }), - runtime: synthetics.Runtime.SYNTHETICS_NODEJS_PUPPETEER_3_1, + runtime: synthetics.Runtime.SYNTHETICS_NODEJS_PUPPETEER_3_3, }); ``` diff --git a/packages/@aws-cdk/aws-synthetics/lib/runtime.ts b/packages/@aws-cdk/aws-synthetics/lib/runtime.ts index c710d68a34e35..81ac1a857e6db 100644 --- a/packages/@aws-cdk/aws-synthetics/lib/runtime.ts +++ b/packages/@aws-cdk/aws-synthetics/lib/runtime.ts @@ -104,6 +104,16 @@ export class Runtime { */ public static readonly SYNTHETICS_NODEJS_PUPPETEER_3_2 = new Runtime('syn-nodejs-puppeteer-3.2', RuntimeFamily.NODEJS); + /** + * `syn-nodejs-puppeteer-3.3` includes the following: + * - Lambda runtime Node.js 12.x + * - Puppeteer-core version 5.5.0 + * - Chromium version 88.0.4298.0 + * + * @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Synthetics_Library_nodejs_puppeteer.html#CloudWatch_Synthetics_runtimeversion-nodejs-puppeteer-3.3 + */ + public static readonly SYNTHETICS_NODEJS_PUPPETEER_3_3 = new Runtime('syn-nodejs-puppeteer-3.3', RuntimeFamily.NODEJS); + /** * `syn-python-selenium-1.0` includes the following: * - Lambda runtime Python 3.8 diff --git a/packages/@aws-cdk/aws-synthetics/test/integ.canary.expected.json b/packages/@aws-cdk/aws-synthetics/test/integ.canary.expected.json index 70d3908aa07f6..988973d8bfe78 100644 --- a/packages/@aws-cdk/aws-synthetics/test/integ.canary.expected.json +++ b/packages/@aws-cdk/aws-synthetics/test/integ.canary.expected.json @@ -456,6 +456,173 @@ "StartCanaryAfterCreation": true } }, + "MyCanaryThreeArtifactsBucket894E857E": { + "Type": "AWS::S3::Bucket", + "Properties": { + "BucketEncryption": { + "ServerSideEncryptionConfiguration": [ + { + "ServerSideEncryptionByDefault": { + "SSEAlgorithm": "aws:kms" + } + } + ] + } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "MyCanaryThreeServiceRole68117E65": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "Policies": [ + { + "PolicyDocument": { + "Statement": [ + { + "Action": "s3:ListAllMyBuckets", + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "s3:PutObject", + "s3:GetBucketLocation" + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "MyCanaryThreeArtifactsBucket894E857E", + "Arn" + ] + }, + "/*" + ] + ] + } + }, + { + "Action": "cloudwatch:PutMetricData", + "Condition": { + "StringEquals": { + "cloudwatch:namespace": "CloudWatchSynthetics" + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "logs:CreateLogStream", + "logs:CreateLogGroup", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:::*" + ] + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "canaryPolicy" + } + ] + } + }, + "MyCanaryThree968B1271": { + "Type": "AWS::Synthetics::Canary", + "Properties": { + "ArtifactS3Location": { + "Fn::Join": [ + "", + [ + "s3://", + { + "Ref": "MyCanaryThreeArtifactsBucket894E857E" + } + ] + ] + }, + "Code": { + "Handler": "canary.handler", + "S3Bucket": { + "Ref": "AssetParametersb1b777dcb79a2fa2790059927207d10bf5f4747d6dd1516e2780726d9d6fa820S3Bucket705C3761" + }, + "S3Key": { + "Fn::Join": [ + "", + [ + { + "Fn::Select": [ + 0, + { + "Fn::Split": [ + "||", + { + "Ref": "AssetParametersb1b777dcb79a2fa2790059927207d10bf5f4747d6dd1516e2780726d9d6fa820S3VersionKeyE546342B" + } + ] + } + ] + }, + { + "Fn::Select": [ + 1, + { + "Fn::Split": [ + "||", + { + "Ref": "AssetParametersb1b777dcb79a2fa2790059927207d10bf5f4747d6dd1516e2780726d9d6fa820S3VersionKeyE546342B" + } + ] + } + ] + } + ] + ] + } + }, + "ExecutionRoleArn": { + "Fn::GetAtt": [ + "MyCanaryThreeServiceRole68117E65", + "Arn" + ] + }, + "Name": "assetcanary-three", + "RuntimeVersion": "syn-nodejs-puppeteer-3.3", + "Schedule": { + "DurationInSeconds": "0", + "Expression": "rate(5 minutes)" + }, + "StartCanaryAfterCreation": true + } + }, "MyPythonCanaryArtifactsBucket7AE88133": { "Type": "AWS::S3::Bucket", "Properties": { diff --git a/packages/@aws-cdk/aws-synthetics/test/integ.canary.ts b/packages/@aws-cdk/aws-synthetics/test/integ.canary.ts index 54822badf1c99..268667b8439f3 100644 --- a/packages/@aws-cdk/aws-synthetics/test/integ.canary.ts +++ b/packages/@aws-cdk/aws-synthetics/test/integ.canary.ts @@ -11,6 +11,7 @@ import * as synthetics from '../lib'; * -- aws synthetics get-canary --name canary-integ has a state of 'RUNNING' * -- aws synthetics get-canary --name assetcanary-one has a state of 'RUNNING' * -- aws synthetics get-canary --name assetcanary-two has a state of 'RUNNING' + * -- aws synthetics get-canary --name assetcanary-three has a state of 'RUNNING' */ const app = new cdk.App(); const stack = new cdk.Stack(app, 'canary-one'); @@ -50,6 +51,15 @@ new synthetics.Canary(stack, 'MyCanaryTwo', { runtime: synthetics.Runtime.SYNTHETICS_NODEJS_PUPPETEER_3_2, }); +new synthetics.Canary(stack, 'MyCanaryThree', { + canaryName: 'assetcanary-three', + test: synthetics.Test.custom({ + handler: 'canary.handler', + code: synthetics.Code.fromAsset(path.join(__dirname, 'canary.zip')), + }), + runtime: synthetics.Runtime.SYNTHETICS_NODEJS_PUPPETEER_3_3, +}); + new synthetics.Canary(stack, 'MyPythonCanary', { canaryName: 'py-canary-integ', test: synthetics.Test.custom({ From 06fb9f93dec448f8536fd19e116f4a2a7b163ee4 Mon Sep 17 00:00:00 2001 From: Calvin Combs <66279577+comcalvi@users.noreply.github.com> Date: Mon, 25 Oct 2021 15:37:13 -0700 Subject: [PATCH 32/87] chore(cli): do not hardcode AWS::URLSuffix in hotswapping (#17104) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/aws-cdk/lib/api/aws-auth/sdk.ts | 20 ++++++ packages/aws-cdk/lib/api/deploy-stack.ts | 26 ++----- .../aws-cdk/lib/api/hotswap-deployments.ts | 3 +- .../evaluate-cloudformation-template.ts | 14 +++- .../aws-cdk/test/api/deploy-stack.test.ts | 3 +- .../api/hotswap/hotswap-deployments.test.ts | 69 +++++++++++++++++++ .../test/api/hotswap/hotswap-test-setup.ts | 4 ++ packages/aws-cdk/test/util/mock-sdk.ts | 12 ++++ 8 files changed, 126 insertions(+), 25 deletions(-) diff --git a/packages/aws-cdk/lib/api/aws-auth/sdk.ts b/packages/aws-cdk/lib/api/aws-auth/sdk.ts index 91fcdc2fede7d..c9c64d5e10ec1 100644 --- a/packages/aws-cdk/lib/api/aws-auth/sdk.ts +++ b/packages/aws-cdk/lib/api/aws-auth/sdk.ts @@ -5,6 +5,20 @@ import { cached } from '../../util/functions'; import { AccountAccessKeyCache } from './account-cache'; import { Account } from './sdk-provider'; +// We need to map regions to domain suffixes, and the SDK already has a function to do this. +// It's not part of the public API, but it's also unlikely to go away. +// +// Reuse that function, and add a safety check so we don't accidentally break if they ever +// refactor that away. + +/* eslint-disable @typescript-eslint/no-require-imports */ +const regionUtil = require('aws-sdk/lib/region_config'); +/* eslint-enable @typescript-eslint/no-require-imports */ + +if (!regionUtil.getEndpointSuffix) { + throw new Error('This version of AWS SDK for JS does not have the \'getEndpointSuffix\' function!'); +} + export interface ISDK { /** * The region this SDK has been instantiated for @@ -22,6 +36,8 @@ export interface ISDK { */ currentAccount(): Promise; + getEndpointSuffix(region: string): string; + lambda(): AWS.Lambda; cloudFormation(): AWS.CloudFormation; ec2(): AWS.EC2; @@ -190,6 +206,10 @@ export class SDK implements ISDK { } } + public getEndpointSuffix(region: string): string { + return regionUtil.getEndpointSuffix(region); + } + /** * Return a wrapping object for the underlying service object * diff --git a/packages/aws-cdk/lib/api/deploy-stack.ts b/packages/aws-cdk/lib/api/deploy-stack.ts index 6b5afe9673ead..ab662d34b517c 100644 --- a/packages/aws-cdk/lib/api/deploy-stack.ts +++ b/packages/aws-cdk/lib/api/deploy-stack.ts @@ -18,20 +18,6 @@ import { } from './util/cloudformation'; import { StackActivityMonitor, StackActivityProgress } from './util/cloudformation/stack-activity-monitor'; -// We need to map regions to domain suffixes, and the SDK already has a function to do this. -// It's not part of the public API, but it's also unlikely to go away. -// -// Reuse that function, and add a safety check so we don't accidentally break if they ever -// refactor that away. - -/* eslint-disable @typescript-eslint/no-require-imports */ -const regionUtil = require('aws-sdk/lib/region_config'); -/* eslint-enable @typescript-eslint/no-require-imports */ - -if (!regionUtil.getEndpointSuffix) { - throw new Error('This version of AWS SDK for JS does not have the \'getEndpointSuffix\' function!'); -} - type TemplateBodyParameter = { TemplateBody?: string TemplateURL?: string @@ -247,8 +233,7 @@ export async function deployStack(options: DeployStackOptions): Promise { + toolkitInfo: ToolkitInfo, + sdk: ISDK): Promise { // If the template has already been uploaded to S3, just use it from there. if (stack.stackTemplateAssetObjectUrl) { - return { TemplateURL: restUrlFromManifest(stack.stackTemplateAssetObjectUrl, resolvedEnvironment) }; + return { TemplateURL: restUrlFromManifest(stack.stackTemplateAssetObjectUrl, resolvedEnvironment, sdk) }; } // Otherwise, pass via API call (if small) or upload here (if large) @@ -553,7 +539,7 @@ function compareTags(a: Tag[], b: Tag[]): boolean { * and reformats s3://.../... urls into S3 REST URLs (which CloudFormation * expects) */ -function restUrlFromManifest(url: string, environment: cxapi.Environment): string { +function restUrlFromManifest(url: string, environment: cxapi.Environment, sdk: ISDK): string { const doNotUseMarker = '**DONOTUSE**'; // This URL may contain placeholders, so still substitute those. url = cxapi.EnvironmentPlaceholders.replace(url, { @@ -576,6 +562,6 @@ function restUrlFromManifest(url: string, environment: cxapi.Environment): strin const bucketName = s3Url[1]; const objectKey = s3Url[2]; - const urlSuffix: string = regionUtil.getEndpointSuffix(environment.region); + const urlSuffix: string = sdk.getEndpointSuffix(environment.region); return `https://s3.${environment.region}.${urlSuffix}/${bucketName}/${objectKey}`; } diff --git a/packages/aws-cdk/lib/api/hotswap-deployments.ts b/packages/aws-cdk/lib/api/hotswap-deployments.ts index 19b8405a7de19..08a22d3944437 100644 --- a/packages/aws-cdk/lib/api/hotswap-deployments.ts +++ b/packages/aws-cdk/lib/api/hotswap-deployments.ts @@ -36,8 +36,7 @@ export async function tryHotswapDeployment( account: resolvedEnv.account, region: resolvedEnv.region, partition: (await sdk.currentAccount()).partition, - // ToDo make this better: - urlSuffix: 'amazonaws.com', + urlSuffix: sdk.getEndpointSuffix, listStackResources, }); diff --git a/packages/aws-cdk/lib/api/hotswap/evaluate-cloudformation-template.ts b/packages/aws-cdk/lib/api/hotswap/evaluate-cloudformation-template.ts index 59d8d7df19445..5dc9f948a4250 100644 --- a/packages/aws-cdk/lib/api/hotswap/evaluate-cloudformation-template.ts +++ b/packages/aws-cdk/lib/api/hotswap/evaluate-cloudformation-template.ts @@ -16,7 +16,7 @@ export interface EvaluateCloudFormationTemplateProps { readonly account: string; readonly region: string; readonly partition: string; - readonly urlSuffix: string; + readonly urlSuffix: (region: string) => string; readonly listStackResources: ListStackResources; } @@ -27,6 +27,8 @@ export class EvaluateCloudFormationTemplate { private readonly account: string; private readonly region: string; private readonly partition: string; + private readonly urlSuffix: (region: string) => string; + private cachedUrlSuffix: string | undefined; constructor(props: EvaluateCloudFormationTemplateProps) { this.stackResources = props.listStackResources; @@ -35,12 +37,12 @@ export class EvaluateCloudFormationTemplate { 'AWS::AccountId': props.account, 'AWS::Region': props.region, 'AWS::Partition': props.partition, - 'AWS::URLSuffix': props.urlSuffix, ...props.parameters, }; this.account = props.account; this.region = props.region; this.partition = props.partition; + this.urlSuffix = props.urlSuffix; } public async findPhysicalNameFor(logicalId: string): Promise { @@ -184,6 +186,14 @@ export class EvaluateCloudFormationTemplate { private async findRefTarget(logicalId: string): Promise { // first, check to see if the Ref is a Parameter who's value we have + if (logicalId === 'AWS::URLSuffix') { + if (!this.cachedUrlSuffix) { + this.cachedUrlSuffix = this.urlSuffix(this.region); + } + + return this.cachedUrlSuffix; + } + const parameterTarget = this.context[logicalId]; if (parameterTarget) { return parameterTarget; diff --git a/packages/aws-cdk/test/api/deploy-stack.test.ts b/packages/aws-cdk/test/api/deploy-stack.test.ts index eb551ac528ec4..13e4640ff01ec 100644 --- a/packages/aws-cdk/test/api/deploy-stack.test.ts +++ b/packages/aws-cdk/test/api/deploy-stack.test.ts @@ -29,6 +29,7 @@ const FAKE_STACK_TERMINATION_PROTECTION = testStack({ let sdk: MockSdk; let sdkProvider: MockSdkProvider; let cfnMocks: MockedObject>; + beforeEach(() => { jest.resetAllMocks(); @@ -62,7 +63,7 @@ beforeEach(() => { updateTerminationProtection: jest.fn((_o) => ({ StackId: 'stack-id' })), }; sdk.stubCloudFormation(cfnMocks as any); - + sdk.stubGetEndpointSuffix(() => 'amazonaws.com'); }); function standardDeployStackArguments(): DeployStackOptions { diff --git a/packages/aws-cdk/test/api/hotswap/hotswap-deployments.test.ts b/packages/aws-cdk/test/api/hotswap/hotswap-deployments.test.ts index 26a8d08c27290..5d059df860cb8 100644 --- a/packages/aws-cdk/test/api/hotswap/hotswap-deployments.test.ts +++ b/packages/aws-cdk/test/api/hotswap/hotswap-deployments.test.ts @@ -4,13 +4,16 @@ import * as setup from './hotswap-test-setup'; let cfnMockProvider: setup.CfnMockProvider; let mockUpdateLambdaCode: (params: Lambda.Types.UpdateFunctionCodeRequest) => Lambda.Types.FunctionConfiguration; let mockUpdateMachineDefinition: (params: StepFunctions.Types.UpdateStateMachineInput) => StepFunctions.Types.UpdateStateMachineOutput; +let mockGetEndpointSuffix: () => string; beforeEach(() => { cfnMockProvider = setup.setupHotswapTests(); mockUpdateLambdaCode = jest.fn(); mockUpdateMachineDefinition = jest.fn(); + mockGetEndpointSuffix = jest.fn(() => 'amazonaws.com'); cfnMockProvider.setUpdateFunctionCodeMock(mockUpdateLambdaCode); cfnMockProvider.setUpdateStateMachineMock(mockUpdateMachineDefinition); + cfnMockProvider.stubGetEndpointSuffix(mockGetEndpointSuffix); }); test('returns a deployStackResult with noOp=true when it receives an empty set of changes', async () => { @@ -240,3 +243,69 @@ test('can correctly reference AWS::Partition in hotswappable changes', async () S3Key: 'new-key', }); }); + +test('can correctly reference AWS::URLSuffix in hotswappable changes', async () => { + // GIVEN + setup.setCurrentCfnStackTemplate({ + Resources: { + Func: { + Type: 'AWS::Lambda::Function', + Properties: { + Code: { + S3Bucket: 'current-bucket', + S3Key: 'current-key', + }, + FunctionName: { + 'Fn::Join': ['', [ + 'my-function-', + { Ref: 'AWS::URLSuffix' }, + '-', + { Ref: 'AWS::URLSuffix' }, + ]], + }, + }, + Metadata: { + 'aws:asset:path': 'old-path', + }, + }, + }, + }); + const cdkStackArtifact = setup.cdkStackArtifactOf({ + template: { + Resources: { + Func: { + Type: 'AWS::Lambda::Function', + Properties: { + Code: { + S3Bucket: 'current-bucket', + S3Key: 'new-key', + }, + FunctionName: { + 'Fn::Join': ['', [ + 'my-function-', + { Ref: 'AWS::URLSuffix' }, + '-', + { Ref: 'AWS::URLSuffix' }, + ]], + }, + }, + Metadata: { + 'aws:asset:path': 'new-path', + }, + }, + }, + }, + }); + + // WHEN + const deployStackResult = await cfnMockProvider.tryHotswapDeployment(cdkStackArtifact); + + // THEN + expect(deployStackResult).not.toBeUndefined(); + expect(mockUpdateLambdaCode).toHaveBeenCalledWith({ + FunctionName: 'my-function-amazonaws.com-amazonaws.com', + S3Bucket: 'current-bucket', + S3Key: 'new-key', + }); + expect(mockGetEndpointSuffix).toHaveBeenCalledTimes(1); +}); 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 c41d67752b791..87e06465c61dd 100644 --- a/packages/aws-cdk/test/api/hotswap/hotswap-test-setup.ts +++ b/packages/aws-cdk/test/api/hotswap/hotswap-test-setup.ts @@ -97,4 +97,8 @@ export class CfnMockProvider { ): Promise { return deployments.tryHotswapDeployment(this.mockSdkProvider, assetParams, currentCfnStack, stackArtifact); } + + public stubGetEndpointSuffix(stub: () => string) { + this.mockSdkProvider.stubGetEndpointSuffix(stub); + } } diff --git a/packages/aws-cdk/test/util/mock-sdk.ts b/packages/aws-cdk/test/util/mock-sdk.ts index 7b9b4f6fb8b1a..c9afd8cd13baa 100644 --- a/packages/aws-cdk/test/util/mock-sdk.ts +++ b/packages/aws-cdk/test/util/mock-sdk.ts @@ -109,6 +109,10 @@ export class MockSdkProvider extends SdkProvider { public stubStepFunctions(stubs: SyncHandlerSubsetOf) { (this.sdk as any).stepFunctions = jest.fn().mockReturnValue(partialAwsService(stubs)); } + + public stubGetEndpointSuffix(stub: () => string) { + this.sdk.getEndpointSuffix = stub; + } } export class MockSdk implements ISDK { @@ -125,6 +129,7 @@ export class MockSdk implements ISDK { public readonly secretsManager = jest.fn(); public readonly kms = jest.fn(); public readonly stepFunctions = jest.fn(); + public readonly getEndpointSuffix = jest.fn(); public currentAccount(): Promise { return Promise.resolve({ accountId: '123456789012', partition: 'aws' }); @@ -150,6 +155,13 @@ export class MockSdk implements ISDK { public stubSsm(stubs: SyncHandlerSubsetOf) { this.ssm.mockReturnValue(partialAwsService(stubs)); } + + /** + * Replace the getEndpointSuffix client with the given object + */ + public stubGetEndpointSuffix(stub: () => string) { + this.getEndpointSuffix.mockReturnValue(stub()); + } } /** From 9f3abd745c98a65e7314528f40d08ea2ecbe19a6 Mon Sep 17 00:00:00 2001 From: Ayush Goyal Date: Tue, 26 Oct 2021 04:58:49 +0530 Subject: [PATCH 33/87] feat(amplify): Add support for custom headers in the App (#17102) feat(amplify): Add support for custom headers in the App closes #17084 Refs: 1. https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-amplify-app.html#cfn-amplify-app-customheaders 2. https://docs.aws.amazon.com/amplify/latest/userguide/custom-headers.html 3. https://www.npmjs.com/package/yaml ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- package.json | 4 ++ packages/@aws-cdk/aws-amplify/NOTICE | 21 +++++++++++ packages/@aws-cdk/aws-amplify/README.md | 29 +++++++++++++++ packages/@aws-cdk/aws-amplify/lib/app.ts | 37 +++++++++++++++++++ packages/@aws-cdk/aws-amplify/package.json | 9 ++++- .../@aws-cdk/aws-amplify/test/app.test.ts | 31 ++++++++++++++++ .../aws-amplify/test/integ.app.expected.json | 1 + .../@aws-cdk/aws-amplify/test/integ.app.ts | 15 ++++++++ 8 files changed, 145 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 7db1f7c20c0ad..6115ddc36950c 100644 --- a/package.json +++ b/package.json @@ -81,6 +81,8 @@ "@aws-cdk/assertions-alpha/string-width/**", "@aws-cdk/assertions-alpha/table", "@aws-cdk/assertions-alpha/table/**", + "@aws-cdk/aws-amplify-alpha/yaml", + "@aws-cdk/aws-amplify-alpha/yaml/**", "@aws-cdk/assertions/colors", "@aws-cdk/assertions/colors/**", "@aws-cdk/assertions/diff", @@ -91,6 +93,8 @@ "@aws-cdk/assertions/string-width/**", "@aws-cdk/assertions/table", "@aws-cdk/assertions/table/**", + "@aws-cdk/aws-amplify/yaml", + "@aws-cdk/aws-amplify/yaml/**", "@aws-cdk/aws-codebuild/yaml", "@aws-cdk/aws-codebuild/yaml/**", "@aws-cdk/aws-codepipeline-actions/case", diff --git a/packages/@aws-cdk/aws-amplify/NOTICE b/packages/@aws-cdk/aws-amplify/NOTICE index 5fc3826926b5b..c84ff36099c3b 100644 --- a/packages/@aws-cdk/aws-amplify/NOTICE +++ b/packages/@aws-cdk/aws-amplify/NOTICE @@ -1,2 +1,23 @@ AWS Cloud Development Kit (AWS CDK) Copyright 2018-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + +------------------------------------------------------------------------------- + +The AWS CDK includes the following third-party software/licensing: + +** yaml - https://www.npmjs.com/package/yaml +Copyright 2018 Eemeli Aro + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. + +---------------- diff --git a/packages/@aws-cdk/aws-amplify/README.md b/packages/@aws-cdk/aws-amplify/README.md index 472846ea276b6..059588e493241 100644 --- a/packages/@aws-cdk/aws-amplify/README.md +++ b/packages/@aws-cdk/aws-amplify/README.md @@ -179,3 +179,32 @@ const amplifyApp = new amplify.App(this, 'MyApp', { autoBranchDeletion: true, // Automatically disconnect a branch when you delete a branch from your repository }); ``` + +## Adding custom response headers + +Use the `customResponseHeaders` prop to configure custom response headers for an Amplify app: + +```ts +const amplifyApp = new amplify.App(stack, 'App', { + sourceCodeProvider: new amplify.GitHubSourceCodeProvider({ + owner: '', + repository: '', + oauthToken: cdk.SecretValue.secretsManager('my-github-token') + }), + customResponseHeaders: [ + { + pattern: '*.json', + headers: { + 'custom-header-name-1': 'custom-header-value-1', + 'custom-header-name-2': 'custom-header-value-2', + }, + }, + { + pattern: '/path/*', + headers: { + 'custom-header-name-1': 'custom-header-value-2', + }, + }, + ], +}); +``` diff --git a/packages/@aws-cdk/aws-amplify/lib/app.ts b/packages/@aws-cdk/aws-amplify/lib/app.ts index 831921f89dbf8..030dc58059a6e 100644 --- a/packages/@aws-cdk/aws-amplify/lib/app.ts +++ b/packages/@aws-cdk/aws-amplify/lib/app.ts @@ -2,6 +2,7 @@ import * as codebuild from '@aws-cdk/aws-codebuild'; import * as iam from '@aws-cdk/aws-iam'; import { IResource, Lazy, Resource, SecretValue } from '@aws-cdk/core'; import { Construct } from 'constructs'; +import * as YAML from 'yaml'; import { CfnApp } from './amplify.generated'; import { BasicAuth } from './basic-auth'; import { Branch, BranchOptions } from './branch'; @@ -118,6 +119,16 @@ export interface AppProps { */ readonly buildSpec?: codebuild.BuildSpec; + + /** + * The custom HTTP response headers for an Amplify app. + * + * @see https://docs.aws.amazon.com/amplify/latest/userguide/custom-headers.html + * + * @default - no custom response headers + */ + readonly customResponseHeaders?: CustomResponseHeader[]; + /** * Custom rewrite/redirect rules for the application * @@ -238,6 +249,7 @@ export class App extends Resource implements IApp, iam.IGrantable { name: props.appName || this.node.id, oauthToken: sourceCodeProviderOptions?.oauthToken?.toString(), repository: sourceCodeProviderOptions?.repository, + customHeaders: props.customResponseHeaders ? renderCustomResponseHeaders(props.customResponseHeaders) : undefined, }); this.appId = app.attrAppId; @@ -486,3 +498,28 @@ export class CustomRule { this.condition = options.condition; } } + +/** + * Custom response header of an Amplify App. + */ +export interface CustomResponseHeader { + /** + * These custom headers will be applied to all URL file paths that match this pattern. + */ + readonly pattern: string; + + /** + * The map of custom headers to be applied. + */ + readonly headers: { [key: string]: string }; +} + +function renderCustomResponseHeaders(customHeaders: CustomResponseHeader[]): string { + const modifiedHeaders = customHeaders.map(customHeader => ({ + ...customHeader, + headers: Object.entries(customHeader.headers).map(([key, value]) => ({ key, value })), + })); + + const customHeadersObject = { customHeaders: modifiedHeaders }; + return YAML.stringify(customHeadersObject); +} diff --git a/packages/@aws-cdk/aws-amplify/package.json b/packages/@aws-cdk/aws-amplify/package.json index 13bbcc0ec61d4..7ee41fd004517 100644 --- a/packages/@aws-cdk/aws-amplify/package.json +++ b/packages/@aws-cdk/aws-amplify/package.json @@ -79,7 +79,8 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^26.0.24" + "@types/jest": "^26.0.24", + "@types/yaml": "1.9.6" }, "dependencies": { "@aws-cdk/aws-codebuild": "0.0.0", @@ -88,8 +89,12 @@ "@aws-cdk/aws-kms": "0.0.0", "@aws-cdk/aws-secretsmanager": "0.0.0", "@aws-cdk/core": "0.0.0", - "constructs": "^3.3.69" + "constructs": "^3.3.69", + "yaml": "1.10.2" }, + "bundledDependencies": [ + "yaml" + ], "peerDependencies": { "@aws-cdk/aws-codebuild": "0.0.0", "@aws-cdk/aws-codecommit": "0.0.0", diff --git a/packages/@aws-cdk/aws-amplify/test/app.test.ts b/packages/@aws-cdk/aws-amplify/test/app.test.ts index 76b6830bec1c5..87b15e143ab7f 100644 --- a/packages/@aws-cdk/aws-amplify/test/app.test.ts +++ b/packages/@aws-cdk/aws-amplify/test/app.test.ts @@ -394,3 +394,34 @@ test('with auto branch deletion', () => { EnableBranchAutoDeletion: true, }); }); + +test('with custom headers', () => { + // WHEN + new amplify.App(stack, 'App', { + sourceCodeProvider: new amplify.GitHubSourceCodeProvider({ + owner: 'aws', + repository: 'aws-cdk', + oauthToken: SecretValue.plainText('secret'), + }), + customResponseHeaders: [ + { + pattern: '*.json', + headers: { + 'custom-header-name-1': 'custom-header-value-1', + 'custom-header-name-2': 'custom-header-value-2', + }, + }, + { + pattern: '/path/*', + headers: { + 'custom-header-name-1': 'custom-header-value-2', + }, + }, + ], + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Amplify::App', { + CustomHeaders: 'customHeaders:\n - pattern: "*.json"\n headers:\n - key: custom-header-name-1\n value: custom-header-value-1\n - key: custom-header-name-2\n value: custom-header-value-2\n - pattern: /path/*\n headers:\n - key: custom-header-name-1\n value: custom-header-value-2\n', + }); +}); diff --git a/packages/@aws-cdk/aws-amplify/test/integ.app.expected.json b/packages/@aws-cdk/aws-amplify/test/integ.app.expected.json index 25971c2ea44a7..d7ddd233378e1 100644 --- a/packages/@aws-cdk/aws-amplify/test/integ.app.expected.json +++ b/packages/@aws-cdk/aws-amplify/test/integ.app.expected.json @@ -54,6 +54,7 @@ }, "Username": "aws" }, + "CustomHeaders": "customHeaders:\n - pattern: \"*.json\"\n headers:\n - key: custom-header-name-1\n value: custom-header-value-1\n - key: custom-header-name-2\n value: custom-header-value-2\n - pattern: /path/*\n headers:\n - key: custom-header-name-1\n value: custom-header-value-2\n", "CustomRules": [ { "Source": "/source", diff --git a/packages/@aws-cdk/aws-amplify/test/integ.app.ts b/packages/@aws-cdk/aws-amplify/test/integ.app.ts index 83ff527a292e2..accdaed6840bf 100644 --- a/packages/@aws-cdk/aws-amplify/test/integ.app.ts +++ b/packages/@aws-cdk/aws-amplify/test/integ.app.ts @@ -9,6 +9,21 @@ class TestStack extends Stack { const amplifyApp = new amplify.App(this, 'App', { basicAuth: amplify.BasicAuth.fromGeneratedPassword('aws'), autoBranchCreation: {}, + customResponseHeaders: [ + { + pattern: '*.json', + headers: { + 'custom-header-name-1': 'custom-header-value-1', + 'custom-header-name-2': 'custom-header-value-2', + }, + }, + { + pattern: '/path/*', + headers: { + 'custom-header-name-1': 'custom-header-value-2', + }, + }, + ], }); amplifyApp.addCustomRule({ From aea7a609412732adfcdcf1b614b9b45708cae520 Mon Sep 17 00:00:00 2001 From: Madeline Kusters <80541297+madeline-k@users.noreply.github.com> Date: Mon, 25 Oct 2021 17:21:09 -0700 Subject: [PATCH 34/87] chore(dependency upgrade): upgrade jest dependency in cdk-build-tools due to CVE-2021-23440 (#17148) We have a security vulnerability coming from a transitive dependency on `set-value` through `jest`. See: https://github.com/aws/aws-cdk/security/dependabot/yarn.lock/set-value/open Generated this diff by: ``` cd tools/@aws-cdk/cdk-build-tools yarn remove jest yarn add jest@latest ``` ### Testing - Ran `yarn audit` to verify that the security vulnerability coming from a transitive dependency on `set-value` via `jest` is in fact gone. - Waiting for the PR build to see if this major version update caused any breaking changes for us. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- tools/@aws-cdk/cdk-build-tools/package.json | 12 +- yarn.lock | 773 +++++++++++++++++++- 2 files changed, 768 insertions(+), 17 deletions(-) diff --git a/tools/@aws-cdk/cdk-build-tools/package.json b/tools/@aws-cdk/cdk-build-tools/package.json index 84005357a2458..c8dfb507afc46 100644 --- a/tools/@aws-cdk/cdk-build-tools/package.json +++ b/tools/@aws-cdk/cdk-build-tools/package.json @@ -35,13 +35,15 @@ }, "license": "Apache-2.0", "devDependencies": { + "@aws-cdk/pkglint": "0.0.0", "@types/fs-extra": "^8.1.2", "@types/jest": "^26.0.24", - "@types/yargs": "^15.0.14", "@types/semver": "^7.3.8", - "@aws-cdk/pkglint": "0.0.0" + "@types/yargs": "^15.0.14" }, "dependencies": { + "@aws-cdk/eslint-plugin": "0.0.0", + "@aws-cdk/yarn-cling": "0.0.0", "@typescript-eslint/eslint-plugin": "^4.33.0", "@typescript-eslint/parser": "^4.33.0", "awslint": "0.0.0", @@ -49,11 +51,10 @@ "eslint": "^7.32.0", "eslint-import-resolver-node": "^0.3.6", "eslint-import-resolver-typescript": "^2.5.0", - "@aws-cdk/eslint-plugin": "0.0.0", "eslint-plugin-import": "^2.25.2", "eslint-plugin-jest": "^24.7.0", "fs-extra": "^9.1.0", - "jest": "^26.6.3", + "jest": "^27.3.1", "jest-junit": "^11.1.0", "jsii": "^1.40.0", "jsii-pacmak": "^1.40.0", @@ -63,8 +64,7 @@ "semver": "^7.3.5", "ts-jest": "^26.5.6", "typescript": "~3.9.10", - "yargs": "^16.2.0", - "@aws-cdk/yarn-cling": "0.0.0" + "yargs": "^16.2.0" }, "keywords": [ "aws", diff --git a/yarn.lock b/yarn.lock index 442e61841ae13..c63b92155ae6a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -32,7 +32,7 @@ dependencies: "@babel/highlight" "^7.10.4" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.14.5", "@babel/code-frame@^7.15.8": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.14.5", "@babel/code-frame@^7.15.8": version "7.15.8" resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.15.8.tgz#45990c47adadb00c03677baa89221f7cc23d2503" integrity sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg== @@ -44,7 +44,7 @@ resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.15.0.tgz#2dbaf8b85334796cafbb0f5793a90a2fc010b176" integrity sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA== -"@babel/core@^7.1.0", "@babel/core@^7.7.5": +"@babel/core@^7.1.0", "@babel/core@^7.7.2", "@babel/core@^7.7.5": version "7.15.8" resolved "https://registry.npmjs.org/@babel/core/-/core-7.15.8.tgz#195b9f2bffe995d2c6c159e72fe525b4114e8c10" integrity sha512-3UG9dsxvYBMYwRv+gS41WKHno4K60/9GPy1CJaH6xy3Elq8CTtvtjT5R5jmNhXfCYLX2mTw+7/aq5ak/gOE0og== @@ -65,7 +65,7 @@ semver "^6.3.0" source-map "^0.5.0" -"@babel/generator@^7.15.4", "@babel/generator@^7.15.8": +"@babel/generator@^7.15.4", "@babel/generator@^7.15.8", "@babel/generator@^7.7.2": version "7.15.8" resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.15.8.tgz#fa56be6b596952ceb231048cf84ee499a19c0cd1" integrity sha512-ECmAKstXbp1cvpTTZciZCgfOt6iN64lR0d+euv3UZisU5awfRawOvg07Utn/qBGuH4bRIEZKrA/4LzZyXhZr8g== @@ -199,7 +199,7 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.15.4", "@babel/parser@^7.15.8": +"@babel/parser@^7.1.0", "@babel/parser@^7.15.4", "@babel/parser@^7.15.8", "@babel/parser@^7.7.2": version "7.15.8" resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.15.8.tgz#7bacdcbe71bdc3ff936d510c15dcea7cf0b99016" integrity sha512-BRYa3wcQnjS/nqI8Ac94pYYpJfojHVvVXJ97+IDCImX4Jc8W8Xv1+47enbruk+q1etOpsQNwnfFcNGw+gtPGxA== @@ -288,6 +288,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" +"@babel/plugin-syntax-typescript@^7.7.2": + version "7.14.5" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.14.5.tgz#b82c6ce471b165b5ce420cf92914d6fb46225716" + integrity sha512-u6OXzDaIXjEstBRRoBCQ/uKQKlbuaeE5in0RvWdA4pN6AhqxTIwUsnHPU1CFZA/amYObMsuWhYfRl3Ch90HD0Q== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/template@^7.15.4", "@babel/template@^7.3.3": version "7.15.4" resolved "https://registry.npmjs.org/@babel/template/-/template-7.15.4.tgz#51898d35dcf3faa670c4ee6afcfd517ee139f194" @@ -297,7 +304,7 @@ "@babel/parser" "^7.15.4" "@babel/types" "^7.15.4" -"@babel/traverse@^7.1.0", "@babel/traverse@^7.15.4": +"@babel/traverse@^7.1.0", "@babel/traverse@^7.15.4", "@babel/traverse@^7.7.2": version "7.15.4" resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.4.tgz#ff8510367a144bfbff552d9e18e28f3e2889c22d" integrity sha512-W6lQD8l4rUbQR/vYgSuCAE75ADyyQvOpFVsvPPdkhf6lATXAsQIG9YdtOcu8BB1dZ0LKu+Zo3c1wEcbKeuhdlA== @@ -417,6 +424,18 @@ jest-util "^26.6.2" slash "^3.0.0" +"@jest/console@^27.3.1": + version "27.3.1" + resolved "https://registry.npmjs.org/@jest/console/-/console-27.3.1.tgz#e8ea3a475d3f8162f23d69efbfaa9cbe486bee93" + integrity sha512-RkFNWmv0iui+qsOr/29q9dyfKTTT5DCuP31kUwg7rmOKPT/ozLeGLKJKVIiOfbiKyleUZKIrHwhmiZWVe8IMdw== + dependencies: + "@jest/types" "^27.2.5" + "@types/node" "*" + chalk "^4.0.0" + jest-message-util "^27.3.1" + jest-util "^27.3.1" + slash "^3.0.0" + "@jest/core@^26.6.3": version "26.6.3" resolved "https://registry.npmjs.org/@jest/core/-/core-26.6.3.tgz#7639fcb3833d748a4656ada54bde193051e45fad" @@ -451,6 +470,40 @@ slash "^3.0.0" strip-ansi "^6.0.0" +"@jest/core@^27.3.1": + version "27.3.1" + resolved "https://registry.npmjs.org/@jest/core/-/core-27.3.1.tgz#04992ef1b58b17c459afb87ab56d81e63d386925" + integrity sha512-DMNE90RR5QKx0EA+wqe3/TNEwiRpOkhshKNxtLxd4rt3IZpCt+RSL+FoJsGeblRZmqdK4upHA/mKKGPPRAifhg== + dependencies: + "@jest/console" "^27.3.1" + "@jest/reporters" "^27.3.1" + "@jest/test-result" "^27.3.1" + "@jest/transform" "^27.3.1" + "@jest/types" "^27.2.5" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + emittery "^0.8.1" + exit "^0.1.2" + graceful-fs "^4.2.4" + jest-changed-files "^27.3.0" + jest-config "^27.3.1" + jest-haste-map "^27.3.1" + jest-message-util "^27.3.1" + jest-regex-util "^27.0.6" + jest-resolve "^27.3.1" + jest-resolve-dependencies "^27.3.1" + jest-runner "^27.3.1" + jest-runtime "^27.3.1" + jest-snapshot "^27.3.1" + jest-util "^27.3.1" + jest-validate "^27.3.1" + jest-watcher "^27.3.1" + micromatch "^4.0.4" + rimraf "^3.0.0" + slash "^3.0.0" + strip-ansi "^6.0.0" + "@jest/environment@^26.6.2": version "26.6.2" resolved "https://registry.npmjs.org/@jest/environment/-/environment-26.6.2.tgz#ba364cc72e221e79cc8f0a99555bf5d7577cf92c" @@ -461,6 +514,16 @@ "@types/node" "*" jest-mock "^26.6.2" +"@jest/environment@^27.3.1": + version "27.3.1" + resolved "https://registry.npmjs.org/@jest/environment/-/environment-27.3.1.tgz#2182defbce8d385fd51c5e7c7050f510bd4c86b1" + integrity sha512-BCKCj4mOVLme6Tanoyc9k0ultp3pnmuyHw73UHRPeeZxirsU/7E3HC4le/VDb/SMzE1JcPnto+XBKFOcoiJzVw== + dependencies: + "@jest/fake-timers" "^27.3.1" + "@jest/types" "^27.2.5" + "@types/node" "*" + jest-mock "^27.3.0" + "@jest/fake-timers@^26.6.2": version "26.6.2" resolved "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-26.6.2.tgz#459c329bcf70cee4af4d7e3f3e67848123535aad" @@ -473,6 +536,18 @@ jest-mock "^26.6.2" jest-util "^26.6.2" +"@jest/fake-timers@^27.3.1": + version "27.3.1" + resolved "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.3.1.tgz#1fad860ee9b13034762cdb94266e95609dfce641" + integrity sha512-M3ZFgwwlqJtWZ+QkBG5NmC23A9w+A6ZxNsO5nJxJsKYt4yguBd3i8TpjQz5NfCX91nEve1KqD9RA2Q+Q1uWqoA== + dependencies: + "@jest/types" "^27.2.5" + "@sinonjs/fake-timers" "^8.0.1" + "@types/node" "*" + jest-message-util "^27.3.1" + jest-mock "^27.3.0" + jest-util "^27.3.1" + "@jest/globals@^26.6.2": version "26.6.2" resolved "https://registry.npmjs.org/@jest/globals/-/globals-26.6.2.tgz#5b613b78a1aa2655ae908eba638cc96a20df720a" @@ -482,6 +557,15 @@ "@jest/types" "^26.6.2" expect "^26.6.2" +"@jest/globals@^27.3.1": + version "27.3.1" + resolved "https://registry.npmjs.org/@jest/globals/-/globals-27.3.1.tgz#ce1dfb03d379237a9da6c1b99ecfaca1922a5f9e" + integrity sha512-Q651FWiWQAIFiN+zS51xqhdZ8g9b88nGCobC87argAxA7nMfNQq0Q0i9zTfQYgLa6qFXk2cGANEqfK051CZ8Pg== + dependencies: + "@jest/environment" "^27.3.1" + "@jest/types" "^27.2.5" + expect "^27.3.1" + "@jest/reporters@^26.6.2": version "26.6.2" resolved "https://registry.npmjs.org/@jest/reporters/-/reporters-26.6.2.tgz#1f518b99637a5f18307bd3ecf9275f6882a667f6" @@ -514,6 +598,37 @@ optionalDependencies: node-notifier "^8.0.0" +"@jest/reporters@^27.3.1": + version "27.3.1" + resolved "https://registry.npmjs.org/@jest/reporters/-/reporters-27.3.1.tgz#28b5c1f5789481e23788048fa822ed15486430b9" + integrity sha512-m2YxPmL9Qn1emFVgZGEiMwDntDxRRQ2D58tiDQlwYTg5GvbFOKseYCcHtn0WsI8CG4vzPglo3nqbOiT8ySBT/w== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@jest/console" "^27.3.1" + "@jest/test-result" "^27.3.1" + "@jest/transform" "^27.3.1" + "@jest/types" "^27.2.5" + "@types/node" "*" + chalk "^4.0.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.2" + graceful-fs "^4.2.4" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-instrument "^4.0.3" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.0.2" + jest-haste-map "^27.3.1" + jest-resolve "^27.3.1" + jest-util "^27.3.1" + jest-worker "^27.3.1" + slash "^3.0.0" + source-map "^0.6.0" + string-length "^4.0.1" + terminal-link "^2.0.0" + v8-to-istanbul "^8.1.0" + "@jest/source-map@^26.6.2": version "26.6.2" resolved "https://registry.npmjs.org/@jest/source-map/-/source-map-26.6.2.tgz#29af5e1e2e324cafccc936f218309f54ab69d535" @@ -523,6 +638,15 @@ graceful-fs "^4.2.4" source-map "^0.6.0" +"@jest/source-map@^27.0.6": + version "27.0.6" + resolved "https://registry.npmjs.org/@jest/source-map/-/source-map-27.0.6.tgz#be9e9b93565d49b0548b86e232092491fb60551f" + integrity sha512-Fek4mi5KQrqmlY07T23JRi0e7Z9bXTOOD86V/uS0EIW4PClvPDqZOyFlLpNJheS6QI0FNX1CgmPjtJ4EA/2M+g== + dependencies: + callsites "^3.0.0" + graceful-fs "^4.2.4" + source-map "^0.6.0" + "@jest/test-result@^26.6.2": version "26.6.2" resolved "https://registry.npmjs.org/@jest/test-result/-/test-result-26.6.2.tgz#55da58b62df134576cc95476efa5f7949e3f5f18" @@ -533,6 +657,16 @@ "@types/istanbul-lib-coverage" "^2.0.0" collect-v8-coverage "^1.0.0" +"@jest/test-result@^27.3.1": + version "27.3.1" + resolved "https://registry.npmjs.org/@jest/test-result/-/test-result-27.3.1.tgz#89adee8b771877c69b3b8d59f52f29dccc300194" + integrity sha512-mLn6Thm+w2yl0opM8J/QnPTqrfS4FoXsXF2WIWJb2O/GBSyResL71BRuMYbYRsGt7ELwS5JGcEcGb52BNrumgg== + dependencies: + "@jest/console" "^27.3.1" + "@jest/types" "^27.2.5" + "@types/istanbul-lib-coverage" "^2.0.0" + collect-v8-coverage "^1.0.0" + "@jest/test-sequencer@^26.6.3": version "26.6.3" resolved "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-26.6.3.tgz#98e8a45100863886d074205e8ffdc5a7eb582b17" @@ -544,6 +678,16 @@ jest-runner "^26.6.3" jest-runtime "^26.6.3" +"@jest/test-sequencer@^27.3.1": + version "27.3.1" + resolved "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.3.1.tgz#4b3bde2dbb05ee74afdae608cf0768e3354683b1" + integrity sha512-siySLo07IMEdSjA4fqEnxfIX8lB/lWYsBPwNFtkOvsFQvmBrL3yj3k3uFNZv/JDyApTakRpxbKLJ3CT8UGVCrA== + dependencies: + "@jest/test-result" "^27.3.1" + graceful-fs "^4.2.4" + jest-haste-map "^27.3.1" + jest-runtime "^27.3.1" + "@jest/transform@^26.6.2": version "26.6.2" resolved "https://registry.npmjs.org/@jest/transform/-/transform-26.6.2.tgz#5ac57c5fa1ad17b2aae83e73e45813894dcf2e4b" @@ -565,6 +709,27 @@ source-map "^0.6.1" write-file-atomic "^3.0.0" +"@jest/transform@^27.3.1": + version "27.3.1" + resolved "https://registry.npmjs.org/@jest/transform/-/transform-27.3.1.tgz#ff80eafbeabe811e9025e4b6f452126718455220" + integrity sha512-3fSvQ02kuvjOI1C1ssqMVBKJpZf6nwoCiSu00zAKh5nrp3SptNtZy/8s5deayHnqxhjD9CWDJ+yqQwuQ0ZafXQ== + dependencies: + "@babel/core" "^7.1.0" + "@jest/types" "^27.2.5" + babel-plugin-istanbul "^6.0.0" + chalk "^4.0.0" + convert-source-map "^1.4.0" + fast-json-stable-stringify "^2.0.0" + graceful-fs "^4.2.4" + jest-haste-map "^27.3.1" + jest-regex-util "^27.0.6" + jest-util "^27.3.1" + micromatch "^4.0.4" + pirates "^4.0.1" + slash "^3.0.0" + source-map "^0.6.1" + write-file-atomic "^3.0.0" + "@jest/types@^26.6.2": version "26.6.2" resolved "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e" @@ -576,6 +741,17 @@ "@types/yargs" "^15.0.0" chalk "^4.0.0" +"@jest/types@^27.2.5": + version "27.2.5" + resolved "https://registry.npmjs.org/@jest/types/-/types-27.2.5.tgz#420765c052605e75686982d24b061b4cbba22132" + integrity sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^16.0.0" + chalk "^4.0.0" + "@jsii/check-node@1.40.0": version "1.40.0" resolved "https://registry.npmjs.org/@jsii/check-node/-/check-node-1.40.0.tgz#49882a61ad1b3a37cd35c35fa1a2301955f1c058" @@ -1528,6 +1704,13 @@ dependencies: "@sinonjs/commons" "^1.7.0" +"@sinonjs/fake-timers@^8.0.1": + version "8.0.1" + resolved "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.0.1.tgz#1c1c9a91419f804e59ae8df316a07dd1c3a76b94" + integrity sha512-AU7kwFxreVd6OAXcAFlKSmZquiRUU0FvYm44k1Y1QbK7Co4m0aqfGMhjykIeQp/H6rcl+nFmj0zfdUcGVs9Dew== + dependencies: + "@sinonjs/commons" "^1.7.0" + "@sinonjs/samsam@^5.3.1": version "5.3.1" resolved "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.3.1.tgz#375a45fe6ed4e92fca2fb920e007c48232a6507f" @@ -1588,7 +1771,7 @@ resolved "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.84.tgz#b1f391ceeb6908b28d8416d93f27afe8d1348d4e" integrity sha512-5V78eLtmN0d4RA14hKDwcsMQRl3JotQJlhGFDBo/jdE2TyDFRaYwB/UmMUC4SzhSvRGn+YMkh7jGPnXi8COAng== -"@types/babel__core@^7.0.0", "@types/babel__core@^7.1.7": +"@types/babel__core@^7.0.0", "@types/babel__core@^7.1.14", "@types/babel__core@^7.1.7": version "7.1.16" resolved "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.16.tgz#bc12c74b7d65e82d29876b5d0baf5c625ac58702" integrity sha512-EAEHtisTMM+KaKwfWdC3oyllIqswlznXCIVCt7/oRNrh+DhgT4UEBNC/jlADNjvw7UnfbcdkGQcPVZ1xYiLcrQ== @@ -1764,7 +1947,7 @@ resolved "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== -"@types/prettier@^2.0.0": +"@types/prettier@^2.0.0", "@types/prettier@^2.1.5": version "2.4.1" resolved "https://registry.npmjs.org/@types/prettier/-/prettier-2.4.1.tgz#e1303048d5389563e130f5bdd89d37a99acb75eb" integrity sha512-Fo79ojj3vdEZOHg3wR9ksAMRz4P3S5fDB5e/YWZiFnyFQI1WY2Vftu9XoXVVtJfxB7Bpce/QTqWSSntkz2Znrw== @@ -1858,6 +2041,13 @@ dependencies: "@types/yargs-parser" "*" +"@types/yargs@^16.0.0": + version "16.0.4" + resolved "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz#26aad98dd2c2a38e421086ea9ad42b9e51642977" + integrity sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw== + dependencies: + "@types/yargs-parser" "*" + "@types/yarnpkg__lockfile@^1.1.5": version "1.1.5" resolved "https://registry.npmjs.org/@types/yarnpkg__lockfile/-/yarnpkg__lockfile-1.1.5.tgz#9639020e1fb65120a2f4387db8f1e8b63efdf229" @@ -2060,6 +2250,11 @@ ansi-regex@^2.0.0: resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + ansi-regex@^4.1.0: version "4.1.0" resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" @@ -2084,6 +2279,11 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" +ansi-styles@^5.0.0: + version "5.2.0" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + anymatch@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" @@ -2365,6 +2565,20 @@ babel-jest@^26.6.3: graceful-fs "^4.2.4" slash "^3.0.0" +babel-jest@^27.3.1: + version "27.3.1" + resolved "https://registry.npmjs.org/babel-jest/-/babel-jest-27.3.1.tgz#0636a3404c68e07001e434ac4956d82da8a80022" + integrity sha512-SjIF8hh/ir0peae2D6S6ZKRhUy7q/DnpH7k/V6fT4Bgs/LXXUztOpX4G2tCgq8mLo5HA9mN6NmlFMeYtKmIsTQ== + dependencies: + "@jest/transform" "^27.3.1" + "@jest/types" "^27.2.5" + "@types/babel__core" "^7.1.14" + babel-plugin-istanbul "^6.0.0" + babel-preset-jest "^27.2.0" + chalk "^4.0.0" + graceful-fs "^4.2.4" + slash "^3.0.0" + babel-plugin-istanbul@^6.0.0: version "6.0.0" resolved "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz#e159ccdc9af95e0b570c75b4573b7c34d671d765" @@ -2386,6 +2600,16 @@ babel-plugin-jest-hoist@^26.6.2: "@types/babel__core" "^7.0.0" "@types/babel__traverse" "^7.0.6" +babel-plugin-jest-hoist@^27.2.0: + version "27.2.0" + resolved "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.2.0.tgz#79f37d43f7e5c4fdc4b2ca3e10cc6cf545626277" + integrity sha512-TOux9khNKdi64mW+0OIhcmbAn75tTlzKhxmiNXevQaPbrBYK7YKjP1jl6NHTJ6XR5UgUrJbCnWlKVnJn29dfjw== + dependencies: + "@babel/template" "^7.3.3" + "@babel/types" "^7.3.3" + "@types/babel__core" "^7.0.0" + "@types/babel__traverse" "^7.0.6" + babel-preset-current-node-syntax@^1.0.0: version "1.0.1" resolved "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" @@ -2412,6 +2636,14 @@ babel-preset-jest@^26.6.2: babel-plugin-jest-hoist "^26.6.2" babel-preset-current-node-syntax "^1.0.0" +babel-preset-jest@^27.2.0: + version "27.2.0" + resolved "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.2.0.tgz#556bbbf340608fed5670ab0ea0c8ef2449fba885" + integrity sha512-z7MgQ3peBwN5L5aCqBKnF6iqdlvZvFUQynEhu0J+X9nHLU72jO3iY331lcYrg+AssJ8q7xsv5/3AICzVmJ/wvg== + dependencies: + babel-plugin-jest-hoist "^27.2.0" + babel-preset-current-node-syntax "^1.0.0" + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -2748,11 +2980,21 @@ ci-info@^2.0.0: resolved "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== +ci-info@^3.2.0: + version "3.2.0" + resolved "https://registry.npmjs.org/ci-info/-/ci-info-3.2.0.tgz#2876cb948a498797b5236f0095bc057d0dca38b6" + integrity sha512-dVqRX7fLUm8J6FgHJ418XuIgDLZDkYcDFTeL6TA2gt5WlIZUQrrH6EZrNClwT/H0FateUsZkGIOPRrLbP+PR9A== + cjs-module-lexer@^0.6.0: version "0.6.0" resolved "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-0.6.0.tgz#4186fcca0eae175970aee870b9fe2d6cf8d5655f" integrity sha512-uc2Vix1frTfnuzxxu1Hp4ktSvM3QaI4oXl4ZUqL1wjTu/BGki9TrCWoqLTg/drR1KwAEarXuRFCG2Svr1GxPFw== +cjs-module-lexer@^1.0.0: + version "1.2.2" + resolved "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40" + integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA== + class-utils@^0.3.5: version "0.3.6" resolved "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" @@ -2836,6 +3078,11 @@ co@^4.6.0: resolved "https://registry.npmjs.org/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + codemaker@^1.39.0: version "1.39.0" resolved "https://registry.npmjs.org/codemaker/-/codemaker-1.39.0.tgz#d8103f4b587210b1d6aa073d62ffb510ac20bc42" @@ -3529,6 +3776,11 @@ diff-sequences@^26.6.2: resolved "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.6.2.tgz#48ba99157de1923412eed41db6b6d4aa9ca7c0b1" integrity sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q== +diff-sequences@^27.0.6: + version "27.0.6" + resolved "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.0.6.tgz#3305cb2e55a033924054695cc66019fd7f8e5723" + integrity sha512-ag6wfpBFyNXZ0p8pcuIDS//D8H062ZQJ3fzYxjpmeKjnz8W4pekL3AI8VohmyZmsWW2PWaHgjsmqR6L13101VQ== + diff@^4.0.1, diff@^4.0.2: version "4.0.2" resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" @@ -3636,6 +3888,11 @@ emittery@^0.7.1: resolved "https://registry.npmjs.org/emittery/-/emittery-0.7.2.tgz#25595908e13af0f5674ab419396e2fb394cdfa82" integrity sha512-A8OG5SR/ij3SsJdWDJdkkSYUjQdCUx6APQXem0SaEePBSRg4eymGYwBkKo1Y6DU+af/Jn2dBQqDBvjnr9Vi8nQ== +emittery@^0.8.1: + version "0.8.1" + resolved "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz#bb23cc86d03b30aa75a7f734819dee2e1ba70860" + integrity sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg== + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -4207,6 +4464,18 @@ expect@^26.6.2: jest-message-util "^26.6.2" jest-regex-util "^26.0.0" +expect@^27.3.1: + version "27.3.1" + resolved "https://registry.npmjs.org/expect/-/expect-27.3.1.tgz#d0f170b1f5c8a2009bab0beffd4bb94f043e38e7" + integrity sha512-MrNXV2sL9iDRebWPGOGFdPQRl2eDQNu/uhxIMShjjx74T6kC6jFIkmQ6OqXDtevjGUkyB2IT56RzDBqXf/QPCg== + dependencies: + "@jest/types" "^27.2.5" + ansi-styles "^5.0.0" + jest-get-type "^27.3.1" + jest-matcher-utils "^27.3.1" + jest-message-util "^27.3.1" + jest-regex-util "^27.0.6" + extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" @@ -4554,7 +4823,7 @@ fs.realpath@^1.0.0: resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= -fsevents@^2.1.2: +fsevents@^2.1.2, fsevents@^2.3.2: version "2.3.2" resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== @@ -5267,6 +5536,18 @@ is-extglob@^2.1.1: resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + is-fullwidth-code-point@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" @@ -5563,6 +5844,40 @@ jest-changed-files@^26.6.2: execa "^4.0.0" throat "^5.0.0" +jest-changed-files@^27.3.0: + version "27.3.0" + resolved "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.3.0.tgz#22a02cc2b34583fc66e443171dc271c0529d263c" + integrity sha512-9DJs9garMHv4RhylUMZgbdCJ3+jHSkpL9aaVKp13xtXAD80qLTLrqcDZL1PHA9dYA0bCI86Nv2BhkLpLhrBcPg== + dependencies: + "@jest/types" "^27.2.5" + execa "^5.0.0" + throat "^6.0.1" + +jest-circus@^27.3.1: + version "27.3.1" + resolved "https://registry.npmjs.org/jest-circus/-/jest-circus-27.3.1.tgz#1679e74387cbbf0c6a8b42de963250a6469e0797" + integrity sha512-v1dsM9II6gvXokgqq6Yh2jHCpfg7ZqV4jWY66u7npz24JnhP3NHxI0sKT7+ZMQ7IrOWHYAaeEllOySbDbWsiXw== + dependencies: + "@jest/environment" "^27.3.1" + "@jest/test-result" "^27.3.1" + "@jest/types" "^27.2.5" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + dedent "^0.7.0" + expect "^27.3.1" + is-generator-fn "^2.0.0" + jest-each "^27.3.1" + jest-matcher-utils "^27.3.1" + jest-message-util "^27.3.1" + jest-runtime "^27.3.1" + jest-snapshot "^27.3.1" + jest-util "^27.3.1" + pretty-format "^27.3.1" + slash "^3.0.0" + stack-utils "^2.0.3" + throat "^6.0.1" + jest-cli@^26.6.3: version "26.6.3" resolved "https://registry.npmjs.org/jest-cli/-/jest-cli-26.6.3.tgz#43117cfef24bc4cd691a174a8796a532e135e92a" @@ -5582,6 +5897,24 @@ jest-cli@^26.6.3: prompts "^2.0.1" yargs "^15.4.1" +jest-cli@^27.3.1: + version "27.3.1" + resolved "https://registry.npmjs.org/jest-cli/-/jest-cli-27.3.1.tgz#b576f9d146ba6643ce0a162d782b40152b6b1d16" + integrity sha512-WHnCqpfK+6EvT62me6WVs8NhtbjAS4/6vZJnk7/2+oOr50cwAzG4Wxt6RXX0hu6m1169ZGMlhYYUNeKBXCph/Q== + dependencies: + "@jest/core" "^27.3.1" + "@jest/test-result" "^27.3.1" + "@jest/types" "^27.2.5" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.4" + import-local "^3.0.2" + jest-config "^27.3.1" + jest-util "^27.3.1" + jest-validate "^27.3.1" + prompts "^2.0.1" + yargs "^16.2.0" + jest-config@^26.6.3: version "26.6.3" resolved "https://registry.npmjs.org/jest-config/-/jest-config-26.6.3.tgz#64f41444eef9eb03dc51d5c53b75c8c71f645349" @@ -5606,6 +5939,33 @@ jest-config@^26.6.3: micromatch "^4.0.2" pretty-format "^26.6.2" +jest-config@^27.3.1: + version "27.3.1" + resolved "https://registry.npmjs.org/jest-config/-/jest-config-27.3.1.tgz#cb3b7f6aaa8c0a7daad4f2b9573899ca7e09bbad" + integrity sha512-KY8xOIbIACZ/vdYCKSopL44I0xboxC751IX+DXL2+Wx6DKNycyEfV3rryC3BPm5Uq/BBqDoMrKuqLEUNJmMKKg== + dependencies: + "@babel/core" "^7.1.0" + "@jest/test-sequencer" "^27.3.1" + "@jest/types" "^27.2.5" + babel-jest "^27.3.1" + chalk "^4.0.0" + ci-info "^3.2.0" + deepmerge "^4.2.2" + glob "^7.1.1" + graceful-fs "^4.2.4" + jest-circus "^27.3.1" + jest-environment-jsdom "^27.3.1" + jest-environment-node "^27.3.1" + jest-get-type "^27.3.1" + jest-jasmine2 "^27.3.1" + jest-regex-util "^27.0.6" + jest-resolve "^27.3.1" + jest-runner "^27.3.1" + jest-util "^27.3.1" + jest-validate "^27.3.1" + micromatch "^4.0.4" + pretty-format "^27.3.1" + jest-diff@^26.0.0, jest-diff@^26.6.2: version "26.6.2" resolved "https://registry.npmjs.org/jest-diff/-/jest-diff-26.6.2.tgz#1aa7468b52c3a68d7d5c5fdcdfcd5e49bd164394" @@ -5616,6 +5976,16 @@ jest-diff@^26.0.0, jest-diff@^26.6.2: jest-get-type "^26.3.0" pretty-format "^26.6.2" +jest-diff@^27.3.1: + version "27.3.1" + resolved "https://registry.npmjs.org/jest-diff/-/jest-diff-27.3.1.tgz#d2775fea15411f5f5aeda2a5e02c2f36440f6d55" + integrity sha512-PCeuAH4AWUo2O5+ksW4pL9v5xJAcIKPUPfIhZBcG1RKv/0+dvaWTQK1Nrau8d67dp65fOqbeMdoil+6PedyEPQ== + dependencies: + chalk "^4.0.0" + diff-sequences "^27.0.6" + jest-get-type "^27.3.1" + pretty-format "^27.3.1" + jest-docblock@^26.0.0: version "26.0.0" resolved "https://registry.npmjs.org/jest-docblock/-/jest-docblock-26.0.0.tgz#3e2fa20899fc928cb13bd0ff68bd3711a36889b5" @@ -5623,6 +5993,13 @@ jest-docblock@^26.0.0: dependencies: detect-newline "^3.0.0" +jest-docblock@^27.0.6: + version "27.0.6" + resolved "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.0.6.tgz#cc78266acf7fe693ca462cbbda0ea4e639e4e5f3" + integrity sha512-Fid6dPcjwepTFraz0YxIMCi7dejjJ/KL9FBjPYhBp4Sv1Y9PdhImlKZqYU555BlN4TQKaTc+F2Av1z+anVyGkA== + dependencies: + detect-newline "^3.0.0" + jest-each@^26.6.2: version "26.6.2" resolved "https://registry.npmjs.org/jest-each/-/jest-each-26.6.2.tgz#02526438a77a67401c8a6382dfe5999952c167cb" @@ -5634,6 +6011,17 @@ jest-each@^26.6.2: jest-util "^26.6.2" pretty-format "^26.6.2" +jest-each@^27.3.1: + version "27.3.1" + resolved "https://registry.npmjs.org/jest-each/-/jest-each-27.3.1.tgz#14c56bb4f18dd18dc6bdd853919b5f16a17761ff" + integrity sha512-E4SwfzKJWYcvOYCjOxhZcxwL+AY0uFMvdCOwvzgutJiaiodFjkxQQDxHm8FQBeTqDnSmKsQWn7ldMRzTn2zJaQ== + dependencies: + "@jest/types" "^27.2.5" + chalk "^4.0.0" + jest-get-type "^27.3.1" + jest-util "^27.3.1" + pretty-format "^27.3.1" + jest-environment-jsdom@^26.6.2: version "26.6.2" resolved "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-26.6.2.tgz#78d09fe9cf019a357009b9b7e1f101d23bd1da3e" @@ -5647,6 +6035,19 @@ jest-environment-jsdom@^26.6.2: jest-util "^26.6.2" jsdom "^16.4.0" +jest-environment-jsdom@^27.3.1: + version "27.3.1" + resolved "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.3.1.tgz#63ac36d68f7a9303494df783494856222b57f73e" + integrity sha512-3MOy8qMzIkQlfb3W1TfrD7uZHj+xx8Olix5vMENkj5djPmRqndMaXtpnaZkxmxM+Qc3lo+yVzJjzuXbCcZjAlg== + dependencies: + "@jest/environment" "^27.3.1" + "@jest/fake-timers" "^27.3.1" + "@jest/types" "^27.2.5" + "@types/node" "*" + jest-mock "^27.3.0" + jest-util "^27.3.1" + jsdom "^16.6.0" + jest-environment-node@^26.6.2: version "26.6.2" resolved "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-26.6.2.tgz#824e4c7fb4944646356f11ac75b229b0035f2b0c" @@ -5659,11 +6060,28 @@ jest-environment-node@^26.6.2: jest-mock "^26.6.2" jest-util "^26.6.2" +jest-environment-node@^27.3.1: + version "27.3.1" + resolved "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.3.1.tgz#af7d0eed04edafb740311b303f3fe7c8c27014bb" + integrity sha512-T89F/FgkE8waqrTSA7/ydMkcc52uYPgZZ6q8OaZgyiZkJb5QNNCF6oPZjH9IfPFfcc9uBWh1574N0kY0pSvTXw== + dependencies: + "@jest/environment" "^27.3.1" + "@jest/fake-timers" "^27.3.1" + "@jest/types" "^27.2.5" + "@types/node" "*" + jest-mock "^27.3.0" + jest-util "^27.3.1" + jest-get-type@^26.3.0: version "26.3.0" resolved "https://registry.npmjs.org/jest-get-type/-/jest-get-type-26.3.0.tgz#e97dc3c3f53c2b406ca7afaed4493b1d099199e0" integrity sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig== +jest-get-type@^27.3.1: + version "27.3.1" + resolved "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.3.1.tgz#a8a2b0a12b50169773099eee60a0e6dd11423eff" + integrity sha512-+Ilqi8hgHSAdhlQ3s12CAVNd8H96ZkQBfYoXmArzZnOfAtVAJEiPDBirjByEblvG/4LPJmkL+nBqPO3A1YJAEg== + jest-haste-map@^26.6.2: version "26.6.2" resolved "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-26.6.2.tgz#dd7e60fe7dc0e9f911a23d79c5ff7fb5c2cafeaa" @@ -5685,6 +6103,26 @@ jest-haste-map@^26.6.2: optionalDependencies: fsevents "^2.1.2" +jest-haste-map@^27.3.1: + version "27.3.1" + resolved "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.3.1.tgz#7656fbd64bf48bda904e759fc9d93e2c807353ee" + integrity sha512-lYfNZIzwPccDJZIyk9Iz5iQMM/MH56NIIcGj7AFU1YyA4ewWFBl8z+YPJuSCRML/ee2cCt2y3W4K3VXPT6Nhzg== + dependencies: + "@jest/types" "^27.2.5" + "@types/graceful-fs" "^4.1.2" + "@types/node" "*" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.4" + jest-regex-util "^27.0.6" + jest-serializer "^27.0.6" + jest-util "^27.3.1" + jest-worker "^27.3.1" + micromatch "^4.0.4" + walker "^1.0.7" + optionalDependencies: + fsevents "^2.3.2" + jest-jasmine2@^26.6.3: version "26.6.3" resolved "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-26.6.3.tgz#adc3cf915deacb5212c93b9f3547cd12958f2edd" @@ -5709,6 +6147,30 @@ jest-jasmine2@^26.6.3: pretty-format "^26.6.2" throat "^5.0.0" +jest-jasmine2@^27.3.1: + version "27.3.1" + resolved "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.3.1.tgz#df6d3d07c7dafc344feb43a0072a6f09458d32b0" + integrity sha512-WK11ZUetDQaC09w4/j7o4FZDUIp+4iYWH/Lik34Pv7ukL+DuXFGdnmmi7dT58J2ZYKFB5r13GyE0z3NPeyJmsg== + dependencies: + "@babel/traverse" "^7.1.0" + "@jest/environment" "^27.3.1" + "@jest/source-map" "^27.0.6" + "@jest/test-result" "^27.3.1" + "@jest/types" "^27.2.5" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + expect "^27.3.1" + is-generator-fn "^2.0.0" + jest-each "^27.3.1" + jest-matcher-utils "^27.3.1" + jest-message-util "^27.3.1" + jest-runtime "^27.3.1" + jest-snapshot "^27.3.1" + jest-util "^27.3.1" + pretty-format "^27.3.1" + throat "^6.0.1" + jest-junit@^11.1.0: version "11.1.0" resolved "https://registry.npmjs.org/jest-junit/-/jest-junit-11.1.0.tgz#79cd53948e44d62b2b30fa23ea0d7a899d2c8d7a" @@ -5737,6 +6199,14 @@ jest-leak-detector@^26.6.2: jest-get-type "^26.3.0" pretty-format "^26.6.2" +jest-leak-detector@^27.3.1: + version "27.3.1" + resolved "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.3.1.tgz#7fb632c2992ef707a1e73286e1e704f9cc1772b2" + integrity sha512-78QstU9tXbaHzwlRlKmTpjP9k4Pvre5l0r8Spo4SbFFVy/4Abg9I6ZjHwjg2QyKEAMg020XcjP+UgLZIY50yEg== + dependencies: + jest-get-type "^27.3.1" + pretty-format "^27.3.1" + jest-matcher-utils@^26.6.2: version "26.6.2" resolved "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-26.6.2.tgz#8e6fd6e863c8b2d31ac6472eeb237bc595e53e7a" @@ -5747,6 +6217,16 @@ jest-matcher-utils@^26.6.2: jest-get-type "^26.3.0" pretty-format "^26.6.2" +jest-matcher-utils@^27.3.1: + version "27.3.1" + resolved "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.3.1.tgz#257ad61e54a6d4044e080d85dbdc4a08811e9c1c" + integrity sha512-hX8N7zXS4k+8bC1Aj0OWpGb7D3gIXxYvPNK1inP5xvE4ztbz3rc4AkI6jGVaerepBnfWB17FL5lWFJT3s7qo8w== + dependencies: + chalk "^4.0.0" + jest-diff "^27.3.1" + jest-get-type "^27.3.1" + pretty-format "^27.3.1" + jest-message-util@^26.6.2: version "26.6.2" resolved "https://registry.npmjs.org/jest-message-util/-/jest-message-util-26.6.2.tgz#58173744ad6fc0506b5d21150b9be56ef001ca07" @@ -5762,6 +6242,21 @@ jest-message-util@^26.6.2: slash "^3.0.0" stack-utils "^2.0.2" +jest-message-util@^27.3.1: + version "27.3.1" + resolved "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.3.1.tgz#f7c25688ad3410ab10bcb862bcfe3152345c6436" + integrity sha512-bh3JEmxsTZ/9rTm0jQrPElbY2+y48Rw2t47uMfByNyUVR+OfPh4anuyKsGqsNkXk/TI4JbLRZx+7p7Hdt6q1yg== + dependencies: + "@babel/code-frame" "^7.12.13" + "@jest/types" "^27.2.5" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.4" + micromatch "^4.0.4" + pretty-format "^27.3.1" + slash "^3.0.0" + stack-utils "^2.0.3" + jest-mock@^26.6.2: version "26.6.2" resolved "https://registry.npmjs.org/jest-mock/-/jest-mock-26.6.2.tgz#d6cb712b041ed47fe0d9b6fc3474bc6543feb302" @@ -5770,6 +6265,14 @@ jest-mock@^26.6.2: "@jest/types" "^26.6.2" "@types/node" "*" +jest-mock@^27.3.0: + version "27.3.0" + resolved "https://registry.npmjs.org/jest-mock/-/jest-mock-27.3.0.tgz#ddf0ec3cc3e68c8ccd489bef4d1f525571a1b867" + integrity sha512-ziZiLk0elZOQjD08bLkegBzv5hCABu/c8Ytx45nJKkysQwGaonvmTxwjLqEA4qGdasq9o2I8/HtdGMNnVsMTGw== + dependencies: + "@jest/types" "^27.2.5" + "@types/node" "*" + jest-pnp-resolver@^1.2.2: version "1.2.2" resolved "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" @@ -5780,6 +6283,11 @@ jest-regex-util@^26.0.0: resolved "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-26.0.0.tgz#d25e7184b36e39fd466c3bc41be0971e821fee28" integrity sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A== +jest-regex-util@^27.0.6: + version "27.0.6" + resolved "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.0.6.tgz#02e112082935ae949ce5d13b2675db3d8c87d9c5" + integrity sha512-SUhPzBsGa1IKm8hx2F4NfTGGp+r7BXJ4CulsZ1k2kI+mGLG+lxGrs76veN2LF/aUdGosJBzKgXmNCw+BzFqBDQ== + jest-resolve-dependencies@^26.6.3: version "26.6.3" resolved "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-26.6.3.tgz#6680859ee5d22ee5dcd961fe4871f59f4c784fb6" @@ -5789,6 +6297,15 @@ jest-resolve-dependencies@^26.6.3: jest-regex-util "^26.0.0" jest-snapshot "^26.6.2" +jest-resolve-dependencies@^27.3.1: + version "27.3.1" + resolved "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.3.1.tgz#85b99bdbdfa46e2c81c6228fc4c91076f624f6e2" + integrity sha512-X7iLzY8pCiYOnvYo2YrK3P9oSE8/3N2f4pUZMJ8IUcZnT81vlSonya1KTO9ZfKGuC+svE6FHK/XOb8SsoRUV1A== + dependencies: + "@jest/types" "^27.2.5" + jest-regex-util "^27.0.6" + jest-snapshot "^27.3.1" + jest-resolve@^26.6.2: version "26.6.2" resolved "https://registry.npmjs.org/jest-resolve/-/jest-resolve-26.6.2.tgz#a3ab1517217f469b504f1b56603c5bb541fbb507" @@ -5803,6 +6320,22 @@ jest-resolve@^26.6.2: resolve "^1.18.1" slash "^3.0.0" +jest-resolve@^27.3.1: + version "27.3.1" + resolved "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.3.1.tgz#0e5542172a1aa0270be6f66a65888647bdd74a3e" + integrity sha512-Dfzt25CFSPo3Y3GCbxynRBZzxq9AdyNN+x/v2IqYx6KVT5Z6me2Z/PsSGFSv3cOSUZqJ9pHxilao/I/m9FouLw== + dependencies: + "@jest/types" "^27.2.5" + chalk "^4.0.0" + graceful-fs "^4.2.4" + jest-haste-map "^27.3.1" + jest-pnp-resolver "^1.2.2" + jest-util "^27.3.1" + jest-validate "^27.3.1" + resolve "^1.20.0" + resolve.exports "^1.1.0" + slash "^3.0.0" + jest-runner@^26.6.3: version "26.6.3" resolved "https://registry.npmjs.org/jest-runner/-/jest-runner-26.6.3.tgz#2d1fed3d46e10f233fd1dbd3bfaa3fe8924be159" @@ -5829,6 +6362,34 @@ jest-runner@^26.6.3: source-map-support "^0.5.6" throat "^5.0.0" +jest-runner@^27.3.1: + version "27.3.1" + resolved "https://registry.npmjs.org/jest-runner/-/jest-runner-27.3.1.tgz#1d594dcbf3bd8600a7e839e790384559eaf96e3e" + integrity sha512-r4W6kBn6sPr3TBwQNmqE94mPlYVn7fLBseeJfo4E2uCTmAyDFm2O5DYAQAFP7Q3YfiA/bMwg8TVsciP7k0xOww== + dependencies: + "@jest/console" "^27.3.1" + "@jest/environment" "^27.3.1" + "@jest/test-result" "^27.3.1" + "@jest/transform" "^27.3.1" + "@jest/types" "^27.2.5" + "@types/node" "*" + chalk "^4.0.0" + emittery "^0.8.1" + exit "^0.1.2" + graceful-fs "^4.2.4" + jest-docblock "^27.0.6" + jest-environment-jsdom "^27.3.1" + jest-environment-node "^27.3.1" + jest-haste-map "^27.3.1" + jest-leak-detector "^27.3.1" + jest-message-util "^27.3.1" + jest-resolve "^27.3.1" + jest-runtime "^27.3.1" + jest-util "^27.3.1" + jest-worker "^27.3.1" + source-map-support "^0.5.6" + throat "^6.0.1" + jest-runtime@^26.6.3: version "26.6.3" resolved "https://registry.npmjs.org/jest-runtime/-/jest-runtime-26.6.3.tgz#4f64efbcfac398331b74b4b3c82d27d401b8fa2b" @@ -5862,6 +6423,38 @@ jest-runtime@^26.6.3: strip-bom "^4.0.0" yargs "^15.4.1" +jest-runtime@^27.3.1: + version "27.3.1" + resolved "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.3.1.tgz#80fa32eb85fe5af575865ddf379874777ee993d7" + integrity sha512-qtO6VxPbS8umqhEDpjA4pqTkKQ1Hy4ZSi9mDVeE9Za7LKBo2LdW2jmT+Iod3XFaJqINikZQsn2wEi0j9wPRbLg== + dependencies: + "@jest/console" "^27.3.1" + "@jest/environment" "^27.3.1" + "@jest/globals" "^27.3.1" + "@jest/source-map" "^27.0.6" + "@jest/test-result" "^27.3.1" + "@jest/transform" "^27.3.1" + "@jest/types" "^27.2.5" + "@types/yargs" "^16.0.0" + chalk "^4.0.0" + cjs-module-lexer "^1.0.0" + collect-v8-coverage "^1.0.0" + execa "^5.0.0" + exit "^0.1.2" + glob "^7.1.3" + graceful-fs "^4.2.4" + jest-haste-map "^27.3.1" + jest-message-util "^27.3.1" + jest-mock "^27.3.0" + jest-regex-util "^27.0.6" + jest-resolve "^27.3.1" + jest-snapshot "^27.3.1" + jest-util "^27.3.1" + jest-validate "^27.3.1" + slash "^3.0.0" + strip-bom "^4.0.0" + yargs "^16.2.0" + jest-serializer@^26.6.2: version "26.6.2" resolved "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.6.2.tgz#d139aafd46957d3a448f3a6cdabe2919ba0742d1" @@ -5870,6 +6463,14 @@ jest-serializer@^26.6.2: "@types/node" "*" graceful-fs "^4.2.4" +jest-serializer@^27.0.6: + version "27.0.6" + resolved "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.0.6.tgz#93a6c74e0132b81a2d54623251c46c498bb5bec1" + integrity sha512-PtGdVK9EGC7dsaziskfqaAPib6wTViY3G8E5wz9tLVPhHyiDNTZn/xjZ4khAw+09QkoOVpn7vF5nPSN6dtBexA== + dependencies: + "@types/node" "*" + graceful-fs "^4.2.4" + jest-snapshot@^26.6.2: version "26.6.2" resolved "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-26.6.2.tgz#f3b0af1acb223316850bd14e1beea9837fb39c84" @@ -5892,6 +6493,36 @@ jest-snapshot@^26.6.2: pretty-format "^26.6.2" semver "^7.3.2" +jest-snapshot@^27.3.1: + version "27.3.1" + resolved "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.3.1.tgz#1da5c0712a252d70917d46c037054f5918c49ee4" + integrity sha512-APZyBvSgQgOT0XumwfFu7X3G5elj6TGhCBLbBdn3R1IzYustPGPE38F51dBWMQ8hRXa9je0vAdeVDtqHLvB6lg== + dependencies: + "@babel/core" "^7.7.2" + "@babel/generator" "^7.7.2" + "@babel/parser" "^7.7.2" + "@babel/plugin-syntax-typescript" "^7.7.2" + "@babel/traverse" "^7.7.2" + "@babel/types" "^7.0.0" + "@jest/transform" "^27.3.1" + "@jest/types" "^27.2.5" + "@types/babel__traverse" "^7.0.4" + "@types/prettier" "^2.1.5" + babel-preset-current-node-syntax "^1.0.0" + chalk "^4.0.0" + expect "^27.3.1" + graceful-fs "^4.2.4" + jest-diff "^27.3.1" + jest-get-type "^27.3.1" + jest-haste-map "^27.3.1" + jest-matcher-utils "^27.3.1" + jest-message-util "^27.3.1" + jest-resolve "^27.3.1" + jest-util "^27.3.1" + natural-compare "^1.4.0" + pretty-format "^27.3.1" + semver "^7.3.2" + jest-util@^26.1.0, jest-util@^26.6.2: version "26.6.2" resolved "https://registry.npmjs.org/jest-util/-/jest-util-26.6.2.tgz#907535dbe4d5a6cb4c47ac9b926f6af29576cbc1" @@ -5904,6 +6535,18 @@ jest-util@^26.1.0, jest-util@^26.6.2: is-ci "^2.0.0" micromatch "^4.0.2" +jest-util@^27.3.1: + version "27.3.1" + resolved "https://registry.npmjs.org/jest-util/-/jest-util-27.3.1.tgz#a58cdc7b6c8a560caac9ed6bdfc4e4ff23f80429" + integrity sha512-8fg+ifEH3GDryLQf/eKZck1DEs2YuVPBCMOaHQxVVLmQwl/CDhWzrvChTX4efLZxGrw+AA0mSXv78cyytBt/uw== + dependencies: + "@jest/types" "^27.2.5" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.4" + picomatch "^2.2.3" + jest-validate@^26.6.2: version "26.6.2" resolved "https://registry.npmjs.org/jest-validate/-/jest-validate-26.6.2.tgz#23d380971587150467342911c3d7b4ac57ab20ec" @@ -5916,6 +6559,18 @@ jest-validate@^26.6.2: leven "^3.1.0" pretty-format "^26.6.2" +jest-validate@^27.3.1: + version "27.3.1" + resolved "https://registry.npmjs.org/jest-validate/-/jest-validate-27.3.1.tgz#3a395d61a19cd13ae9054af8cdaf299116ef8a24" + integrity sha512-3H0XCHDFLA9uDII67Bwi1Vy7AqwA5HqEEjyy934lgVhtJ3eisw6ShOF1MDmRPspyikef5MyExvIm0/TuLzZ86Q== + dependencies: + "@jest/types" "^27.2.5" + camelcase "^6.2.0" + chalk "^4.0.0" + jest-get-type "^27.3.1" + leven "^3.1.0" + pretty-format "^27.3.1" + jest-watcher@^26.6.2: version "26.6.2" resolved "https://registry.npmjs.org/jest-watcher/-/jest-watcher-26.6.2.tgz#a5b683b8f9d68dbcb1d7dae32172d2cca0592975" @@ -5929,6 +6584,19 @@ jest-watcher@^26.6.2: jest-util "^26.6.2" string-length "^4.0.1" +jest-watcher@^27.3.1: + version "27.3.1" + resolved "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.3.1.tgz#ba5e0bc6aa843612b54ddb7f009d1cbff7e05f3e" + integrity sha512-9/xbV6chABsGHWh9yPaAGYVVKurWoP3ZMCv6h+O1v9/+pkOroigs6WzZ0e9gLP/njokUwM7yQhr01LKJVMkaZA== + dependencies: + "@jest/test-result" "^27.3.1" + "@jest/types" "^27.2.5" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + jest-util "^27.3.1" + string-length "^4.0.1" + jest-worker@^26.6.2: version "26.6.2" resolved "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" @@ -5938,6 +6606,15 @@ jest-worker@^26.6.2: merge-stream "^2.0.0" supports-color "^7.0.0" +jest-worker@^27.3.1: + version "27.3.1" + resolved "https://registry.npmjs.org/jest-worker/-/jest-worker-27.3.1.tgz#0def7feae5b8042be38479799aeb7b5facac24b2" + integrity sha512-ks3WCzsiZaOPJl/oMsDjaf0TRiSv7ctNgs0FqRr2nARsovz6AWWy4oLElwcquGSz692DzgZQrCLScPNs5YlC4g== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + jest@^26.6.3: version "26.6.3" resolved "https://registry.npmjs.org/jest/-/jest-26.6.3.tgz#40e8fdbe48f00dfa1f0ce8121ca74b88ac9148ef" @@ -5947,6 +6624,15 @@ jest@^26.6.3: import-local "^3.0.2" jest-cli "^26.6.3" +jest@^27.3.1: + version "27.3.1" + resolved "https://registry.npmjs.org/jest/-/jest-27.3.1.tgz#b5bab64e8f56b6f7e275ba1836898b0d9f1e5c8a" + integrity sha512-U2AX0AgQGd5EzMsiZpYt8HyZ+nSVIh5ujQ9CPp9EQZJMjXIiSZpJNweZl0swatKRoqHWgGKM3zaSwm4Zaz87ng== + dependencies: + "@jest/core" "^27.3.1" + import-local "^3.0.2" + jest-cli "^27.3.1" + jmespath@0.15.0: version "0.15.0" resolved "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz#a3f222a9aae9f966f5d27c796510e28091764217" @@ -5982,7 +6668,7 @@ jsbn@~0.1.0: resolved "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= -jsdom@^16.4.0: +jsdom@^16.4.0, jsdom@^16.6.0: version "16.7.0" resolved "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz#918ae71965424b197c819f8183a754e18977b710" integrity sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw== @@ -7286,6 +7972,11 @@ null-check@^1.0.0: resolved "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz#977dffd7176012b9ec30d2a39db5cf72a0439edd" integrity sha1-l33/1xdgErnsMNKjnbXPcqBDnt0= +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + nwsapi@^2.2.0: version "2.2.0" resolved "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" @@ -7873,6 +8564,16 @@ pretty-format@^26.0.0, pretty-format@^26.6.2: ansi-styles "^4.0.0" react-is "^17.0.1" +pretty-format@^27.3.1: + version "27.3.1" + resolved "https://registry.npmjs.org/pretty-format/-/pretty-format-27.3.1.tgz#7e9486365ccdd4a502061fa761d3ab9ca1b78df5" + integrity sha512-DR/c+pvFc52nLimLROYjnXPtolawm+uWDxr4FjuLDLUn+ktWnSN851KoHwHzzqq6rfCOjkzN8FLgDrSub6UDuA== + dependencies: + "@jest/types" "^27.2.5" + ansi-regex "^5.0.1" + ansi-styles "^5.0.0" + react-is "^17.0.1" + printj@~1.1.0: version "1.1.2" resolved "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz#d90deb2975a8b9f600fb3a1c94e3f4c53c78a222" @@ -8321,6 +9022,11 @@ resolve-url@^0.2.1: resolved "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= +resolve.exports@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9" + integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ== + resolve@^1.10.0, resolve@^1.10.1, resolve@^1.11.1, resolve@^1.18.1, resolve@^1.20.0: version "1.20.0" resolved "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" @@ -8830,7 +9536,7 @@ ssri@^8.0.0, ssri@^8.0.1: dependencies: minipass "^3.1.1" -stack-utils@^2.0.2: +stack-utils@^2.0.2, stack-utils@^2.0.3: version "2.0.5" resolved "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz#d25265fca995154659dbbfba3b49254778d2fdd5" integrity sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA== @@ -8893,7 +9599,7 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -string-width@*, string-width@^1.0.1, "string-width@^1.0.2 || 2", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +string-width@*, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -8902,6 +9608,23 @@ string-width@*, string-width@^1.0.1, "string-width@^1.0.2 || 2", string-width@^4 is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +"string-width@^1.0.2 || 2": + version "2.1.1" + resolved "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + string.prototype.repeat@^0.2.0: version "0.2.0" resolved "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-0.2.0.tgz#aba36de08dcee6a5a337d49b2ea1da1b28fc0ecf" @@ -8954,6 +9677,13 @@ strip-ansi@^3.0.0, strip-ansi@^3.0.1: dependencies: ansi-regex "^2.0.0" +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0" + strip-ansi@^5.2.0: version "5.2.0" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" @@ -9023,6 +9753,13 @@ supports-color@^7.0.0, supports-color@^7.1.0, supports-color@^7.2.0: dependencies: has-flag "^4.0.0" +supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + supports-hyperlinks@^2.0.0: version "2.2.0" resolved "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz#4f77b42488765891774b70c79babd87f9bd594bb" @@ -9145,6 +9882,11 @@ throat@^5.0.0: resolved "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b" integrity sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA== +throat@^6.0.1: + version "6.0.1" + resolved "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz#d514fedad95740c12c2d7fc70ea863eb51ade375" + integrity sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w== + through2@^2.0.0: version "2.0.5" resolved "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" @@ -9607,6 +10349,15 @@ v8-to-istanbul@^7.0.0: convert-source-map "^1.6.0" source-map "^0.7.3" +v8-to-istanbul@^8.1.0: + version "8.1.0" + resolved "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.0.tgz#0aeb763894f1a0a1676adf8a8b7612a38902446c" + integrity sha512-/PRhfd8aTNp9Ggr62HPzXg2XasNFGy5PBt0Rp04du7/8GNNSgxFL6WBTkgMKSL9bFjH+8kKEG3f37FmxiTqUUA== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^1.6.0" + source-map "^0.7.3" + validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.4: version "3.0.4" resolved "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" From e1bf1b9e1813bf3964f3fd63139dc814fde8d8fb Mon Sep 17 00:00:00 2001 From: kaizen3031593 <36202692+kaizen3031593@users.noreply.github.com> Date: Mon, 25 Oct 2021 23:13:31 -0400 Subject: [PATCH 35/87] docs(stepfunctions): make examples compile (#17141) ---- *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-stepfunctions/README.md | 135 ++++++++++++------ .../rosetta/default.ts-fixture | 14 ++ .../scripts/verify-readme-import-rewrites.ts | 4 +- 3 files changed, 107 insertions(+), 46 deletions(-) create mode 100644 packages/@aws-cdk/aws-stepfunctions/rosetta/default.ts-fixture diff --git a/packages/@aws-cdk/aws-stepfunctions/README.md b/packages/@aws-cdk/aws-stepfunctions/README.md index 52aa717e6d1a2..e74367df84676 100644 --- a/packages/@aws-cdk/aws-stepfunctions/README.md +++ b/packages/@aws-cdk/aws-stepfunctions/README.md @@ -22,13 +22,10 @@ example](https://docs.aws.amazon.com/step-functions/latest/dg/job-status-poller- ## Example ```ts -import * as cdk from '@aws-cdk/core'; -import * as sfn from '@aws-cdk/aws-stepfunctions'; -import * as tasks from '@aws-cdk/aws-stepfunctions-tasks'; import * as lambda from '@aws-cdk/aws-lambda'; -const submitLambda = new lambda.Function(this, 'SubmitLambda', { ... }); -const getStatusLambda = new lambda.Function(this, 'CheckLambda', { ... }); +declare const submitLambda: lambda.Function; +declare const getStatusLambda: lambda.Function; const submitJob = new tasks.LambdaInvoke(this, 'Submit Job', { lambdaFunction: submitLambda, @@ -71,7 +68,7 @@ const definition = submitJob new sfn.StateMachine(this, 'StateMachine', { definition, - timeout: cdk.Duration.minutes(5), + timeout: Duration.minutes(5), }); ``` @@ -145,6 +142,7 @@ const pass = new sfn.Pass(this, 'Add Hello World', { }); // Set the next state +const nextState = new sfn.Pass(this, 'NextState'); pass.next(nextState); ``` @@ -183,6 +181,7 @@ const wait = new sfn.Wait(this, 'Wait For Trigger Time', { }); // Set the next state +const startTheWork = new sfn.Pass(this, 'StartTheWork'); wait.next(startTheWork); ``` @@ -195,10 +194,13 @@ values in the execution's JSON state: const choice = new sfn.Choice(this, 'Did it work?'); // Add conditions with .when() +const successState = new sfn.Pass(this, 'SuccessState'); +const failureState = new sfn.Pass(this, 'FailureState'); choice.when(sfn.Condition.stringEquals('$.status', 'SUCCESS'), successState); choice.when(sfn.Condition.numberGreaterThan('$.attempts', 5), failureState); // Use .otherwise() to indicate what should be done if none of the conditions match +const tryAgainState = new sfn.Pass(this, 'TryAgainState'); choice.otherwise(tryAgainState); ``` @@ -208,11 +210,15 @@ then ... else` works in a programming language), use the `.afterwards()` method: ```ts const choice = new sfn.Choice(this, 'What color is it?'); +const handleBlueItem = new sfn.Pass(this, 'HandleBlueItem'); +const handleRedItem = new sfn.Pass(this, 'HandleRedItem'); +const handleOtherItemColor = new sfn.Pass(this, 'HanldeOtherItemColor'); choice.when(sfn.Condition.stringEquals('$.color', 'BLUE'), handleBlueItem); choice.when(sfn.Condition.stringEquals('$.color', 'RED'), handleRedItem); choice.otherwise(handleOtherItemColor); // Use .afterwards() to join all possible paths back together and continue +const shipTheItem = new sfn.Pass(this, 'ShipTheItem'); choice.afterwards().next(shipTheItem); ``` @@ -279,6 +285,9 @@ be used to catch and recover from errors in subworkflows. const parallel = new sfn.Parallel(this, 'Do the work in parallel'); // Add branches to be executed in parallel +const shipItem = new sfn.Pass(this, 'ShipItem'); +const sendInvoice = new sfn.Pass(this, 'SendInvoice'); +const restock = new sfn.Pass(this, 'Restock'); parallel.branch(shipItem); parallel.branch(sendInvoice); parallel.branch(restock); @@ -287,9 +296,11 @@ parallel.branch(restock); parallel.addRetry({ maxAttempts: 1 }); // How to recover from errors +const sendFailureNotification = new sfn.Pass(this, 'SendFailureNotification'); parallel.addCatch(sendFailureNotification); // What to do in case everything succeeded +const closeOrder = new sfn.Pass(this, 'CloseOrder'); parallel.next(closeOrder); ``` @@ -354,19 +365,17 @@ the State Machine uses. The following example uses the `DynamoDB` service integration to insert data into a DynamoDB table. ```ts -import * as cdk from '@aws-cdk/core'; -import * as ddb from '@aws-cdk/aws-dynamodb'; -import * as sfn from '@aws-cdk/aws-stepfunctions'; +import * as dynamodb from '@aws-cdk/aws-dynamodb'; // create a table -const table = new ddb.Table(this, 'montable', { +const table = new dynamodb.Table(this, 'montable', { partitionKey: { name: 'id', - type: ddb.AttributeType.STRING, + type: dynamodb.AttributeType.STRING, }, }); -const finalStatus = new sfn.Pass(stack, 'final step'); +const finalStatus = new sfn.Pass(this, 'final step'); // States language JSON to put an item into DynamoDB // snippet generated from https://docs.aws.amazon.com/step-functions/latest/dg/tutorial-code-snippet.html#tutorial-code-snippet-1 @@ -394,7 +403,7 @@ const chain = sfn.Chain.start(custom) const sm = new sfn.StateMachine(this, 'StateMachine', { definition: chain, - timeout: cdk.Duration.seconds(30), + timeout: Duration.seconds(30), }); // don't forget permissions. You need to assign them @@ -410,6 +419,21 @@ In particular, the `.next()` method can be repeated. The result of a series of targets of `Choice.on` or `Parallel.branch`: ```ts +const step1 = new sfn.Pass(this, 'Step1'); +const step2 = new sfn.Pass(this, 'Step2'); +const step3 = new sfn.Pass(this, 'Step3'); +const step4 = new sfn.Pass(this, 'Step4'); +const step5 = new sfn.Pass(this, 'Step5'); +const step6 = new sfn.Pass(this, 'Step6'); +const step7 = new sfn.Pass(this, 'Step7'); +const step8 = new sfn.Pass(this, 'Step8'); +const step9 = new sfn.Pass(this, 'Step9'); +const step10 = new sfn.Pass(this, 'Step10'); +const choice = new sfn.Choice(this, 'Choice'); +const condition1 = sfn.Condition.stringEquals('$.status', 'SUCCESS'); +const parallel = new sfn.Parallel(this, 'Parallel'); +const finish = new sfn.Pass(this, 'Finish'); + const definition = step1 .next(step2) .next(choice @@ -430,6 +454,10 @@ If you don't like the visual look of starting a chain directly off the first step, you can use `Chain.start`: ```ts +const step1 = new sfn.Pass(this, 'Step1'); +const step2 = new sfn.Pass(this, 'Step2'); +const step3 = new sfn.Pass(this, 'Step3'); + const definition = sfn.Chain .start(step1) .next(step2) @@ -456,7 +484,11 @@ The class `StateMachineFragment` contains some helper functions (like `prefixStates()`) to make it easier for you to do this. If you define your state machine as a subclass of this, it will be convenient to use: -```ts +```ts nofixture +import { Construct, Stack } from '@aws-cdk/core'; +import * as sfn from '@aws-cdk/aws-stepfunctions'; +import * as tasks from '@aws-cdk/aws-stepfunctions-tasks'; + interface MyJobProps { jobFlavor: string; } @@ -465,23 +497,30 @@ class MyJob extends sfn.StateMachineFragment { public readonly startState: sfn.State; public readonly endStates: sfn.INextable[]; - constructor(parent: cdk.Construct, id: string, props: MyJobProps) { + constructor(parent: Construct, id: string, props: MyJobProps) { super(parent, id); - const first = new sfn.Task(this, 'First', { ... }); + const choice = new sfn.Choice(this, 'Choice') + .when(sfn.Condition.stringEquals('$.branch', 'left'), new sfn.Pass(this, 'Left Branch')) + .when(sfn.Condition.stringEquals('$.branch', 'right'), new sfn.Pass(this, 'Right Branch')); + // ... - const last = new sfn.Task(this, 'Last', { ... }); - this.startState = first; - this.endStates = [last]; + this.startState = choice; + this.endStates = choice.afterwards().endStates; } } -// Do 3 different variants of MyJob in parallel -new sfn.Parallel(this, 'All jobs') - .branch(new MyJob(this, 'Quick', { jobFlavor: 'quick' }).prefixStates()) - .branch(new MyJob(this, 'Medium', { jobFlavor: 'medium' }).prefixStates()) - .branch(new MyJob(this, 'Slow', { jobFlavor: 'slow' }).prefixStates()); +class MyStack extends Stack { + constructor(scope: Construct, id: string) { + super(scope, id); + // Do 3 different variants of MyJob in parallel + new sfn.Parallel(this, 'All jobs') + .branch(new MyJob(this, 'Quick', { jobFlavor: 'quick' }).prefixStates()) + .branch(new MyJob(this, 'Medium', { jobFlavor: 'medium' }).prefixStates()) + .branch(new MyJob(this, 'Slow', { jobFlavor: 'slow' }).prefixStates()); + } +} ``` A few utility functions are available to parse state machine fragments. @@ -504,7 +543,7 @@ const activity = new sfn.Activity(this, 'Activity'); // Read this CloudFormation Output from your application and use it to poll for work on // the activity. -new cdk.CfnOutput(this, 'ActivityArn', { value: activity.activityArn }); +new CfnOutput(this, 'ActivityArn', { value: activity.activityArn }); ``` ### Activity-Level Permissions @@ -514,7 +553,7 @@ Granting IAM permissions to an activity can be achieved by calling the `grant(pr ```ts const activity = new sfn.Activity(this, 'Activity'); -const role = new iam.Role(stack, 'Role', { +const role = new iam.Role(this, 'Role', { assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'), }); @@ -529,6 +568,7 @@ This will grant the IAM principal the specified actions onto the activity. to create an alarm on a particular task failing: ```ts +declare const task: sfn.Task; new cloudwatch.Alarm(this, 'TaskAlarm', { metric: task.metricFailed(), threshold: 1, @@ -539,6 +579,7 @@ new cloudwatch.Alarm(this, 'TaskAlarm', { There are also metrics on the complete state machine: ```ts +declare const stateMachine: sfn.StateMachine; new cloudwatch.Alarm(this, 'StateMachineAlarm', { metric: stateMachine.metricFailed(), threshold: 1, @@ -550,7 +591,7 @@ And there are metrics on the capacity of all state machines in your account: ```ts new cloudwatch.Alarm(this, 'ThrottledAlarm', { - metric: StateTransitionMetrics.metricThrottledEvents(), + metric: sfn.StateTransitionMetric.metricThrottledEvents(), threshold: 10, evaluationPeriods: 2, }); @@ -578,10 +619,12 @@ Enable logging to CloudWatch by passing a logging configuration with a destination LogGroup: ```ts -const logGroup = new logs.LogGroup(stack, 'MyLogGroup'); +import * as logs from '@aws-cdk/aws-logs'; + +const logGroup = new logs.LogGroup(this, 'MyLogGroup'); -new sfn.StateMachine(stack, 'MyStateMachine', { - definition: sfn.Chain.start(new sfn.Pass(stack, 'Pass')), +new sfn.StateMachine(this, 'MyStateMachine', { + definition: sfn.Chain.start(new sfn.Pass(this, 'Pass')), logs: { destination: logGroup, level: sfn.LogLevel.ALL, @@ -594,8 +637,8 @@ new sfn.StateMachine(stack, 'MyStateMachine', { Enable X-Ray tracing for StateMachine: ```ts -new sfn.StateMachine(stack, 'MyStateMachine', { - definition: sfn.Chain.start(new sfn.Pass(stack, 'Pass')), +new sfn.StateMachine(this, 'MyStateMachine', { + definition: sfn.Chain.start(new sfn.Pass(this, 'Pass')), tracingEnabled: true, }); ``` @@ -620,11 +663,12 @@ Any object that implements the `IGrantable` interface (has an associated princip Grant permission to start an execution of a state machine by calling the `grantStartExecution()` API. ```ts -const role = new iam.Role(stack, 'Role', { +const role = new iam.Role(this, 'Role', { assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'), }); -const stateMachine = new stepfunction.StateMachine(stack, 'StateMachine', { +declare const definition: sfn.IChainable; +const stateMachine = new sfn.StateMachine(this, 'StateMachine', { definition, }); @@ -641,11 +685,12 @@ The following permission is provided to a service principal by the `grantStartEx Grant `read` access to a state machine by calling the `grantRead()` API. ```ts -const role = new iam.Role(stack, 'Role', { +const role = new iam.Role(this, 'Role', { assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'), }); -const stateMachine = new stepfunction.StateMachine(stack, 'StateMachine', { +declare const definition: sfn.IChainable; +const stateMachine = new sfn.StateMachine(this, 'StateMachine', { definition, }); @@ -669,11 +714,12 @@ The following read permissions are provided to a service principal by the `grant Grant permission to allow task responses to a state machine by calling the `grantTaskResponse()` API: ```ts -const role = new iam.Role(stack, 'Role', { +const role = new iam.Role(this, 'Role', { assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'), }); -const stateMachine = new stepfunction.StateMachine(stack, 'StateMachine', { +declare const definition: sfn.IChainable; +const stateMachine = new sfn.StateMachine(this, 'StateMachine', { definition, }); @@ -692,11 +738,12 @@ The following read permissions are provided to a service principal by the `grant Grant execution-level permissions to a state machine by calling the `grantExecution()` API: ```ts -const role = new iam.Role(stack, 'Role', { +const role = new iam.Role(this, 'Role', { assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'), }); -const stateMachine = new stepfunction.StateMachine(stack, 'StateMachine', { +declare const definition: sfn.IChainable; +const stateMachine = new sfn.StateMachine(this, 'StateMachine', { definition, }); @@ -709,9 +756,10 @@ stateMachine.grantExecution(role, 'states:GetExecutionHistory'); You can add any set of permissions to a state machine by calling the `grant()` API. ```ts -const user = new iam.User(stack, 'MyUser'); +const user = new iam.User(this, 'MyUser'); -const stateMachine = new stepfunction.StateMachine(stack, 'StateMachine', { +declare const definition: sfn.IChainable; +const stateMachine = new sfn.StateMachine(this, 'StateMachine', { definition, }); @@ -727,8 +775,7 @@ into your CDK stack. State machines can be imported by their ARN via the `StateMachine.fromStateMachineArn()` API ```ts -import * as sfn from 'aws-stepfunctions'; - +const app = new App(); const stack = new Stack(app, 'MyStack'); sfn.StateMachine.fromStateMachineArn( stack, diff --git a/packages/@aws-cdk/aws-stepfunctions/rosetta/default.ts-fixture b/packages/@aws-cdk/aws-stepfunctions/rosetta/default.ts-fixture new file mode 100644 index 0000000000000..91085b6c8933c --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions/rosetta/default.ts-fixture @@ -0,0 +1,14 @@ +// Fixture with packages imported, but nothing else +import { Construct } from 'constructs'; +import { App, CfnOutput, Duration, Stack } from '@aws-cdk/core'; +import sfn = require('@aws-cdk/aws-stepfunctions'); +import tasks = require('@aws-cdk/aws-stepfunctions-tasks'); +import cloudwatch = require('@aws-cdk/aws-cloudwatch'); +import iam = require('@aws-cdk/aws-iam'); + +class Fixture extends Stack { + constructor(scope: Construct, id: string) { + super(scope, id); + /// here + } +} diff --git a/packages/aws-cdk-lib/scripts/verify-readme-import-rewrites.ts b/packages/aws-cdk-lib/scripts/verify-readme-import-rewrites.ts index a31f721c05dfc..a2e3569573ef4 100644 --- a/packages/aws-cdk-lib/scripts/verify-readme-import-rewrites.ts +++ b/packages/aws-cdk-lib/scripts/verify-readme-import-rewrites.ts @@ -23,7 +23,7 @@ const jsiiManifest = JSON.parse(fs.readFileSync(jsiiManifestPath, { encoding: 'u // If this test fails because one of the below import statements is invalid, // please update to have a new, comparable example. // This is admittedly a bit fragile; if this test breaks a lot, we should reconsider validation methodology. -// Count of times this test has been broken by README updates so far (please increment as necessary! :D): 0 +// Count of times this test has been broken by README updates so far (please increment as necessary! :D): 1 const EXPECTED_SUBMODULE_IMPORTS = { // import * as origins from '@aws-cdk/aws-cloudfront-origins'; 'aws-cdk-lib.aws_cloudfront_origins': "import { aws_cloudfront_origins as origins } from 'aws-cdk-lib';", @@ -34,7 +34,7 @@ const EXPECTED_SUBMODULE_IMPORTS = { // import { Rule, Schedule } from '@aws-cdk/aws-events'; 'aws-cdk-lib.aws_events': "import { Rule, Schedule } from 'aws-cdk-lib/aws-events';", // import * as cdk from '@aws-cdk/core'; - 'aws-cdk-lib.aws_stepfunctions': "import * as cdk from 'aws-cdk-lib';", + 'aws-cdk-lib.aws_rds': "import * as cdk from 'aws-cdk-lib';", }; Object.entries(EXPECTED_SUBMODULE_IMPORTS).forEach(([submodule, importStatement]) => { From 55d3c507707192d7aa5ea4a38ee0d1cb58f07e06 Mon Sep 17 00:00:00 2001 From: Hassan Azhar <57677979+hassanazharkhan@users.noreply.github.com> Date: Tue, 26 Oct 2021 14:11:41 +0500 Subject: [PATCH 36/87] feat(lambda-nodejs): typescript emitDecoratorMetadata support (#16543) closes [#13767](https://github.com/aws/aws-cdk/issues/13767) ---- *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-lambda-nodejs/README.md | 16 ++ .../@aws-cdk/aws-lambda-nodejs/lib/Dockerfile | 3 + .../aws-lambda-nodejs/lib/bundling.ts | 64 +++++- ...nstallation.ts => package-installation.ts} | 14 +- .../@aws-cdk/aws-lambda-nodejs/lib/types.ts | 10 + .../aws-lambda-nodejs/test/bundling.test.ts | 109 +++++++++- .../integ-handlers/ts-decorator-handler.ts | 23 ++ .../test/integ.compilations.expected.json | 198 ++++++++++++++++++ .../test/integ.compilations.ts | 39 ++++ ...n.test.ts => package-installation.test.ts} | 8 +- 10 files changed, 460 insertions(+), 24 deletions(-) rename packages/@aws-cdk/aws-lambda-nodejs/lib/{esbuild-installation.ts => package-installation.ts} (59%) create mode 100644 packages/@aws-cdk/aws-lambda-nodejs/test/integ-handlers/ts-decorator-handler.ts create mode 100644 packages/@aws-cdk/aws-lambda-nodejs/test/integ.compilations.expected.json create mode 100644 packages/@aws-cdk/aws-lambda-nodejs/test/integ.compilations.ts rename packages/@aws-cdk/aws-lambda-nodejs/test/{esbuild-installation.test.ts => package-installation.test.ts} (84%) diff --git a/packages/@aws-cdk/aws-lambda-nodejs/README.md b/packages/@aws-cdk/aws-lambda-nodejs/README.md index 2c0572231a8ae..6e901612539d8 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/README.md +++ b/packages/@aws-cdk/aws-lambda-nodejs/README.md @@ -225,6 +225,22 @@ an array of commands to run. Commands are chained with `&&`. The commands will run in the environment in which bundling occurs: inside the container for Docker bundling or on the host OS for local bundling. +## Pre Compilation with TSC + +In some cases, `esbuild` may not yet support some newer features of the typescript language, such as, +[`emitDecoratorMetadata`](https://www.typescriptlang.org/tsconfig#emitDecoratorMetadata). +In such cases, it is possible to run pre-compilation using `tsc` by setting the `preCompilation` flag. + +```ts +new lambda.NodejsFunction(this, 'my-handler', { + bundling: { + preCompilation: true, + }, +}); +``` + +Note: A [`tsconfig.json` file](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) is required + ## Customizing Docker bundling Use `bundling.environment` to define environments variables when `esbuild` runs: diff --git a/packages/@aws-cdk/aws-lambda-nodejs/lib/Dockerfile b/packages/@aws-cdk/aws-lambda-nodejs/lib/Dockerfile index 578b1b8135d5c..54969bb5fde2c 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/lib/Dockerfile +++ b/packages/@aws-cdk/aws-lambda-nodejs/lib/Dockerfile @@ -9,6 +9,9 @@ RUN npm install --global yarn@1.22.5 # Install pnpm RUN npm install --global pnpm +# Install typescript +RUN npm install --global typescript + # Install esbuild # (unsafe-perm because esbuild has a postinstall script) ARG ESBUILD_VERSION=0 diff --git a/packages/@aws-cdk/aws-lambda-nodejs/lib/bundling.ts b/packages/@aws-cdk/aws-lambda-nodejs/lib/bundling.ts index 3db8b21c3f592..e53e5e092de7c 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/lib/bundling.ts +++ b/packages/@aws-cdk/aws-lambda-nodejs/lib/bundling.ts @@ -2,7 +2,7 @@ import * as os from 'os'; import * as path from 'path'; import { Architecture, AssetCode, Code, Runtime } from '@aws-cdk/aws-lambda'; import * as cdk from '@aws-cdk/core'; -import { EsbuildInstallation } from './esbuild-installation'; +import { PackageInstallation } from './package-installation'; import { PackageManager } from './package-manager'; import { BundlingOptions, SourceMapMode } from './types'; import { exec, extractDependencies, findUp } from './util'; @@ -37,6 +37,12 @@ export interface BundlingProps extends BundlingOptions { * Path to project root */ readonly projectRoot: string; + + /** + * Run compilation using `tsc` before bundling + */ + readonly preCompilation?: boolean + } /** @@ -57,7 +63,17 @@ export class Bundling implements cdk.BundlingOptions { this.esbuildInstallation = undefined; } - private static esbuildInstallation?: EsbuildInstallation; + public static clearTscInstallationCache(): void { + this.tscInstallation = undefined; + } + + public static clearTscCompilationCache(): void { + this.tscCompiled = false; + } + + private static esbuildInstallation?: PackageInstallation; + private static tscInstallation?: PackageInstallation; + private static tscCompiled = false // Core bundling options public readonly image: cdk.DockerImage; @@ -76,7 +92,8 @@ export class Bundling implements cdk.BundlingOptions { constructor(private readonly props: BundlingProps) { this.packageManager = PackageManager.fromLockFile(props.depsLockFilePath); - Bundling.esbuildInstallation = Bundling.esbuildInstallation ?? EsbuildInstallation.detect(); + Bundling.esbuildInstallation = Bundling.esbuildInstallation ?? PackageInstallation.detect('esbuild'); + Bundling.tscInstallation = Bundling.tscInstallation ?? PackageInstallation.detect('tsc'); this.projectRoot = props.projectRoot; this.relativeEntryPath = path.relative(this.projectRoot, path.resolve(props.entry)); @@ -90,6 +107,10 @@ export class Bundling implements cdk.BundlingOptions { this.relativeTsconfigPath = path.relative(this.projectRoot, path.resolve(props.tsconfig)); } + if (props.preCompilation && !/\.tsx?$/.test(props.entry)) { + throw new Error('preCompilation can only be used with typescript files'); + } + this.externals = [ ...props.externalModules ?? ['aws-sdk'], // Mark aws-sdk as external by default (available in the runtime) ...props.nodeModules ?? [], // Mark the modules that we are going to install as externals also @@ -97,8 +118,8 @@ export class Bundling implements cdk.BundlingOptions { // Docker bundling const shouldBuildImage = props.forceDockerBundling || !Bundling.esbuildInstallation; - this.image = shouldBuildImage - ? props.dockerImage ?? cdk.DockerImage.fromBuild(path.join(__dirname, '../lib'), { + this.image = shouldBuildImage ? props.dockerImage ?? cdk.DockerImage.fromBuild(path.join(__dirname, '../lib'), + { buildArgs: { ...props.buildArgs ?? {}, IMAGE: props.runtime.bundlingImage.image, @@ -112,6 +133,7 @@ export class Bundling implements cdk.BundlingOptions { inputDir: cdk.AssetStaging.BUNDLING_INPUT_DIR, outputDir: cdk.AssetStaging.BUNDLING_OUTPUT_DIR, esbuildRunner: 'esbuild', // esbuild is installed globally in the docker image + tscRunner: 'tsc', // tsc is installed globally in the docker image osPlatform: 'linux', // linux docker image }); this.command = ['bash', '-c', bundlingCommand]; @@ -128,6 +150,27 @@ export class Bundling implements cdk.BundlingOptions { private createBundlingCommand(options: BundlingCommandOptions): string { const pathJoin = osPathJoin(options.osPlatform); + let tscCommand: string = ''; + let relativeEntryPath = this.relativeEntryPath; + + if (this.props.preCompilation) { + + let tsconfig = this.relativeTsconfigPath; + if (!tsconfig) { + const findConfig = findUp('tsconfig.json', path.dirname(this.props.entry)); + if (!findConfig) { + throw new Error('Cannot find a tsconfig.json, please specify the prop: tsconfig'); + } + tsconfig = path.relative(this.projectRoot, findConfig); + } + + relativeEntryPath = relativeEntryPath.replace(/\.ts(x?)$/, '.js$1'); + if (!Bundling.tscCompiled) { + // Intentionally Setting rootDir and outDir, so that the compiled js file always end up next ts file. + tscCommand = `${options.tscRunner} --project ${pathJoin(options.inputDir, tsconfig)} --rootDir ./ --outDir ./`; + Bundling.tscCompiled = true; + } + } const loaders = Object.entries(this.props.loader ?? {}); const defines = Object.entries(this.props.define ?? {}); @@ -135,14 +178,14 @@ export class Bundling implements cdk.BundlingOptions { if (this.props.sourceMap === false && this.props.sourceMapMode) { throw new Error('sourceMapMode cannot be used when sourceMap is false'); } - // eslint-disable-next-line no-console + const sourceMapEnabled = this.props.sourceMapMode ?? this.props.sourceMap; const sourceMapMode = this.props.sourceMapMode ?? SourceMapMode.DEFAULT; const sourceMapValue = sourceMapMode === SourceMapMode.DEFAULT ? '' : `=${this.props.sourceMapMode}`; const esbuildCommand: string[] = [ options.esbuildRunner, - '--bundle', `"${pathJoin(options.inputDir, this.relativeEntryPath)}"`, + '--bundle', `"${pathJoin(options.inputDir, relativeEntryPath)}"`, `--target=${this.props.target ?? toTarget(this.props.runtime)}`, '--platform=node', `--outfile="${pathJoin(options.outputDir, 'index.js')}"`, @@ -185,6 +228,7 @@ export class Bundling implements cdk.BundlingOptions { return chain([ ...this.props.commandHooks?.beforeBundling(options.inputDir, options.outputDir) ?? [], + tscCommand, esbuildCommand.join(' '), ...(this.props.nodeModules && this.props.commandHooks?.beforeInstall(options.inputDir, options.outputDir)) ?? [], depsCommand, @@ -194,10 +238,11 @@ export class Bundling implements cdk.BundlingOptions { private getLocalBundlingProvider(): cdk.ILocalBundling { const osPlatform = os.platform(); - const createLocalCommand = (outputDir: string, esbuild: EsbuildInstallation) => this.createBundlingCommand({ + const createLocalCommand = (outputDir: string, esbuild: PackageInstallation, tsc?: PackageInstallation) => this.createBundlingCommand({ inputDir: this.projectRoot, outputDir, esbuildRunner: esbuild.isLocal ? this.packageManager.runBinCommand('esbuild') : 'esbuild', + tscRunner: tsc && (tsc.isLocal ? this.packageManager.runBinCommand('tsc') : 'tsc'), osPlatform, }); const environment = this.props.environment ?? {}; @@ -214,7 +259,7 @@ export class Bundling implements cdk.BundlingOptions { throw new Error(`Expected esbuild version ${ESBUILD_MAJOR_VERSION}.x but got ${Bundling.esbuildInstallation.version}`); } - const localCommand = createLocalCommand(outputDir, Bundling.esbuildInstallation); + const localCommand = createLocalCommand(outputDir, Bundling.esbuildInstallation, Bundling.tscInstallation); exec( osPlatform === 'win32' ? 'cmd' : 'bash', @@ -243,6 +288,7 @@ interface BundlingCommandOptions { readonly inputDir: string; readonly outputDir: string; readonly esbuildRunner: string; + readonly tscRunner?: string; readonly osPlatform: NodeJS.Platform; } diff --git a/packages/@aws-cdk/aws-lambda-nodejs/lib/esbuild-installation.ts b/packages/@aws-cdk/aws-lambda-nodejs/lib/package-installation.ts similarity index 59% rename from packages/@aws-cdk/aws-lambda-nodejs/lib/esbuild-installation.ts rename to packages/@aws-cdk/aws-lambda-nodejs/lib/package-installation.ts index 8ef2e8dbb23d9..789246badcceb 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/lib/esbuild-installation.ts +++ b/packages/@aws-cdk/aws-lambda-nodejs/lib/package-installation.ts @@ -2,13 +2,13 @@ import { spawnSync } from 'child_process'; import { tryGetModuleVersion } from './util'; /** - * An esbuild installation + * Package installation */ -export abstract class EsbuildInstallation { - public static detect(): EsbuildInstallation | undefined { +export abstract class PackageInstallation { + public static detect(module: string): PackageInstallation | undefined { try { // Check local version first - const version = tryGetModuleVersion('esbuild'); + const version = tryGetModuleVersion(module); if (version) { return { isLocal: true, @@ -17,11 +17,11 @@ export abstract class EsbuildInstallation { } // Fallback to a global version - const esbuild = spawnSync('esbuild', ['--version']); - if (esbuild.status === 0 && !esbuild.error) { + const proc = spawnSync(module, ['--version']); + if (proc.status === 0 && !proc.error) { return { isLocal: false, - version: esbuild.stdout.toString().trim(), + version: proc.stdout.toString().trim(), }; } return undefined; diff --git a/packages/@aws-cdk/aws-lambda-nodejs/lib/types.ts b/packages/@aws-cdk/aws-lambda-nodejs/lib/types.ts index 8d0d263fe64e6..6bd26c846c6fe 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/lib/types.ts +++ b/packages/@aws-cdk/aws-lambda-nodejs/lib/types.ts @@ -197,6 +197,16 @@ export interface BundlingOptions { */ readonly forceDockerBundling?: boolean; + /** + * Run compilation using tsc before running file through bundling step. + * This usually is not required unless you are using new experimental features that + * are only supported by typescript's `tsc` compiler. + * One example of such feature is `emitDecoratorMetadata`. + * + * @default false + */ + readonly preCompilation?: boolean + /** * A custom bundling Docker image. * diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/bundling.test.ts b/packages/@aws-cdk/aws-lambda-nodejs/test/bundling.test.ts index df70c1437d356..02b6030ae3e12 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/test/bundling.test.ts +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/bundling.test.ts @@ -5,20 +5,22 @@ import { Architecture, Code, Runtime } from '@aws-cdk/aws-lambda'; import { AssetHashType, DockerImage } from '@aws-cdk/core'; import { version as delayVersion } from 'delay/package.json'; import { Bundling } from '../lib/bundling'; -import { EsbuildInstallation } from '../lib/esbuild-installation'; +import { PackageInstallation } from '../lib/package-installation'; import { LogLevel, SourceMapMode } from '../lib/types'; import * as util from '../lib/util'; -let detectEsbuildMock: jest.SpyInstance; + +let detectPackageInstallationMock: jest.SpyInstance; beforeEach(() => { jest.clearAllMocks(); jest.resetAllMocks(); jest.restoreAllMocks(); Bundling.clearEsbuildInstallationCache(); + Bundling.clearTscInstallationCache(); jest.spyOn(Code, 'fromAsset'); - detectEsbuildMock = jest.spyOn(EsbuildInstallation, 'detect').mockReturnValue({ + detectPackageInstallationMock = jest.spyOn(PackageInstallation, 'detect').mockReturnValue({ isLocal: true, version: '0.8.8', }); @@ -429,7 +431,7 @@ test('Local bundling', () => { test('Incorrect esbuild version', () => { - detectEsbuildMock.mockReturnValueOnce({ + detectPackageInstallationMock.mockReturnValueOnce({ isLocal: true, version: '3.4.5', }); @@ -554,3 +556,102 @@ test('esbuild bundling with projectRoot and externals and dependencies', () => { }), }); }); + +test('esbuild bundling with pre compilations', () => { + Bundling.bundle({ + entry, + projectRoot, + depsLockFilePath, + runtime: Runtime.NODEJS_14_X, + forceDockerBundling: true, + tsconfig, + preCompilation: true, + architecture: Architecture.X86_64, + }); + + // Correctly bundles with esbuild + expect(Code.fromAsset).toHaveBeenCalledWith(path.dirname(depsLockFilePath), { + assetHashType: AssetHashType.OUTPUT, + bundling: expect.objectContaining({ + command: [ + 'bash', '-c', + [ + 'tsc --project /asset-input/lib/custom-tsconfig.ts --rootDir ./ --outDir ./ &&', + 'esbuild --bundle \"/asset-input/lib/handler.js\" --target=node14 --platform=node --outfile=\"/asset-output/index.js\"', + '--external:aws-sdk --tsconfig=/asset-input/lib/custom-tsconfig.ts', + ].join(' '), + ], + }), + }); + + Bundling.bundle({ + entry, + projectRoot, + depsLockFilePath, + runtime: Runtime.NODEJS_14_X, + forceDockerBundling: true, + tsconfig, + preCompilation: true, + architecture: Architecture.X86_64, + }); + + // Correctly bundles with esbuild + expect(Code.fromAsset).toHaveBeenCalledWith(path.dirname(depsLockFilePath), { + assetHashType: AssetHashType.OUTPUT, + bundling: expect.objectContaining({ + command: [ + 'bash', '-c', + [ + 'esbuild --bundle \"/asset-input/lib/handler.js\" --target=node14 --platform=node --outfile=\"/asset-output/index.js\"', + '--external:aws-sdk --tsconfig=/asset-input/lib/custom-tsconfig.ts', + ].join(' '), + ], + }), + }); + +}); + +test('esbuild bundling with pre compilations with undefined tsconfig ( Should find in root directory )', () => { + Bundling.clearTscCompilationCache(); + const packageLock = path.join(__dirname, '..', 'package-lock.json'); + + Bundling.bundle({ + entry: __filename.replace('.js', '.ts'), + projectRoot: path.dirname(packageLock), + depsLockFilePath: packageLock, + runtime: Runtime.NODEJS_14_X, + forceDockerBundling: true, + preCompilation: true, + architecture: Architecture.X86_64, + }); + + // Correctly bundles with esbuild + expect(Code.fromAsset).toHaveBeenCalledWith(path.dirname(packageLock), { + assetHashType: AssetHashType.OUTPUT, + bundling: expect.objectContaining({ + command: [ + 'bash', '-c', + [ + 'tsc --project /asset-input/tsconfig.json --rootDir ./ --outDir ./ &&', + 'esbuild --bundle \"/asset-input/test/bundling.test.js\" --target=node14 --platform=node --outfile=\"/asset-output/index.js\"', + '--external:aws-sdk', + ].join(' '), + ], + }), + }); +}); + +test('esbuild bundling with pre compilations and undefined tsconfig ( Should throw) ', () => { + expect(() => { + Bundling.bundle({ + entry, + projectRoot, + depsLockFilePath, + runtime: Runtime.NODEJS_14_X, + forceDockerBundling: true, + preCompilation: true, + architecture: Architecture.X86_64, + }); + }).toThrow('Cannot find a tsconfig.json, please specify the prop: tsconfig'); + +}); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/integ-handlers/ts-decorator-handler.ts b/packages/@aws-cdk/aws-lambda-nodejs/test/integ-handlers/ts-decorator-handler.ts new file mode 100644 index 0000000000000..99ca5ee8ceec1 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/integ-handlers/ts-decorator-handler.ts @@ -0,0 +1,23 @@ +function enumerable(value: boolean) { + return function (_target: any, _propertyKey: string, descriptor: PropertyDescriptor) { + descriptor.enumerable = value; + }; +} + +class Greeter { + greeting: string; + constructor(message: string) { + this.greeting = message; + } + + @enumerable(false) + greet() { + return 'Hello, ' + this.greeting; + } +} + + +export async function handler(): Promise { + const message = new Greeter('World').greet(); + console.log(message); // eslint-disable-line no-console +} diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/integ.compilations.expected.json b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.compilations.expected.json new file mode 100644 index 0000000000000..de56ccb33b617 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.compilations.expected.json @@ -0,0 +1,198 @@ +{ + "Resources": { + "tsdecoratorhandlerServiceRole61E9E52C": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "tsdecoratorhandlerC8E2F076": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": { + "Ref": "AssetParameters482454f5e1d850303130cf1cdbee1376fca84deaf9ccfa2c4cf8a246d415283fS3Bucket2B516B38" + }, + "S3Key": { + "Fn::Join": [ + "", + [ + { + "Fn::Select": [ + 0, + { + "Fn::Split": [ + "||", + { + "Ref": "AssetParameters482454f5e1d850303130cf1cdbee1376fca84deaf9ccfa2c4cf8a246d415283fS3VersionKey4B530CD7" + } + ] + } + ] + }, + { + "Fn::Select": [ + 1, + { + "Fn::Split": [ + "||", + { + "Ref": "AssetParameters482454f5e1d850303130cf1cdbee1376fca84deaf9ccfa2c4cf8a246d415283fS3VersionKey4B530CD7" + } + ] + } + ] + } + ] + ] + } + }, + "Role": { + "Fn::GetAtt": [ + "tsdecoratorhandlerServiceRole61E9E52C", + "Arn" + ] + }, + "Environment": { + "Variables": { + "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1" + } + }, + "Handler": "index.handler", + "Runtime": "nodejs14.x" + }, + "DependsOn": [ + "tsdecoratorhandlerServiceRole61E9E52C" + ] + }, + "tsdecoratorhandlertsconfigServiceRoleC4AE481E": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "tsdecoratorhandlertsconfig68EC191E": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": { + "Ref": "AssetParameters482454f5e1d850303130cf1cdbee1376fca84deaf9ccfa2c4cf8a246d415283fS3Bucket2B516B38" + }, + "S3Key": { + "Fn::Join": [ + "", + [ + { + "Fn::Select": [ + 0, + { + "Fn::Split": [ + "||", + { + "Ref": "AssetParameters482454f5e1d850303130cf1cdbee1376fca84deaf9ccfa2c4cf8a246d415283fS3VersionKey4B530CD7" + } + ] + } + ] + }, + { + "Fn::Select": [ + 1, + { + "Fn::Split": [ + "||", + { + "Ref": "AssetParameters482454f5e1d850303130cf1cdbee1376fca84deaf9ccfa2c4cf8a246d415283fS3VersionKey4B530CD7" + } + ] + } + ] + } + ] + ] + } + }, + "Role": { + "Fn::GetAtt": [ + "tsdecoratorhandlertsconfigServiceRoleC4AE481E", + "Arn" + ] + }, + "Environment": { + "Variables": { + "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1" + } + }, + "Handler": "index.handler", + "Runtime": "nodejs14.x" + }, + "DependsOn": [ + "tsdecoratorhandlertsconfigServiceRoleC4AE481E" + ] + } + }, + "Parameters": { + "AssetParameters482454f5e1d850303130cf1cdbee1376fca84deaf9ccfa2c4cf8a246d415283fS3Bucket2B516B38": { + "Type": "String", + "Description": "S3 bucket for asset \"482454f5e1d850303130cf1cdbee1376fca84deaf9ccfa2c4cf8a246d415283f\"" + }, + "AssetParameters482454f5e1d850303130cf1cdbee1376fca84deaf9ccfa2c4cf8a246d415283fS3VersionKey4B530CD7": { + "Type": "String", + "Description": "S3 key for asset version \"482454f5e1d850303130cf1cdbee1376fca84deaf9ccfa2c4cf8a246d415283f\"" + }, + "AssetParameters482454f5e1d850303130cf1cdbee1376fca84deaf9ccfa2c4cf8a246d415283fArtifactHash237F55B4": { + "Type": "String", + "Description": "Artifact hash for asset \"482454f5e1d850303130cf1cdbee1376fca84deaf9ccfa2c4cf8a246d415283f\"" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/integ.compilations.ts b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.compilations.ts new file mode 100644 index 0000000000000..2c78bde18bbf7 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.compilations.ts @@ -0,0 +1,39 @@ +/// !cdk-integ pragma:ignore-assets +import * as path from 'path'; +import { Runtime } from '@aws-cdk/aws-lambda'; +import { App, Stack, StackProps } from '@aws-cdk/core'; +import { Construct } from 'constructs'; +import * as lambda from '../lib'; + +class TestStack extends Stack { + constructor(scope: Construct, id: string, props?: StackProps) { + super(scope, id, props); + + new lambda.NodejsFunction(this, 'ts-decorator-handler', { + entry: path.join(__dirname, 'integ-handlers/ts-decorator-handler.ts'), + bundling: { + minify: true, + sourceMap: true, + sourceMapMode: lambda.SourceMapMode.BOTH, + preCompilation: true, + }, + runtime: Runtime.NODEJS_14_X, + }); + + new lambda.NodejsFunction(this, 'ts-decorator-handler-tsconfig', { + entry: path.join(__dirname, 'integ-handlers/ts-decorator-handler.ts'), + bundling: { + minify: true, + sourceMap: true, + sourceMapMode: lambda.SourceMapMode.BOTH, + tsconfig: path.join(__dirname, '..', 'tsconfig.json'), + preCompilation: true, + }, + runtime: Runtime.NODEJS_14_X, + }); + } +} + +const app = new App(); +new TestStack(app, 'cdk-integ-compilations-lambda-nodejs'); +app.synth(); diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/esbuild-installation.test.ts b/packages/@aws-cdk/aws-lambda-nodejs/test/package-installation.test.ts similarity index 84% rename from packages/@aws-cdk/aws-lambda-nodejs/test/esbuild-installation.test.ts rename to packages/@aws-cdk/aws-lambda-nodejs/test/package-installation.test.ts index 24b9b512c98bc..e7afddc09fdbb 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/test/esbuild-installation.test.ts +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/package-installation.test.ts @@ -1,12 +1,12 @@ import * as child_process from 'child_process'; -import { EsbuildInstallation } from '../lib/esbuild-installation'; +import { PackageInstallation } from '../lib/package-installation'; import * as util from '../lib/util'; // eslint-disable-next-line @typescript-eslint/no-require-imports, import/no-extraneous-dependencies const version = require('esbuild/package.json').version; test('detects local version', () => { - expect(EsbuildInstallation.detect()).toEqual({ + expect(PackageInstallation.detect('esbuild')).toEqual({ isLocal: true, version, }); @@ -23,7 +23,7 @@ test('checks global version if local detection fails', () => { signal: null, }); - expect(EsbuildInstallation.detect()).toEqual({ + expect(PackageInstallation.detect('esbuild')).toEqual({ isLocal: false, version: 'global-version', }); @@ -44,7 +44,7 @@ test('returns undefined on error', () => { signal: null, }); - expect(EsbuildInstallation.detect()).toBeUndefined(); + expect(PackageInstallation.detect('esbuild')).toBeUndefined(); spawnSyncMock.mockRestore(); getModuleVersionMock.mockRestore(); From 82de2e210286123e218116b39b1d9b26ad73ff38 Mon Sep 17 00:00:00 2001 From: Nick Lynch Date: Tue, 26 Oct 2021 12:00:10 +0100 Subject: [PATCH 37/87] chore: fix master build by skipping optional release notes copy (#17154) For releases (v1 and v2), we need to create the release notes (as part of the build) and then copy them to the dist/ directory (as part of pack). However, for `master` builds, we don't create the release notes because the BUMP_CANDIDATE builds reference a non-existent release version. Assuming the presence of the release notes in pack is causing the `master` pipeline to fail. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- pack.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pack.sh b/pack.sh index 86c29bacbd48c..168a17f972406 100755 --- a/pack.sh +++ b/pack.sh @@ -94,7 +94,10 @@ HERE # copy CHANGELOG.md and RELEASE_NOTES.md to dist/ for github releases cp ${changelog_file} ${distdir}/CHANGELOG.md -cp RELEASE_NOTES.md ${distdir}/RELEASE_NOTES.md +# Release notes are not available for bump candidate builds. +if ! ${BUMP_CANDIDATE:-false}; then + cp RELEASE_NOTES.md ${distdir}/RELEASE_NOTES.md +fi # defensive: make sure our artifacts don't use the version marker (this means # that "pack" will always fails when building in a dev environment) From 62f389ea0522cbaefca5ca17080228031d401ce6 Mon Sep 17 00:00:00 2001 From: Amir Szekely <73248943+amirfireeye@users.noreply.github.com> Date: Tue, 26 Oct 2021 04:55:07 -0700 Subject: [PATCH 38/87] feat(sns): addSubscription returns the created Subscription (#16785) Allow creating dependencies on the subscription by returning it from `addSubscription()`. Before this change the subscription resource was inaccessible. Creating a dependency required manually creating the subscription resource. Our current workaround is: ``` topic = sns.Topic(self, "topic") subscription_req = subs.SqsSubscription(queue) subscription_data = subscription_req.bind(topic) subscription = sns.Subscription( self, "Subscription", topic=topic, endpoint=subscription_data.endpoint, protocol=subscription_data.protocol, region=subscription_data.region, raw_message_delivery=subscription_data.raw_message_delivery, filter_policy=subscription_data.filter_policy, dead_letter_queue=subscription_data.dead_letter_queue, ) something.add_dependency(subscription) ``` And it would be much simpler as: ``` topic = sns.Topic(self, "topic") subscription = topic.add_subscription(subs.SqsSubscription(queue)) something.add_dependency(subscription) ``` ---- *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-sns/lib/topic-base.ts | 6 +++--- packages/@aws-cdk/aws-sns/test/sns.test.ts | 22 +++++++++++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk/aws-sns/lib/topic-base.ts b/packages/@aws-cdk/aws-sns/lib/topic-base.ts index b867670474177..3d9984c86dff0 100644 --- a/packages/@aws-cdk/aws-sns/lib/topic-base.ts +++ b/packages/@aws-cdk/aws-sns/lib/topic-base.ts @@ -31,7 +31,7 @@ export interface ITopic extends IResource, notifications.INotificationRuleTarget /** * Subscribe some endpoint to this topic */ - addSubscription(subscription: ITopicSubscription): void; + addSubscription(subscription: ITopicSubscription): Subscription; /** * Adds a statement to the IAM resource policy associated with this topic. @@ -68,7 +68,7 @@ export abstract class TopicBase extends Resource implements ITopic { /** * Subscribe some endpoint to this topic */ - public addSubscription(subscription: ITopicSubscription) { + public addSubscription(subscription: ITopicSubscription): Subscription { const subscriptionConfig = subscription.bind(this); const scope = subscriptionConfig.subscriberScope || this; @@ -83,7 +83,7 @@ export abstract class TopicBase extends Resource implements ITopic { throw new Error(`A subscription with id "${id}" already exists under the scope ${scope.node.path}`); } - new Subscription(scope, id, { + return new Subscription(scope, id, { topic: this, ...subscriptionConfig, }); diff --git a/packages/@aws-cdk/aws-sns/test/sns.test.ts b/packages/@aws-cdk/aws-sns/test/sns.test.ts index 950aef6cbcef1..5bb928bff544e 100644 --- a/packages/@aws-cdk/aws-sns/test/sns.test.ts +++ b/packages/@aws-cdk/aws-sns/test/sns.test.ts @@ -480,4 +480,26 @@ describe('Topic', () => { }); + + test('result of addSubscription() can be used as a dependency', () => { + // GIVEN + const stack = new cdk.Stack(); + const topic = new sns.Topic(stack, 'Topic'); + const user = new iam.User(stack, 'User'); + + // WHEN + const subscription = topic.addSubscription({ + bind: () => ({ + protocol: sns.SubscriptionProtocol.HTTP, + endpoint: 'http://foo/bar', + subscriberId: 'my-subscription', + }), + }); + user.node.addDependency(subscription); + + // THEN + Template.fromStack(stack).hasResource('AWS::IAM::User', { + DependsOn: ['Topicmysubscription1E605DD7'], + }); + }); }); From aca19e18fefc497deebecd3ccf5b37036ba5a0a0 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Tue, 26 Oct 2021 17:33:47 +0200 Subject: [PATCH 39/87] chore(appscaling): make examples compile (#17164) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../aws-applicationautoscaling/README.md | 88 ++++++++++--------- .../rosetta/default.ts-fixture | 48 ++++++++++ 2 files changed, 96 insertions(+), 40 deletions(-) create mode 100644 packages/@aws-cdk/aws-applicationautoscaling/rosetta/default.ts-fixture diff --git a/packages/@aws-cdk/aws-applicationautoscaling/README.md b/packages/@aws-cdk/aws-applicationautoscaling/README.md index c00dac29ece2c..77f3858b8e6f2 100644 --- a/packages/@aws-cdk/aws-applicationautoscaling/README.md +++ b/packages/@aws-cdk/aws-applicationautoscaling/README.md @@ -51,15 +51,19 @@ There are three ways to scale your capacity: The general pattern of autoscaling will look like this: ```ts +declare const resource: SomeScalableResource; + const capacity = resource.autoScaleCapacity({ minCapacity: 5, maxCapacity: 100 }); -// Enable a type of metric scaling and/or schedule scaling -capacity.scaleOnMetric(...); -capacity.scaleToTrackMetric(...); -capacity.scaleOnSchedule(...); +// Then call a method to enable metric scaling and/or schedule scaling +// (explained below): +// +// capacity.scaleOnMetric(...); +// capacity.scaleToTrackMetric(...); +// capacity.scaleOnSchedule(...); ``` ## Step Scaling @@ -82,8 +86,11 @@ a possible one. You will have to determine what thresholds are right for you). You would configure it like this: ```ts +declare const capacity: ScalableAttribute; +declare const cpuUtilization: cloudwatch.Metric; + capacity.scaleOnMetric('ScaleToCPU', { - metric: service.metricCpuUtilization(), + metric: cpuUtilization, scalingSteps: [ { upper: 10, change: -1 }, { lower: 50, change: +1 }, @@ -92,7 +99,7 @@ capacity.scaleOnMetric('ScaleToCPU', { // Change this to AdjustmentType.PercentChangeInCapacity to interpret the // 'change' numbers before as percentages instead of capacity counts. - adjustmentType: autoscaling.AdjustmentType.CHANGE_IN_CAPACITY, + adjustmentType: appscaling.AdjustmentType.CHANGE_IN_CAPACITY, }); ``` @@ -111,6 +118,10 @@ The following example configures the read capacity of a DynamoDB table to be around 60% utilization: ```ts +import * as dynamodb from '@aws-cdk/aws-dynamodb'; + +declare const table: dynamodb.Table; + const readCapacity = table.autoScaleReadCapacity({ minCapacity: 10, maxCapacity: 1000 @@ -145,18 +156,20 @@ The following example scales the fleet out in the morning, and lets natural scaling take over at night: ```ts +declare const resource: SomeScalableResource; + const capacity = resource.autoScaleCapacity({ minCapacity: 1, maxCapacity: 50, }); capacity.scaleOnSchedule('PrescaleInTheMorning', { - schedule: autoscaling.Schedule.cron({ hour: '8', minute: '0' }), + schedule: appscaling.Schedule.cron({ hour: '8', minute: '0' }), minCapacity: 20, }); capacity.scaleOnSchedule('AllowDownscalingAtNight', { - schedule: autoscaling.Schedule.cron({ hour: '20', minute: '0' }), + schedule: appscaling.Schedule.cron({ hour: '20', minute: '0' }), minCapacity: 1 }); ``` @@ -166,35 +179,30 @@ capacity.scaleOnSchedule('AllowDownscalingAtNight', { ### Lambda Provisioned Concurrency Auto Scaling ```ts - const handler = new lambda.Function(this, 'MyFunction', { - runtime: lambda.Runtime.PYTHON_3_7, - handler: 'index.handler', - code: new lambda.InlineCode(` -import json, time -def handler(event, context): - time.sleep(1) - return { - 'statusCode': 200, - 'body': json.dumps('Hello CDK from Lambda!') - }`), - reservedConcurrentExecutions: 2, - }); - - const fnVer = handler.addVersion('CDKLambdaVersion', undefined, 'demo alias', 10); - - new apigateway.LambdaRestApi(this, 'API', { handler: fnVer }) - - const target = new applicationautoscaling.ScalableTarget(this, 'ScalableTarget', { - serviceNamespace: applicationautoscaling.ServiceNamespace.LAMBDA, - maxCapacity: 100, - minCapacity: 10, - resourceId: `function:${handler.functionName}:${fnVer.version}`, - scalableDimension: 'lambda:function:ProvisionedConcurrency', - }) -s - target.scaleToTrackMetric('PceTracking', { - targetValue: 0.9, - predefinedMetric: applicationautoscaling.PredefinedMetric.LAMBDA_PROVISIONED_CONCURRENCY_UTILIZATION, - }) - } - ``` +import * as lambda from '@aws-cdk/aws-lambda'; + +declare const code: lambda.Code; + +const handler = new lambda.Function(this, 'MyFunction', { + runtime: lambda.Runtime.PYTHON_3_7, + handler: 'index.handler', + code, + + reservedConcurrentExecutions: 2, +}); + +const fnVer = handler.addVersion('CDKLambdaVersion', undefined, 'demo alias', 10); + +const target = new appscaling.ScalableTarget(this, 'ScalableTarget', { + serviceNamespace: appscaling.ServiceNamespace.LAMBDA, + maxCapacity: 100, + minCapacity: 10, + resourceId: `function:${handler.functionName}:${fnVer.version}`, + scalableDimension: 'lambda:function:ProvisionedConcurrency', +}) + +target.scaleToTrackMetric('PceTracking', { + targetValue: 0.9, + predefinedMetric: appscaling.PredefinedMetric.LAMBDA_PROVISIONED_CONCURRENCY_UTILIZATION, +}) +``` diff --git a/packages/@aws-cdk/aws-applicationautoscaling/rosetta/default.ts-fixture b/packages/@aws-cdk/aws-applicationautoscaling/rosetta/default.ts-fixture new file mode 100644 index 0000000000000..9a75db0061b9d --- /dev/null +++ b/packages/@aws-cdk/aws-applicationautoscaling/rosetta/default.ts-fixture @@ -0,0 +1,48 @@ +// Fixture with packages imported, but nothing else +import { Construct, Node } from 'constructs'; +import { Aspects, CfnOutput, Stack, Duration, Resource, SecretValue } from '@aws-cdk/core'; +import * as ec2 from '@aws-cdk/aws-ec2'; +import * as appscaling from '@aws-cdk/aws-applicationautoscaling'; +import * as cloudwatch from '@aws-cdk/aws-cloudwatch'; +import * as iam from '@aws-cdk/aws-iam'; + + +interface UtilizationScalingProps { + readonly targetUtilizationPercent: number; +} + +class ScalableAttribute { + public scaleOnSchedule(id: string, action: appscaling.ScalingSchedule) { + Array.isArray(id); + Array.isArray(action); + } + public scaleOnUtilization(props: UtilizationScalingProps) { + Array.isArray(props); + } + public scaleOnMetric(id: string, props: appscaling.BasicStepScalingPolicyProps) { + Array.isArray(id); + Array.isArray(props); + } +} + +interface Caps { + readonly minCapacity: number; + readonly maxCapacity: number; +} + +class SomeScalableResource { + public autoScaleCapacity(caps: Caps) { + return new ScalableAttribute(); + } +} + +class Fixture extends Stack { + constructor(scope: Construct, id: string) { + super(scope, id); + + /// here + } +} + + + From 325952324da82265d7043099f2b5287b40266896 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Tue, 26 Oct 2021 18:25:37 +0200 Subject: [PATCH 40/87] chore(autoscaling): make examples compile (#17163) ---- *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-autoscaling/README.md | 110 +++++++++++++----- .../aws-autoscaling/lib/scheduled-action.ts | 2 - .../@aws-cdk/aws-autoscaling/lib/volume.ts | 5 +- .../rosetta/default.ts-fixture | 18 +++ 4 files changed, 104 insertions(+), 31 deletions(-) create mode 100644 packages/@aws-cdk/aws-autoscaling/rosetta/default.ts-fixture diff --git a/packages/@aws-cdk/aws-autoscaling/README.md b/packages/@aws-cdk/aws-autoscaling/README.md index 75aa4f66807e2..11c67226afdb4 100644 --- a/packages/@aws-cdk/aws-autoscaling/README.md +++ b/packages/@aws-cdk/aws-autoscaling/README.md @@ -20,8 +20,7 @@ An `AutoScalingGroup` represents a number of instances on which you run your cod pick the size of the fleet, the instance type and the OS image: ```ts -import * as autoscaling from '@aws-cdk/aws-autoscaling'; -import * as ec2 from '@aws-cdk/aws-ec2'; +declare const vpc: ec2.Vpc; new autoscaling.AutoScalingGroup(this, 'ASG', { vpc, @@ -36,7 +35,9 @@ your instances to be able to start arbitrary connections. Alternatively, you can group to attach to the instances that are launched, rather than have the group create a new one. ```ts -const mySecurityGroup = new ec2.SecurityGroup(this, 'SecurityGroup', {...}); +declare const vpc: ec2.Vpc; + +const mySecurityGroup = new ec2.SecurityGroup(this, 'SecurityGroup', { vpc }); new autoscaling.AutoScalingGroup(this, 'ASG', { vpc, instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.MICRO), @@ -89,24 +90,31 @@ There are three ways to scale your capacity: The general pattern of autoscaling will look like this: ```ts +declare const vpc: ec2.Vpc; +declare const instanceType: ec2.InstanceType; +declare const machineImage: ec2.IMachineImage; + const autoScalingGroup = new autoscaling.AutoScalingGroup(this, 'ASG', { + vpc, + instanceType, + machineImage, + minCapacity: 5, maxCapacity: 100 // ... }); -// Step scaling -autoScalingGroup.scaleOnMetric(...); - -// Target tracking scaling -autoScalingGroup.scaleOnCpuUtilization(...); -autoScalingGroup.scaleOnIncomingBytes(...); -autoScalingGroup.scaleOnOutgoingBytes(...); -autoScalingGroup.scaleOnRequestCount(...); -autoScalingGroup.scaleToTrackMetric(...); - -// Scheduled scaling -autoScalingGroup.scaleOnSchedule(...); +// Then call one of the scaling methods (explained below) +// +// autoScalingGroup.scaleOnMetric(...); +// +// autoScalingGroup.scaleOnCpuUtilization(...); +// autoScalingGroup.scaleOnIncomingBytes(...); +// autoScalingGroup.scaleOnOutgoingBytes(...); +// autoScalingGroup.scaleOnRequestCount(...); +// autoScalingGroup.scaleToTrackMetric(...); +// +// autoScalingGroup.scaleOnSchedule(...); ``` ### Step Scaling @@ -132,12 +140,14 @@ metric representing your worker utilization from your instances. After that, you would configure the scaling something like this: ```ts +declare const autoScalingGroup: autoscaling.AutoScalingGroup; + const workerUtilizationMetric = new cloudwatch.Metric({ namespace: 'MyService', metricName: 'WorkerUtilization' }); -capacity.scaleOnMetric('ScaleToCPU', { +autoScalingGroup.scaleOnMetric('ScaleToCPU', { metric: workerUtilizationMetric, scalingSteps: [ { upper: 10, change: -1 }, @@ -170,6 +180,8 @@ The following example scales to keep the CPU usage of your instances around 50% utilization: ```ts +declare const autoScalingGroup: autoscaling.AutoScalingGroup; + autoScalingGroup.scaleOnCpuUtilization('KeepSpareCPU', { targetUtilizationPercent: 50 }); @@ -178,10 +190,12 @@ autoScalingGroup.scaleOnCpuUtilization('KeepSpareCPU', { To scale on average network traffic in and out of your instances: ```ts +declare const autoScalingGroup: autoscaling.AutoScalingGroup; + autoScalingGroup.scaleOnIncomingBytes('LimitIngressPerInstance', { targetBytesPerSecond: 10 * 1024 * 1024 // 10 MB/s }); -autoScalingGroup.scaleOnOutcomingBytes('LimitEgressPerInstance', { +autoScalingGroup.scaleOnOutgoingBytes('LimitEgressPerInstance', { targetBytesPerSecond: 10 * 1024 * 1024 // 10 MB/s }); ``` @@ -191,6 +205,8 @@ AutoScalingGroups that have been attached to Application Load Balancers): ```ts +declare const autoScalingGroup: autoscaling.AutoScalingGroup; + autoScalingGroup.scaleOnRequestCount('LimitRPS', { targetRequestsPerSecond: 1000 }); @@ -214,6 +230,8 @@ The following example scales the fleet out in the morning, going back to natural scaling (all the way down to 1 instance if necessary) at night: ```ts +declare const autoScalingGroup: autoscaling.AutoScalingGroup; + autoScalingGroup.scaleOnSchedule('PrescaleInTheMorning', { schedule: autoscaling.Schedule.cron({ hour: '8', minute: '0' }), minCapacity: 20, @@ -246,7 +264,15 @@ Here's an example of using CloudFormation Init to write a file to the instance hosts on startup: ```ts +declare const vpc: ec2.Vpc; +declare const instanceType: ec2.InstanceType; +declare const machineImage: ec2.IMachineImage; + new autoscaling.AutoScalingGroup(this, 'ASG', { + vpc, + instanceType, + machineImage, + // ... init: ec2.CloudFormationInit.fromElements( @@ -347,16 +373,30 @@ See [EC2 docs](https://docs.aws.amazon.com/autoscaling/ec2/userguide/as-instance To enable group metrics monitoring using the `groupMetrics` property: ```ts +declare const vpc: ec2.Vpc; +declare const instanceType: ec2.InstanceType; +declare const machineImage: ec2.IMachineImage; + // Enable monitoring of all group metrics -new autoscaling.AutoScalingGroup(stack, 'ASG', { - groupMetrics: [GroupMetrics.all()], +new autoscaling.AutoScalingGroup(this, 'ASG', { + vpc, + instanceType, + machineImage, + // ... + + groupMetrics: [autoscaling.GroupMetrics.all()], }); // Enable monitoring for a subset of group metrics -new autoscaling.AutoScalingGroup(stack, 'ASG', { - groupMetrics: [new autoscaling.GroupMetrics(GroupMetric.MIN_SIZE, GroupMetric.MAX_SIZE)], +new autoscaling.AutoScalingGroup(this, 'ASG', { + vpc, + instanceType, + machineImage, + // ... + + groupMetrics: [new autoscaling.GroupMetrics(autoscaling.GroupMetric.MIN_SIZE, autoscaling.GroupMetric.MAX_SIZE)], }); ``` @@ -372,9 +412,18 @@ terminated. EC2 Capacity Providers for Amazon ECS requires this attribute be set to `true`. ```ts -new autoscaling.AutoScalingGroup(stack, 'ASG', { - newInstancesProtectedFromScaleIn: true, +declare const vpc: ec2.Vpc; +declare const instanceType: ec2.InstanceType; +declare const machineImage: ec2.IMachineImage; + +new autoscaling.AutoScalingGroup(this, 'ASG', { + vpc, + instanceType, + machineImage, + // ... + + newInstancesProtectedFromScaleIn: true, }); ``` @@ -389,9 +438,18 @@ To do this for a single `AutoScalingGroup`, you can use set the `requireImdsv2` The example below demonstrates IMDSv2 being required on a single `AutoScalingGroup`: ```ts -new autoscaling.AutoScalingGroup(stack, 'ASG', { - requireImdsv2: true, +declare const vpc: ec2.Vpc; +declare const instanceType: ec2.InstanceType; +declare const machineImage: ec2.IMachineImage; + +new autoscaling.AutoScalingGroup(this, 'ASG', { + vpc, + instanceType, + machineImage, + // ... + + requireImdsv2: true, }); ``` @@ -401,7 +459,7 @@ The example below demonstrates the `AutoScalingGroupRequireImdsv2Aspect` being u ```ts const aspect = new autoscaling.AutoScalingGroupRequireImdsv2Aspect(); -Aspects.of(stack).add(aspect); +Aspects.of(this).add(aspect); ``` ## Future work diff --git a/packages/@aws-cdk/aws-autoscaling/lib/scheduled-action.ts b/packages/@aws-cdk/aws-autoscaling/lib/scheduled-action.ts index 71fde34af72cd..70a269bde9239 100644 --- a/packages/@aws-cdk/aws-autoscaling/lib/scheduled-action.ts +++ b/packages/@aws-cdk/aws-autoscaling/lib/scheduled-action.ts @@ -14,8 +14,6 @@ export interface BasicScheduledActionProps { * Supports cron expressions. * * For more information about cron expressions, see https://en.wikipedia.org/wiki/Cron. - * - * @example 0 8 * * ? */ readonly schedule: Schedule; diff --git a/packages/@aws-cdk/aws-autoscaling/lib/volume.ts b/packages/@aws-cdk/aws-autoscaling/lib/volume.ts index cbe08bac7c6ab..1c5f5da6dc659 100644 --- a/packages/@aws-cdk/aws-autoscaling/lib/volume.ts +++ b/packages/@aws-cdk/aws-autoscaling/lib/volume.ts @@ -9,7 +9,7 @@ export interface BlockDevice { /** * The device name exposed to the EC2 instance * - * @example '/dev/sdh', 'xvdh' + * Supply a value like `/dev/sdh`, `xvdh`. * * @see https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/device_naming.html */ @@ -18,8 +18,7 @@ export interface BlockDevice { /** * Defines the block device volume, to be either an Amazon EBS volume or an ephemeral instance store volume * - * @example BlockDeviceVolume.ebs(15), BlockDeviceVolume.ephemeral(0) - * + * Supply a value like `BlockDeviceVolume.ebs(15)`, `BlockDeviceVolume.ephemeral(0)`. */ readonly volume: BlockDeviceVolume; diff --git a/packages/@aws-cdk/aws-autoscaling/rosetta/default.ts-fixture b/packages/@aws-cdk/aws-autoscaling/rosetta/default.ts-fixture new file mode 100644 index 0000000000000..314520288f9cb --- /dev/null +++ b/packages/@aws-cdk/aws-autoscaling/rosetta/default.ts-fixture @@ -0,0 +1,18 @@ +// Fixture with packages imported, but nothing else +import { Construct, Node } from 'constructs'; +import { Aspects, CfnOutput, Stack, Duration, Resource, SecretValue } from '@aws-cdk/core'; +import * as ec2 from '@aws-cdk/aws-ec2'; +import * as autoscaling from '@aws-cdk/aws-autoscaling'; +import * as cloudwatch from '@aws-cdk/aws-cloudwatch'; +import * as iam from '@aws-cdk/aws-iam'; + +class Fixture extends Stack { + constructor(scope: Construct, id: string) { + super(scope, id); + + /// here + } +} + + + From f37991c4de21ecbc7db5117de7f9adc1ecc40f2b Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Tue, 26 Oct 2021 19:18:02 +0200 Subject: [PATCH 41/87] chore(cloudwatch): make examples compile (#17158) ---- *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-cloudwatch/README.md | 128 ++++++++++++------ .../aws-cloudwatch/rosetta/default.ts-fixture | 17 +++ 2 files changed, 100 insertions(+), 45 deletions(-) create mode 100644 packages/@aws-cdk/aws-cloudwatch/rosetta/default.ts-fixture diff --git a/packages/@aws-cdk/aws-cloudwatch/README.md b/packages/@aws-cdk/aws-cloudwatch/README.md index 450fc8ca9821a..67b68ed46e741 100644 --- a/packages/@aws-cdk/aws-cloudwatch/README.md +++ b/packages/@aws-cdk/aws-cloudwatch/README.md @@ -25,6 +25,8 @@ For example, `lambda.Function` objects have the `fn.metricErrors()` method, whic represents the amount of errors reported by that Lambda function: ```ts +declare const fn: lambda.Function; + const errors = fn.metricErrors(); ``` @@ -37,7 +39,7 @@ For example: ```ts const hostedZone = new route53.HostedZone(this, 'MyHostedZone', { zoneName: "example.org" }); -const metric = new Metric({ +const metric = new cloudwatch.Metric({ namespace: 'AWS/Route53', metricName: 'DNSQueries', dimensionsMap: { @@ -52,7 +54,7 @@ If you want to reference a metric that is not yet exposed by an existing constru you can instantiate a `Metric` object to represent it. For example: ```ts -const metric = new Metric({ +const metric = new cloudwatch.Metric({ namespace: 'MyNamespace', metricName: 'MyMetric', dimensionsMap: { @@ -67,11 +69,13 @@ Math expressions are supported by instantiating the `MathExpression` class. For example, a math expression that sums two other metrics looks like this: ```ts -const allProblems = new MathExpression({ - expression: "errors + faults", +declare const fn: lambda.Function; + +const allProblems = new cloudwatch.MathExpression({ + expression: "errors + throttles", usingMetrics: { - errors: myConstruct.metricErrors(), - faults: myConstruct.metricFaults(), + errors: fn.metricErrors(), + faults: fn.metricThrottles(), } }); ``` @@ -80,11 +84,14 @@ You can use `MathExpression` objects like any other metric, including using them in other math expressions: ```ts -const problemPercentage = new MathExpression({ +declare const fn: lambda.Function; +declare const allProblems: cloudwatch.MathExpression; + +const problemPercentage = new cloudwatch.MathExpression({ expression: "(problems / invocations) * 100", usingMetrics: { problems: allProblems, - invocations: myConstruct.metricInvocations() + invocations: fn.metricInvocations() } }); ``` @@ -96,7 +103,7 @@ search expression returns all CPUUtilization metrics that it finds, with the graph showing the Average statistic with an aggregation period of 5 minutes: ```ts -const cpuUtilization = new MathExpression({ +const cpuUtilization = new cloudwatch.MathExpression({ expression: "SEARCH('{AWS/EC2,InstanceId} MetricName=\"CPUUtilization\"', 'Average', 300)" }); ``` @@ -120,6 +127,8 @@ the function or the period), you can do so by passing additional parameters to the metric function call: ```ts +declare const fn: lambda.Function; + const minuteErrorRate = fn.metricErrors({ statistic: 'avg', period: Duration.minutes(1), @@ -153,9 +162,10 @@ useful when embedding them in graphs, see below). Alarms can be created on metrics in one of two ways. Either create an `Alarm` object, passing the `Metric` object to set the alarm on: - ```ts -new Alarm(this, 'Alarm', { +declare const fn: lambda.Function; + +new cloudwatch.Alarm(this, 'Alarm', { metric: fn.metricErrors(), threshold: 100, evaluationPeriods: 2, @@ -165,6 +175,8 @@ new Alarm(this, 'Alarm', { Alternatively, you can call `metric.createAlarm()`: ```ts +declare const fn: lambda.Function; + fn.metricErrors().createAlarm(this, 'Alarm', { threshold: 100, evaluationPeriods: 2, @@ -188,33 +200,36 @@ an SNS topic when an alarm breaches, do the following: ```ts import * as cw_actions from '@aws-cdk/aws-cloudwatch-actions'; +declare const alarm: cloudwatch.Alarm; -// ... -const topic = new sns.Topic(stack, 'Topic'); -const alarm = new cloudwatch.Alarm(stack, 'Alarm', { /* ... */ }); - +const topic = new sns.Topic(this, 'Topic'); alarm.addAlarmAction(new cw_actions.SnsAction(topic)); ``` ### Composite Alarms -[Composite Alarms](https://aws.amazon.com/about-aws/whats-new/2020/03/amazon-cloudwatch-now-allows-you-to-combine-multiple-alarms/) +[Composite Alarms](https://aws.amazon.com/about-aws/whats-new/2020/03/amazon-cloudwatch-now-allows-you-to-combine-multiple-alarms/) can be created from existing Alarm resources. ```ts -const alarmRule = AlarmRule.anyOf( - AlarmRule.allOf( - AlarmRule.anyOf( +declare const alarm1: cloudwatch.Alarm; +declare const alarm2: cloudwatch.Alarm; +declare const alarm3: cloudwatch.Alarm; +declare const alarm4: cloudwatch.Alarm; + +const alarmRule = cloudwatch.AlarmRule.anyOf( + cloudwatch.AlarmRule.allOf( + cloudwatch.AlarmRule.anyOf( alarm1, - AlarmRule.fromAlarm(alarm2, AlarmState.OK), + cloudwatch.AlarmRule.fromAlarm(alarm2, cloudwatch.AlarmState.OK), alarm3, ), - AlarmRule.not(AlarmRule.fromAlarm(alarm4, AlarmState.INSUFFICIENT_DATA)), + cloudwatch.AlarmRule.not(cloudwatch.AlarmRule.fromAlarm(alarm4, cloudwatch.AlarmState.INSUFFICIENT_DATA)), ), - AlarmRule.fromBoolean(false), + cloudwatch.AlarmRule.fromBoolean(false), ); -new CompositeAlarm(this, 'MyAwesomeCompositeAlarm', { +new cloudwatch.CompositeAlarm(this, 'MyAwesomeCompositeAlarm', { alarmRule, }); ``` @@ -260,7 +275,11 @@ A graph widget can display any number of metrics on either the `left` or `right` vertical axis: ```ts -dashboard.addWidgets(new GraphWidget({ +declare const dashboard: cloudwatch.Dashboard; +declare const executionCountMetric: cloudwatch.Metric; +declare const errorCountMetric: cloudwatch.Metric; + +dashboard.addWidgets(new cloudwatch.GraphWidget({ title: "Executions vs error rate", left: [executionCountMetric], @@ -268,7 +287,7 @@ dashboard.addWidgets(new GraphWidget({ right: [errorCountMetric.with({ statistic: "average", label: "Error rate", - color: Color.GREEN + color: cloudwatch.Color.GREEN })] })); ``` @@ -278,12 +297,13 @@ Using the methods `addLeftMetric()` and `addRightMetric()` you can add metrics t Graph widgets can also display annotations attached to the left or the right y-axis. ```ts -dashboard.addWidgets(new GraphWidget({ - // ... +declare const dashboard: cloudwatch.Dashboard; + +dashboard.addWidgets(new cloudwatch.GraphWidget({ // ... leftAnnotations: [ - { value: 1800, label: Duration.minutes(30).toHumanString(), color: Color.RED, }, + { value: 1800, label: Duration.minutes(30).toHumanString(), color: cloudwatch.Color.RED, }, { value: 3600, label: '1 hour', color: '#2ca02c', } ], })); @@ -292,19 +312,21 @@ dashboard.addWidgets(new GraphWidget({ The graph legend can be adjusted from the default position at bottom of the widget. ```ts -dashboard.addWidgets(new GraphWidget({ - // ... +declare const dashboard: cloudwatch.Dashboard; + +dashboard.addWidgets(new cloudwatch.GraphWidget({ // ... - legendPosition: LegendPosition.RIGHT, + legendPosition: cloudwatch.LegendPosition.RIGHT, })); ``` The graph can publish live data within the last minute that has not been fully aggregated. ```ts -dashboard.addWidgets(new GraphWidget({ - // ... +declare const dashboard: cloudwatch.Dashboard; + +dashboard.addWidgets(new cloudwatch.GraphWidget({ // ... liveData: true, @@ -314,11 +336,12 @@ dashboard.addWidgets(new GraphWidget({ The graph view can be changed from default 'timeSeries' to 'bar' or 'pie'. ```ts -dashboard.addWidgets(new GraphWidget({ - // ... +declare const dashboard: cloudwatch.Dashboard; + +dashboard.addWidgets(new cloudwatch.GraphWidget({ // ... - view: GraphWidgetView.BAR, + view: cloudwatch.GraphWidgetView.BAR, })); ``` @@ -327,7 +350,10 @@ dashboard.addWidgets(new GraphWidget({ An alarm widget shows the graph and the alarm line of a single alarm: ```ts -dashboard.addWidgets(new AlarmWidget({ +declare const dashboard: cloudwatch.Dashboard; +declare const errorAlarm: cloudwatch.Alarm; + +dashboard.addWidgets(new cloudwatch.AlarmWidget({ title: "Errors", alarm: errorAlarm, })); @@ -339,7 +365,11 @@ A single-value widget shows the latest value of a set of metrics (as opposed to a graph of the value over time): ```ts -dashboard.addWidgets(new SingleValueWidget({ +declare const dashboard: cloudwatch.Dashboard; +declare const visitorCount: cloudwatch.Metric; +declare const purchaseCount: cloudwatch.Metric; + +dashboard.addWidgets(new cloudwatch.SingleValueWidget({ metrics: [visitorCount, purchaseCount], })); ``` @@ -347,9 +377,10 @@ dashboard.addWidgets(new SingleValueWidget({ Show as many digits as can fit, before rounding. ```ts -dashboard.addWidgets(new SingleValueWidget({ - // .. - // .. +declare const dashboard: cloudwatch.Dashboard; + +dashboard.addWidgets(new cloudwatch.SingleValueWidget({ + metrics: [ /* ... */ ], fullPrecision: true, })); @@ -361,7 +392,9 @@ A text widget shows an arbitrary piece of MarkDown. Use this to add explanations to your dashboard: ```ts -dashboard.addWidgets(new TextWidget({ +declare const dashboard: cloudwatch.Dashboard; + +dashboard.addWidgets(new cloudwatch.TextWidget({ markdown: '# Key Performance Indicators' })); ``` @@ -372,8 +405,11 @@ An alarm status widget displays instantly the status of any type of alarms and g ability to aggregate one or more alarms together in a small surface. ```ts +declare const dashboard: cloudwatch.Dashboard; +declare const errorAlarm: cloudwatch.Alarm; + dashboard.addWidgets( - new AlarmStatusWidget({ + new cloudwatch.AlarmStatusWidget({ alarms: [errorAlarm], }) ); @@ -384,9 +420,11 @@ dashboard.addWidgets( A `LogQueryWidget` shows the results of a query from Logs Insights: ```ts -dashboard.addWidgets(new LogQueryWidget({ +declare const dashboard: cloudwatch.Dashboard; + +dashboard.addWidgets(new cloudwatch.LogQueryWidget({ logGroupNames: ['my-log-group'], - view: LogQueryVisualizationType.TABLE, + view: cloudwatch.LogQueryVisualizationType.TABLE, // The lines will be automatically combined using '\n|'. queryLines: [ 'fields @message', diff --git a/packages/@aws-cdk/aws-cloudwatch/rosetta/default.ts-fixture b/packages/@aws-cdk/aws-cloudwatch/rosetta/default.ts-fixture new file mode 100644 index 0000000000000..85cc6b579f761 --- /dev/null +++ b/packages/@aws-cdk/aws-cloudwatch/rosetta/default.ts-fixture @@ -0,0 +1,17 @@ +// Fixture with packages imported, but nothing else +import { Construct } from 'constructs'; +import { Stack, Duration } from '@aws-cdk/core'; +import * as cloudwatch from '@aws-cdk/aws-cloudwatch'; +import * as route53 from '@aws-cdk/aws-route53'; +import * as sns from '@aws-cdk/aws-sns'; +import * as lambda from '@aws-cdk/aws-lambda'; + +class Fixture extends Stack { + constructor(scope: Construct, id: string) { + super(scope, id); + + /// here + } +} + + From 76898698d3657ab996e994c7eec79dd818684589 Mon Sep 17 00:00:00 2001 From: Nick Lynch Date: Tue, 26 Oct 2021 19:10:41 +0100 Subject: [PATCH 42/87] chore: Revert "feat(sns): addSubscription returns the created Subscription (#16785)" (#17166) This reverts commit 62f389ea0522cbaefca5ca17080228031d401ce6. Changing the return type from void to Subscription is a breaking change for F# customers, where the return type changes from "unit" to "Subscription", potentially breaking `do` statements. Example: https://github.com/aws/aws-cdk/blob/62f389ea0522cbaefca5ca17080228031d401ce6/packages/aws-cdk/lib/init-templates/v1/sample-app/fsharp/src/%25name.PascalCased%25/%25name.PascalCased%25Stack.template.fs#L14 ---- *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-sns/lib/topic-base.ts | 6 +++--- packages/@aws-cdk/aws-sns/test/sns.test.ts | 22 --------------------- 2 files changed, 3 insertions(+), 25 deletions(-) diff --git a/packages/@aws-cdk/aws-sns/lib/topic-base.ts b/packages/@aws-cdk/aws-sns/lib/topic-base.ts index 3d9984c86dff0..b867670474177 100644 --- a/packages/@aws-cdk/aws-sns/lib/topic-base.ts +++ b/packages/@aws-cdk/aws-sns/lib/topic-base.ts @@ -31,7 +31,7 @@ export interface ITopic extends IResource, notifications.INotificationRuleTarget /** * Subscribe some endpoint to this topic */ - addSubscription(subscription: ITopicSubscription): Subscription; + addSubscription(subscription: ITopicSubscription): void; /** * Adds a statement to the IAM resource policy associated with this topic. @@ -68,7 +68,7 @@ export abstract class TopicBase extends Resource implements ITopic { /** * Subscribe some endpoint to this topic */ - public addSubscription(subscription: ITopicSubscription): Subscription { + public addSubscription(subscription: ITopicSubscription) { const subscriptionConfig = subscription.bind(this); const scope = subscriptionConfig.subscriberScope || this; @@ -83,7 +83,7 @@ export abstract class TopicBase extends Resource implements ITopic { throw new Error(`A subscription with id "${id}" already exists under the scope ${scope.node.path}`); } - return new Subscription(scope, id, { + new Subscription(scope, id, { topic: this, ...subscriptionConfig, }); diff --git a/packages/@aws-cdk/aws-sns/test/sns.test.ts b/packages/@aws-cdk/aws-sns/test/sns.test.ts index 5bb928bff544e..950aef6cbcef1 100644 --- a/packages/@aws-cdk/aws-sns/test/sns.test.ts +++ b/packages/@aws-cdk/aws-sns/test/sns.test.ts @@ -480,26 +480,4 @@ describe('Topic', () => { }); - - test('result of addSubscription() can be used as a dependency', () => { - // GIVEN - const stack = new cdk.Stack(); - const topic = new sns.Topic(stack, 'Topic'); - const user = new iam.User(stack, 'User'); - - // WHEN - const subscription = topic.addSubscription({ - bind: () => ({ - protocol: sns.SubscriptionProtocol.HTTP, - endpoint: 'http://foo/bar', - subscriberId: 'my-subscription', - }), - }); - user.node.addDependency(subscription); - - // THEN - Template.fromStack(stack).hasResource('AWS::IAM::User', { - DependsOn: ['Topicmysubscription1E605DD7'], - }); - }); }); From fcd17e9c9a9e1b83a29c140d558f696c0290bfd7 Mon Sep 17 00:00:00 2001 From: James Lakin Date: Tue, 26 Oct 2021 21:33:06 +0100 Subject: [PATCH 43/87] feat(rds): support backtrackWindow in DatabaseCluster (#17160) This is a small PR to fix #9369 without needing to use an escape hatch. Fixes #9369 ---- *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-rds/lib/cluster.ts | 11 ++++++++++ .../@aws-cdk/aws-rds/test/cluster.test.ts | 20 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/packages/@aws-cdk/aws-rds/lib/cluster.ts b/packages/@aws-cdk/aws-rds/lib/cluster.ts index 15f9e60215ebc..7324cacb333c2 100644 --- a/packages/@aws-cdk/aws-rds/lib/cluster.ts +++ b/packages/@aws-cdk/aws-rds/lib/cluster.ts @@ -40,6 +40,16 @@ interface DatabaseClusterBaseProps { */ readonly instanceProps: InstanceProps; + /** + * The number of seconds to set a cluster's target backtrack window to. + * This feature is only supported by the Aurora MySQL database engine and + * cannot be enabled on existing clusters. + * + * @see https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Managing.Backtrack.html + * @default 0 seconds (no backtrack) + */ + readonly backtrackWindow?: Duration + /** * Backup settings * @@ -364,6 +374,7 @@ abstract class DatabaseClusterNew extends DatabaseClusterBase { deletionProtection: defaultDeletionProtection(props.deletionProtection, props.removalPolicy), enableIamDatabaseAuthentication: props.iamAuthentication, // Admin + backtrackWindow: props.backtrackWindow?.toSeconds(), backupRetentionPeriod: props.backup?.retention?.toDays(), preferredBackupWindow: props.backup?.preferredWindow, preferredMaintenanceWindow: props.preferredMaintenanceWindow, diff --git a/packages/@aws-cdk/aws-rds/test/cluster.test.ts b/packages/@aws-cdk/aws-rds/test/cluster.test.ts index 97d5548611fcd..5adc3d4906643 100644 --- a/packages/@aws-cdk/aws-rds/test/cluster.test.ts +++ b/packages/@aws-cdk/aws-rds/test/cluster.test.ts @@ -2032,6 +2032,26 @@ describe('cluster', () => { CopyTagsToSnapshot: true, }); }); + + test('cluster has BacktrackWindow in seconds', () => { + // GIVEN + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + + // WHEN + new DatabaseCluster(stack, 'Database', { + engine: DatabaseClusterEngine.AURORA, + instanceProps: { + vpc, + }, + backtrackWindow: cdk.Duration.days(1), + }); + + // THEN + expect(stack).toHaveResourceLike('AWS::RDS::DBCluster', { + BacktrackWindow: 24 * 60 * 60, + }); + }); }); test.each([ From ad36306ed206e8102a85ee391136b84ba6f4c6e1 Mon Sep 17 00:00:00 2001 From: Adel Salakh Date: Wed, 27 Oct 2021 02:22:31 +0300 Subject: [PATCH 44/87] docs(lambda-layer-kubctl): fix incorrect versions in README (#16413) Swap Helm and Kubectl versions in the README ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/@aws-cdk/lambda-layer-kubectl/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/lambda-layer-kubectl/README.md b/packages/@aws-cdk/lambda-layer-kubectl/README.md index 3782174b1aa72..97329d16c8c50 100644 --- a/packages/@aws-cdk/lambda-layer-kubectl/README.md +++ b/packages/@aws-cdk/lambda-layer-kubectl/README.md @@ -11,8 +11,9 @@ This module exports a single class called `KubectlLayer` which is a `lambda.Layer` that bundles the [`kubectl`](https://kubernetes.io/docs/reference/kubectl/kubectl/) and the [`helm`](https://helm.sh/) command line. -> - Helm Version: 1.20.0 -> - Kubectl Version: 3.4.2 +> - Helm Version: 3.5.4 +> - Kubectl Version: 1.20.0 +> Usage: From 3efd31e478d5060f0fb45668ae3ef1cb44e9fd14 Mon Sep 17 00:00:00 2001 From: peterwoodworth Date: Tue, 26 Oct 2021 16:52:57 -0700 Subject: [PATCH 45/87] chore: add corymhall, peterwoodworth, ryparker to mergify --- .mergify.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mergify.yml b/.mergify.yml index e460f1d12842f..c30db93044503 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -10,7 +10,7 @@ pull_request_rules: label: add: [ contribution/core ] conditions: - - author~=^(eladb|RomainMuller|garnaat|nija-at|skinny85|rix0rrr|NGL321|Jerry-AWS|MrArnoldPalmer|NetaNir|iliapolo|njlynch|ericzbeard|ccfife|fulghum|pkandasamy91|SoManyHs|uttarasridhar|otaviomacedo|BenChaimberg|madeline-k|BryanPan342|kaizen3031593|comcalvi|Chriscbr)$ + - author~=^(eladb|RomainMuller|garnaat|nija-at|skinny85|rix0rrr|NGL321|Jerry-AWS|MrArnoldPalmer|NetaNir|iliapolo|njlynch|ericzbeard|ccfife|fulghum|pkandasamy91|SoManyHs|uttarasridhar|otaviomacedo|BenChaimberg|madeline-k|BryanPan342|kaizen3031593|comcalvi|Chriscbr|corymhall|peterwoodworth|ryparker)$ - -label~="contribution/core" - name: automatic merge actions: From 7bdd9079d55e503cd625bc5663f0bb73ad94a40f Mon Sep 17 00:00:00 2001 From: Peter Woodworth <44349620+peterwoodworth@users.noreply.github.com> Date: Wed, 27 Oct 2021 00:31:42 -0700 Subject: [PATCH 46/87] chore: update autolabeler config (#17174) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .github/workflows/issue-label-assign.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/issue-label-assign.yml b/.github/workflows/issue-label-assign.yml index b82a4040658d8..b7bfacd0126b0 100644 --- a/.github/workflows/issue-label-assign.yml +++ b/.github/workflows/issue-label-assign.yml @@ -24,6 +24,7 @@ jobs: {"area":"@aws-cdk/alexa-ask","keywords":["alexa-ask","alexa", "cfnskill"],"labels":["@aws-cdk/alexa-ask"],"assignees":["madeline-k"]}, {"area":"@aws-cdk/app-delivery","keywords":["app-delivery","PipelineDeployStackAction"],"labels":["@aws-cdk/app-delivery"],"assignees":["skinny85"]}, {"area":"@aws-cdk/assert","keywords":["assert"],"labels":["@aws-cdk/assert"],"assignees":["nija-at"]}, + {"area":"@aws-cdk/assertions","keywords":["assertions"],"labels":["@aws-cdk/assertions"],"assignees":["nija-at"]}, {"area":"@aws-cdk/assets","keywords":["assets","staging"],"labels":["@aws-cdk/assets"],"assignees":["eladb"]}, {"area":"@aws-cdk/aws-accessanalyzer","keywords":["aws-accessanalyzer","accessanalyzer","cfnanalyzer"],"labels":["@aws-cdk/aws-accessanalyzer"],"assignees":["skinny85"]}, {"area":"@aws-cdk/aws-acmpca","keywords":["aws-acmpca","acmpca","certificateauthority"],"labels":["@aws-cdk/aws-acmpca"],"assignees":["skinny85"]}, @@ -56,7 +57,7 @@ jobs: {"area":"@aws-cdk/aws-certificatemanager","keywords":["aws-certificatemanager","certificate-manager","dnsvalidatedcertificate","acm"],"labels":["@aws-cdk/aws-certificatemanager"],"assignees":["njlynch"]}, {"area":"@aws-cdk/aws-chatbot","keywords":["aws-chatbot","chatbot","slackchannelconfiguration"],"labels":["@aws-cdk/aws-chatbot"],"assignees":["kaizen3031593"]}, {"area":"@aws-cdk/aws-cloud9","keywords":["aws-cloud9","cloud 9","ec2environment"],"labels":["@aws-cdk/aws-cloud9"],"assignees":["skinny85"]}, - {"area":"@aws-cdk/aws-cloudformation","keywords":["aws-cloudformation","nestedstack","customresource"],"labels":["@aws-cdk/aws-cloudformation"],"assignees":["rix0rrr"]}, + {"area":"@aws-cdk/aws-cloudformation","keywords":["aws-cloudformation","nestedstack"],"labels":["@aws-cdk/aws-cloudformation"],"assignees":["rix0rrr"]}, {"area":"@aws-cdk/aws-cloudfront","keywords":["aws-cloudfront","cloud front","cachepolicy","cloudfrontwebdistribution"],"labels":["@aws-cdk/aws-cloudfront"],"assignees":["njlynch"]}, {"area":"@aws-cdk/aws-cloudfront-origins","keywords":["aws-cloudfront-origins","cloudfront origins"],"labels":["@aws-cdk/aws-cloudfront-origins"],"assignees":["njlynch"]}, {"area":"@aws-cdk/aws-cloudtrail","keywords":["aws-cloudtrail","cloud trail","trail"],"labels":["@aws-cdk/aws-cloudtrail"],"assignees":["rix0rrr"]}, @@ -68,8 +69,8 @@ jobs: {"area":"@aws-cdk/aws-codedeploy","keywords":["aws-codedeploy","code-deploy","customlambdadeploymentconfig","ecsapplication","lambdaapplication","lambdadeploymentgroup","serverapplication"],"labels":["@aws-cdk/aws-codedeploy"],"assignees":["skinny85"]}, {"area":"@aws-cdk/aws-codeguruprofiler","keywords":["aws-codeguruprofiler","codeguru-profiler","profilinggroup"],"labels":["@aws-cdk/aws-codeguruprofiler"],"assignees":["skinny85"]}, {"area":"@aws-cdk/aws-codegurureviewer","keywords":["aws-codegurureviewer","codeguru-reviewer"],"labels":["@aws-cdk/aws-codegurureviewer"],"assignees":["skinny85"]}, - {"area":"@aws-cdk/aws-codepipeline","keywords":["aws-codepipeline","code-pipeline","pipeline"],"labels":["@aws-cdk/aws-codepipeline"],"assignees":["skinny85"]}, - {"area":"@aws-cdk/aws-codepipeline-actions","keywords":["aws-codepipeline-actions","codepipeline actions","jenkinsprovider"],"labels":["@aws-cdk/aws-codepipeline-actions"],"assignees":["skinny85"]}, + {"area":"@aws-cdk/aws-codepipeline","keywords":["aws-codepipeline","code-pipeline"],"labels":["@aws-cdk/aws-codepipeline"],"assignees":["skinny85"]}, + {"area":"@aws-cdk/aws-codepipeline-actions","keywords":["aws-codepipeline-actions","codepipeline-actions","jenkinsprovider"],"labels":["@aws-cdk/aws-codepipeline-actions"],"assignees":["skinny85"]}, {"area":"@aws-cdk/aws-codestar","keywords":["aws-codestar","codestar","githubrepository"],"labels":["@aws-cdk/aws-codestar"],"assignees":["skinny85"]}, {"area":"@aws-cdk/aws-codestarconnections","keywords":["aws-codestarconnections","codestar-connections"],"labels":["@aws-cdk/aws-codestarconnections"],"assignees":["skinny85"]}, {"area":"@aws-cdk/aws-codestarnotifications","keywords":["aws-codestarnotifications","codestar-notifications"],"labels":["@aws-cdk/aws-codestarnotifications"],"assignees":["skinny85"]}, From 3ea6873af6e36380d23979bf646451f9cc1a549e Mon Sep 17 00:00:00 2001 From: kaizen3031593 <36202692+kaizen3031593@users.noreply.github.com> Date: Wed, 27 Oct 2021 05:08:43 -0400 Subject: [PATCH 47/87] docs(kms): make examples compile (#17167) ---- *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-kms/README.md | 32 +++++++++---------- .../aws-kms/rosetta/default.ts-fixture | 14 ++++++++ 2 files changed, 30 insertions(+), 16 deletions(-) create mode 100644 packages/@aws-cdk/aws-kms/rosetta/default.ts-fixture diff --git a/packages/@aws-cdk/aws-kms/README.md b/packages/@aws-cdk/aws-kms/README.md index 098e643440784..201accf122675 100644 --- a/packages/@aws-cdk/aws-kms/README.md +++ b/packages/@aws-cdk/aws-kms/README.md @@ -14,10 +14,8 @@ Define a KMS key: ```ts -import * as kms from '@aws-cdk/aws-kms'; - new kms.Key(this, 'MyKey', { - enableKeyRotation: true + enableKeyRotation: true, }); ``` @@ -27,7 +25,7 @@ Specifies the number of days in the waiting period before AWS KMS deletes a CMK ```ts const key = new kms.Key(this, 'MyKey', { - pendingWindow: 10 // Default to 30 Days + pendingWindow: Duration.days(10), // Default to 30 Days }); ``` @@ -48,7 +46,7 @@ Valid `keySpec` values depends on `keyUsage` value. ```ts const key = new kms.Key(this, 'MyKey', { keySpec: kms.KeySpec.ECC_SECG_P256K1, // Default to SYMMETRIC_DEFAULT - keyUsage: kms.KeyUsage.SIGN_VERIFY // and ENCRYPT_DECRYPT + keyUsage: kms.KeyUsage.SIGN_VERIFY, // and ENCRYPT_DECRYPT }); ``` @@ -84,10 +82,12 @@ If a Key has an associated Alias, the Alias can be imported by name and used in of the Key as a reference. A common scenario for this is in referencing AWS managed keys. ```ts +import * as cloudtrail from '@aws-cdk/aws-cloudtrail'; + const myKeyAlias = kms.Alias.fromAliasName(this, 'myKey', 'alias/aws/s3'); const trail = new cloudtrail.Trail(this, 'myCloudTrail', { - sendToCloudWatchLogs: true, - kmsKey: myKeyAlias + sendToCloudWatchLogs: true, + kmsKey: myKeyAlias, }); ``` @@ -110,7 +110,7 @@ Here's how `Key.fromLookup()` can be used: ```ts const myKeyLookup = kms.Key.fromLookup(this, 'MyKeyLookup', { - aliasName: 'alias/KeyAlias' + aliasName: 'alias/KeyAlias', }); const role = new iam.Role(this, 'MyRole', { @@ -138,7 +138,7 @@ which is set for all new projects; for existing projects, this same behavior can passing the `trustAccountIdentities` property as `true` when creating the key: ```ts -new kms.Key(stack, 'MyKey', { trustAccountIdentities: true }); +new kms.Key(this, 'MyKey', { trustAccountIdentities: true }); ``` With either the `@aws-cdk/aws-kms:defaultKeyPolicies` feature flag set, @@ -158,8 +158,8 @@ This enables the root account user -- via IAM policies -- to grant access to oth With the above default policy, future permissions can be added to either the key policy or IAM principal policy. ```ts -const key = new kms.Key(stack, 'MyKey'); -const user = new iam.User(stack, 'MyUser'); +const key = new kms.Key(this, 'MyKey'); +const user = new iam.User(this, 'MyUser'); key.grantEncrypt(user); // Adds encrypt permissions to user policy; key policy is unmodified. ``` @@ -177,12 +177,12 @@ A common addition to the key policy would be to add other key admins that are al via the `grantAdmin` method. ```ts -const myTrustedAdminRole = iam.Role.fromRoleArn(stack, 'TrustedRole', 'arn:aws:iam:....'); -const key = new kms.Key(stack, 'MyKey', { +const myTrustedAdminRole = iam.Role.fromRoleArn(this, 'TrustedRole', 'arn:aws:iam:....'); +const key = new kms.Key(this, 'MyKey', { admins: [myTrustedAdminRole], }); -const secondKey = new kms.Key(stack, 'MyKey2'); +const secondKey = new kms.Key(this, 'MyKey2'); secondKey.grantAdmin(myTrustedAdminRole); ``` @@ -193,7 +193,7 @@ and with `trustedAccountIdentities` set to false (the default), specifying a pol provided policy to the default key policy, rather than _replacing_ the default policy. ```ts -const myTrustedAdminRole = iam.Role.fromRoleArn(stack, 'TrustedRole', 'arn:aws:iam:....'); +const myTrustedAdminRole = iam.Role.fromRoleArn(this, 'TrustedRole', 'arn:aws:iam:....'); // Creates a limited admin policy and assigns to the account root. const myCustomPolicy = new iam.PolicyDocument({ statements: [new iam.PolicyStatement({ @@ -208,7 +208,7 @@ const myCustomPolicy = new iam.PolicyDocument({ resources: ['*'], })], }); -const key = new kms.Key(stack, 'MyKey', { +const key = new kms.Key(this, 'MyKey', { policy: myCustomPolicy, }); ``` diff --git a/packages/@aws-cdk/aws-kms/rosetta/default.ts-fixture b/packages/@aws-cdk/aws-kms/rosetta/default.ts-fixture new file mode 100644 index 0000000000000..3e5ab4d8a6ab9 --- /dev/null +++ b/packages/@aws-cdk/aws-kms/rosetta/default.ts-fixture @@ -0,0 +1,14 @@ +// Fixture with packages imported, but nothing else +import { Construct } from 'constructs'; +import { Duration, Stack } from '@aws-cdk/core'; +import * as kms from '@aws-cdk/aws-kms'; +import * as iam from '@aws-cdk/aws-iam'; + +class Fixture extends Stack { + constructor(scope: Construct, id: string) { + super(scope, id); + + /// here + } +} + From a605525ddda34d36ded30cd19bc0a1b45b3b870a Mon Sep 17 00:00:00 2001 From: kaizen3031593 <36202692+kaizen3031593@users.noreply.github.com> Date: Wed, 27 Oct 2021 06:00:50 -0400 Subject: [PATCH 48/87] docs(ecr): make examples compile (#17169) ---- *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-ecr/README.md | 24 +++++++++---------- .../aws-ecr/rosetta/default.ts-fixture | 23 ++++++++++++++++++ 2 files changed, 34 insertions(+), 13 deletions(-) create mode 100644 packages/@aws-cdk/aws-ecr/rosetta/default.ts-fixture diff --git a/packages/@aws-cdk/aws-ecr/README.md b/packages/@aws-cdk/aws-ecr/README.md index 03172cac6ff82..193d5de2f0645 100644 --- a/packages/@aws-cdk/aws-ecr/README.md +++ b/packages/@aws-cdk/aws-ecr/README.md @@ -27,16 +27,19 @@ const repository = new ecr.Repository(this, 'Repository'); Amazon ECR image scanning helps in identifying software vulnerabilities in your container images. You can manually scan container images stored in Amazon ECR, or you can configure your repositories to scan images when you push them to a repository. To create a new repository to scan on push, simply enable `imageScanOnPush` in the properties ```ts -const repository = new ecr.Repository(stack, 'Repo', { - imageScanOnPush: true +const repository = new ecr.Repository(this, 'Repo', { + imageScanOnPush: true, }); ``` To create an `onImageScanCompleted` event rule and trigger the event target ```ts +declare const repository: ecr.Repository; +declare const target: SomeTarget; + repository.onImageScanCompleted('ImageScanComplete') - .addTarget(...) + .addTarget(target); ``` ### Authorization Token @@ -50,10 +53,7 @@ A Docker authorization token can be obtained using the `GetAuthorizationToken` E grants an IAM user access to call this API. ```ts -import * as iam from '@aws-cdk/aws-iam'; -import * as ecr from '@aws-cdk/aws-ecr'; - -const user = new iam.User(this, 'User', { ... }); +const user = new iam.User(this, 'User'); ecr.AuthorizationToken.grantRead(user); ``` @@ -65,10 +65,7 @@ higher rate and bandwidth limits. The following code snippet grants an IAM user access to retrieve an authorization token for the public gallery. ```ts -import * as iam from '@aws-cdk/aws-iam'; -import * as ecr from '@aws-cdk/aws-ecr'; - -const user = new iam.User(this, 'User', { ... }); +const user = new iam.User(this, 'User'); ecr.PublicGalleryAuthorizationToken.grantRead(user); ``` @@ -79,7 +76,7 @@ This user can then proceed to login to the registry using one of the [authentica You can set tag immutability on images in our repository using the `imageTagMutability` construct prop. ```ts -new ecr.Repository(stack, 'Repo', { imageTagMutability: ecr.TagMutability.IMMUTABLE }); +new ecr.Repository(this, 'Repo', { imageTagMutability: ecr.TagMutability.IMMUTABLE }); ``` ## Automatically clean up repositories @@ -91,6 +88,7 @@ against that image. For example, the following deletes images older than is important here): ```ts +declare const repository: ecr.Repository; repository.addLifecycleRule({ tagPrefixList: ['prod'], maxImageCount: 9999 }); -repository.addLifecycleRule({ maxImageAge: cdk.Duration.days(30) }); +repository.addLifecycleRule({ maxImageAge: Duration.days(30) }); ``` diff --git a/packages/@aws-cdk/aws-ecr/rosetta/default.ts-fixture b/packages/@aws-cdk/aws-ecr/rosetta/default.ts-fixture new file mode 100644 index 0000000000000..6381522ef9b78 --- /dev/null +++ b/packages/@aws-cdk/aws-ecr/rosetta/default.ts-fixture @@ -0,0 +1,23 @@ +// Fixture with packages imported, but nothing else +import { Construct } from 'constructs'; +import { Duration, Stack } from '@aws-cdk/core'; +import * as ecr from '@aws-cdk/aws-ecr'; +import * as events from '@aws-cdk/aws-events'; +import * as iam from '@aws-cdk/aws-iam'; + +class SomeTarget implements events.IRuleTarget { + public bind(): events.RuleTargetConfig { + return { + arn: 'ARN1', + }; + } +} + +class Fixture extends Stack { + constructor(scope: Construct, id: string) { + super(scope, id); + + /// here + } +} + From f357955b9bd17bf705832336d12835c3de5c3d40 Mon Sep 17 00:00:00 2001 From: kaizen3031593 <36202692+kaizen3031593@users.noreply.github.com> Date: Wed, 27 Oct 2021 06:56:03 -0400 Subject: [PATCH 49/87] docs(ecs-patterns): make examples compile (#17171) ---- *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-ecs-patterns/README.md | 233 ++++++++++-------- .../rosetta/default.ts-fixture | 17 ++ 2 files changed, 146 insertions(+), 104 deletions(-) create mode 100644 packages/@aws-cdk/aws-ecs-patterns/rosetta/default.ts-fixture diff --git a/packages/@aws-cdk/aws-ecs-patterns/README.md b/packages/@aws-cdk/aws-ecs-patterns/README.md index 00212e704e294..386682e0b75d9 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/README.md +++ b/packages/@aws-cdk/aws-ecs-patterns/README.md @@ -24,14 +24,15 @@ To define an Amazon ECS service that is behind an application load balancer, ins * `ApplicationLoadBalancedEc2Service` ```ts -const loadBalancedEcsService = new ecsPatterns.ApplicationLoadBalancedEc2Service(stack, 'Service', { +declare const cluster: ecs.Cluster; +const loadBalancedEcsService = new ecsPatterns.ApplicationLoadBalancedEc2Service(this, 'Service', { cluster, memoryLimitMiB: 1024, taskImageOptions: { image: ecs.ContainerImage.fromRegistry('test'), environment: { TEST_ENVIRONMENT_VARIABLE1: "test environment variable 1 value", - TEST_ENVIRONMENT_VARIABLE2: "test environment variable 2 value" + TEST_ENVIRONMENT_VARIABLE2: "test environment variable 2 value", }, }, desiredCount: 2, @@ -41,7 +42,8 @@ const loadBalancedEcsService = new ecsPatterns.ApplicationLoadBalancedEc2Service * `ApplicationLoadBalancedFargateService` ```ts -const loadBalancedFargateService = new ecsPatterns.ApplicationLoadBalancedFargateService(stack, 'Service', { +declare const cluster: ecs.Cluster; +const loadBalancedFargateService = new ecsPatterns.ApplicationLoadBalancedFargateService(this, 'Service', { cluster, memoryLimitMiB: 1024, cpu: 512, @@ -78,7 +80,8 @@ Additionally, if more than one application target group are needed, instantiate ```ts // One application load balancer with one listener and two target groups. -const loadBalancedEc2Service = new ApplicationMultipleTargetGroupsEc2Service(stack, 'Service', { +declare const cluster: ecs.Cluster; +const loadBalancedEc2Service = new ecsPatterns.ApplicationMultipleTargetGroupsEc2Service(this, 'Service', { cluster, memoryLimitMiB: 256, taskImageOptions: { @@ -91,9 +94,9 @@ const loadBalancedEc2Service = new ApplicationMultipleTargetGroupsEc2Service(sta { containerPort: 90, pathPattern: 'a/b/c', - priority: 10 - } - ] + priority: 10, + }, + ], }); ``` @@ -101,7 +104,8 @@ const loadBalancedEc2Service = new ApplicationMultipleTargetGroupsEc2Service(sta ```ts // One application load balancer with one listener and two target groups. -const loadBalancedFargateService = new ApplicationMultipleTargetGroupsFargateService(stack, 'Service', { +declare const cluster: ecs.Cluster; +const loadBalancedFargateService = new ecsPatterns.ApplicationMultipleTargetGroupsFargateService(this, 'Service', { cluster, memoryLimitMiB: 1024, cpu: 512, @@ -115,9 +119,9 @@ const loadBalancedFargateService = new ApplicationMultipleTargetGroupsFargateSer { containerPort: 90, pathPattern: 'a/b/c', - priority: 10 - } - ] + priority: 10, + }, + ], }); ``` @@ -128,14 +132,15 @@ To define an Amazon ECS service that is behind a network load balancer, instanti * `NetworkLoadBalancedEc2Service` ```ts -const loadBalancedEcsService = new ecsPatterns.NetworkLoadBalancedEc2Service(stack, 'Service', { +declare const cluster: ecs.Cluster; +const loadBalancedEcsService = new ecsPatterns.NetworkLoadBalancedEc2Service(this, 'Service', { cluster, memoryLimitMiB: 1024, taskImageOptions: { image: ecs.ContainerImage.fromRegistry('test'), environment: { TEST_ENVIRONMENT_VARIABLE1: "test environment variable 1 value", - TEST_ENVIRONMENT_VARIABLE2: "test environment variable 2 value" + TEST_ENVIRONMENT_VARIABLE2: "test environment variable 2 value", }, }, desiredCount: 2, @@ -145,7 +150,8 @@ const loadBalancedEcsService = new ecsPatterns.NetworkLoadBalancedEc2Service(sta * `NetworkLoadBalancedFargateService` ```ts -const loadBalancedFargateService = new ecsPatterns.NetworkLoadBalancedFargateService(stack, 'Service', { +declare const cluster: ecs.Cluster; +const loadBalancedFargateService = new ecsPatterns.NetworkLoadBalancedFargateService(this, 'Service', { cluster, memoryLimitMiB: 1024, cpu: 512, @@ -167,7 +173,8 @@ Additionally, if more than one network target group is needed, instantiate one o ```ts // Two network load balancers, each with their own listener and target group. -const loadBalancedEc2Service = new NetworkMultipleTargetGroupsEc2Service(stack, 'Service', { +declare const cluster: ecs.Cluster; +const loadBalancedEc2Service = new ecsPatterns.NetworkMultipleTargetGroupsEc2Service(this, 'Service', { cluster, memoryLimitMiB: 256, taskImageOptions: { @@ -178,29 +185,29 @@ const loadBalancedEc2Service = new NetworkMultipleTargetGroupsEc2Service(stack, name: 'lb1', listeners: [ { - name: 'listener1' - } - ] + name: 'listener1', + }, + ], }, { name: 'lb2', listeners: [ { - name: 'listener2' - } - ] - } + name: 'listener2', + }, + ], + }, ], targetGroups: [ { containerPort: 80, - listener: 'listener1' + listener: 'listener1', }, { containerPort: 90, - listener: 'listener2' - } - ] + listener: 'listener2', + }, + ], }); ``` @@ -208,7 +215,8 @@ const loadBalancedEc2Service = new NetworkMultipleTargetGroupsEc2Service(stack, ```ts // Two network load balancers, each with their own listener and target group. -const loadBalancedFargateService = new NetworkMultipleTargetGroupsFargateService(stack, 'Service', { +declare const cluster: ecs.Cluster; +const loadBalancedFargateService = new ecsPatterns.NetworkMultipleTargetGroupsFargateService(this, 'Service', { cluster, memoryLimitMiB: 512, taskImageOptions: { @@ -219,29 +227,29 @@ const loadBalancedFargateService = new NetworkMultipleTargetGroupsFargateService name: 'lb1', listeners: [ { - name: 'listener1' - } - ] + name: 'listener1', + }, + ], }, { name: 'lb2', listeners: [ { - name: 'listener2' - } - ] - } + name: 'listener2', + }, + ], + }, ], targetGroups: [ { containerPort: 80, - listener: 'listener1' + listener: 'listener1', }, { containerPort: 90, - listener: 'listener2' - } - ] + listener: 'listener2', + }, + ], }); ``` @@ -252,7 +260,8 @@ To define a service that creates a queue and reads from that queue, instantiate * `QueueProcessingEc2Service` ```ts -const queueProcessingEc2Service = new QueueProcessingEc2Service(stack, 'Service', { +declare const cluster: ecs.Cluster; +const queueProcessingEc2Service = new ecsPatterns.QueueProcessingEc2Service(this, 'Service', { cluster, memoryLimitMiB: 1024, image: ecs.ContainerImage.fromRegistry('test'), @@ -261,9 +270,8 @@ const queueProcessingEc2Service = new QueueProcessingEc2Service(stack, 'Service' desiredTaskCount: 2, environment: { TEST_ENVIRONMENT_VARIABLE1: "test environment variable 1 value", - TEST_ENVIRONMENT_VARIABLE2: "test environment variable 2 value" + TEST_ENVIRONMENT_VARIABLE2: "test environment variable 2 value", }, - queue, maxScalingCapacity: 5, containerName: 'test', }); @@ -272,7 +280,8 @@ const queueProcessingEc2Service = new QueueProcessingEc2Service(stack, 'Service' * `QueueProcessingFargateService` ```ts -const queueProcessingFargateService = new QueueProcessingFargateService(stack, 'Service', { +declare const cluster: ecs.Cluster; +const queueProcessingFargateService = new ecsPatterns.QueueProcessingFargateService(this, 'Service', { cluster, memoryLimitMiB: 512, image: ecs.ContainerImage.fromRegistry('test'), @@ -281,9 +290,8 @@ const queueProcessingFargateService = new QueueProcessingFargateService(stack, ' desiredTaskCount: 2, environment: { TEST_ENVIRONMENT_VARIABLE1: "test environment variable 1 value", - TEST_ENVIRONMENT_VARIABLE2: "test environment variable 2 value" + TEST_ENVIRONMENT_VARIABLE2: "test environment variable 2 value", }, - queue, maxScalingCapacity: 5, containerName: 'test', }); @@ -299,29 +307,31 @@ To define a task that runs periodically, there are 2 options: ```ts // Instantiate an Amazon EC2 Task to run at a scheduled interval -const ecsScheduledTask = new ScheduledEc2Task(stack, 'ScheduledTask', { +declare const cluster: ecs.Cluster; +const ecsScheduledTask = new ecsPatterns.ScheduledEc2Task(this, 'ScheduledTask', { cluster, scheduledEc2TaskImageOptions: { image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), memoryLimitMiB: 256, environment: { name: 'TRIGGER', value: 'CloudWatch Events' }, }, - schedule: events.Schedule.expression('rate(1 minute)'), + schedule: appscaling.Schedule.expression('rate(1 minute)'), enabled: true, - ruleName: 'sample-scheduled-task-rule' + ruleName: 'sample-scheduled-task-rule', }); ``` * `ScheduledFargateTask` ```ts -const scheduledFargateTask = new ScheduledFargateTask(stack, 'ScheduledFargateTask', { +declare const cluster: ecs.Cluster; +const scheduledFargateTask = new ecsPatterns.ScheduledFargateTask(this, 'ScheduledFargateTask', { cluster, scheduledFargateTaskImageOptions: { image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), memoryLimitMiB: 512, }, - schedule: events.Schedule.expression('rate(1 minute)'), + schedule: appscaling.Schedule.expression('rate(1 minute)'), platformVersion: ecs.FargatePlatformVersion.LATEST, }); ``` @@ -333,7 +343,6 @@ In addition to using the constructs, users can also add logic to customize these ### Configure HTTPS on an ApplicationLoadBalancedFargateService ```ts -import { ApplicationLoadBalancedFargateService } from './application-load-balanced-fargate-service'; import { HostedZone } from '@aws-cdk/aws-route53'; import { Certificate } from '@aws-cdk/aws-certificatemanager'; import { SslPolicy } from '@aws-cdk/aws-elasticloadbalancingv2'; @@ -341,8 +350,10 @@ import { SslPolicy } from '@aws-cdk/aws-elasticloadbalancingv2'; const domainZone = HostedZone.fromLookup(this, 'Zone', { domainName: 'example.com' }); const certificate = Certificate.fromCertificateArn(this, 'Cert', 'arn:aws:acm:us-east-1:123456:certificate/abcdefg'); -const loadBalancedFargateService = new ApplicationLoadBalancedFargateService(stack, 'Service', { - vpc +declare const vpc: ec2.Vpc; +declare const cluster: ecs.Cluster; +const loadBalancedFargateService = new ecsPatterns.ApplicationLoadBalancedFargateService(this, 'Service', { + vpc, cluster, certificate, sslPolicy: SslPolicy.RECOMMENDED, @@ -358,10 +369,8 @@ const loadBalancedFargateService = new ApplicationLoadBalancedFargateService(sta ### Add Schedule-Based Auto-Scaling to an ApplicationLoadBalancedFargateService ```ts -import { Schedule } from '@aws-cdk/aws-applicationautoscaling'; -import { ApplicationLoadBalancedFargateService, ApplicationLoadBalancedFargateServiceProps } from './application-load-balanced-fargate-service'; - -const loadBalancedFargateService = new ApplicationLoadBalancedFargateService(stack, 'Service', { +declare const cluster: ecs.Cluster; +const loadBalancedFargateService = new ecsPatterns.ApplicationLoadBalancedFargateService(this, 'Service', { cluster, memoryLimitMiB: 1024, desiredCount: 1, @@ -377,12 +386,12 @@ const scalableTarget = loadBalancedFargateService.service.autoScaleTaskCount({ }); scalableTarget.scaleOnSchedule('DaytimeScaleDown', { - schedule: Schedule.cron({ hour: '8', minute: '0'}), + schedule: appscaling.Schedule.cron({ hour: '8', minute: '0'}), minCapacity: 1, }); scalableTarget.scaleOnSchedule('EveningRushScaleUp', { - schedule: Schedule.cron({ hour: '20', minute: '0'}), + schedule: appscaling.Schedule.cron({ hour: '20', minute: '0'}), minCapacity: 10, }); ``` @@ -390,9 +399,8 @@ scalableTarget.scaleOnSchedule('EveningRushScaleUp', { ### Add Metric-Based Auto-Scaling to an ApplicationLoadBalancedFargateService ```ts -import { ApplicationLoadBalancedFargateService } from './application-load-balanced-fargate-service'; - -const loadBalancedFargateService = new ApplicationLoadBalancedFargateService(stack, 'Service', { +declare const cluster: ecs.Cluster; +const loadBalancedFargateService = new ecsPatterns.ApplicationLoadBalancedFargateService(this, 'Service', { cluster, memoryLimitMiB: 1024, desiredCount: 1, @@ -419,9 +427,8 @@ scalableTarget.scaleOnMemoryUtilization('MemoryScaling', { ### Change the default Deployment Controller ```ts -import { ApplicationLoadBalancedFargateService } from './application-load-balanced-fargate-service'; - -const loadBalancedFargateService = new ApplicationLoadBalancedFargateService(stack, 'Service', { +declare const cluster: ecs.Cluster; +const loadBalancedFargateService = new ecsPatterns.ApplicationLoadBalancedFargateService(this, 'Service', { cluster, memoryLimitMiB: 1024, desiredCount: 1, @@ -443,7 +450,8 @@ deployment circuit breaker and optionally enable `rollback` for automatic rollba for more details. ```ts -const service = new ApplicationLoadBalancedFargateService(stack, 'Service', { +declare const cluster: ecs.Cluster; +const service = new ecsPatterns.ApplicationLoadBalancedFargateService(this, 'Service', { cluster, memoryLimitMiB: 1024, desiredCount: 1, @@ -458,7 +466,8 @@ const service = new ApplicationLoadBalancedFargateService(stack, 'Service', { ### Set deployment configuration on QueueProcessingService ```ts -const queueProcessingFargateService = new QueueProcessingFargateService(stack, 'Service', { +declare const cluster: ecs.Cluster; +const queueProcessingFargateService = new ecsPatterns.QueueProcessingFargateService(this, 'Service', { cluster, memoryLimitMiB: 512, image: ecs.ContainerImage.fromRegistry('test'), @@ -466,17 +475,18 @@ const queueProcessingFargateService = new QueueProcessingFargateService(stack, ' enableLogging: false, desiredTaskCount: 2, environment: {}, - queue, maxScalingCapacity: 5, maxHealthyPercent: 200, - minHealthPercent: 66, + minHealthyPercent: 66, }); ``` ### Set taskSubnets and securityGroups for QueueProcessingFargateService ```ts -const queueProcessingFargateService = new QueueProcessingFargateService(stack, 'Service', { +declare const vpc: ec2.Vpc; +declare const securityGroup: ec2.SecurityGroup; +const queueProcessingFargateService = new ecsPatterns.QueueProcessingFargateService(this, 'Service', { vpc, memoryLimitMiB: 512, image: ecs.ContainerImage.fromRegistry('test'), @@ -488,7 +498,8 @@ const queueProcessingFargateService = new QueueProcessingFargateService(stack, ' ### Define tasks with public IPs for QueueProcessingFargateService ```ts -const queueProcessingFargateService = new QueueProcessingFargateService(stack, 'Service', { +declare const vpc: ec2.Vpc; +const queueProcessingFargateService = new ecsPatterns.QueueProcessingFargateService(this, 'Service', { vpc, memoryLimitMiB: 512, image: ecs.ContainerImage.fromRegistry('test'), @@ -499,24 +510,24 @@ const queueProcessingFargateService = new QueueProcessingFargateService(stack, ' ### Define tasks with custom queue parameters for QueueProcessingFargateService ```ts -const queueProcessingFargateService = new QueueProcessingFargateService(stack, 'Service', { +declare const vpc: ec2.Vpc; +const queueProcessingFargateService = new ecsPatterns.QueueProcessingFargateService(this, 'Service', { vpc, memoryLimitMiB: 512, image: ecs.ContainerImage.fromRegistry('test'), maxReceiveCount: 42, - retentionPeriod: cdk.Duration.days(7), - visibilityTimeout: cdk.Duration.minutes(5), + retentionPeriod: Duration.days(7), + visibilityTimeout: Duration.minutes(5), }); ``` ### Set capacityProviderStrategies for QueueProcessingFargateService ```ts -const vpc = new ec2.Vpc(stack, 'Vpc', { maxAzs: 1 }); -const cluster = new ecs.Cluster(stack, 'EcsCluster', { vpc }); +declare const cluster: ecs.Cluster; cluster.enableFargateCapacityProviders(); -const queueProcessingFargateService = new QueueProcessingFargateService(stack, 'Service', { +const queueProcessingFargateService = new ecsPatterns.QueueProcessingFargateService(this, 'Service', { cluster, memoryLimitMiB: 512, image: ecs.ContainerImage.fromRegistry('test'), @@ -536,19 +547,21 @@ const queueProcessingFargateService = new QueueProcessingFargateService(stack, ' ### Set capacityProviderStrategies for QueueProcessingEc2Service ```ts -const vpc = new ec2.Vpc(stack, 'Vpc', { maxAzs: 1 }); -const cluster = new ecs.Cluster(stack, 'EcsCluster', { vpc }); -const autoScalingGroup = new autoscaling.AutoScalingGroup(stack, 'asg', { +import * as autoscaling from '@aws-cdk/aws-autoscaling'; + +const vpc = new ec2.Vpc(this, 'Vpc', { maxAzs: 1 }); +const cluster = new ecs.Cluster(this, 'EcsCluster', { vpc }); +const autoScalingGroup = new autoscaling.AutoScalingGroup(this, 'asg', { vpc, instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.MICRO), machineImage: ecs.EcsOptimizedImage.amazonLinux2(), }); -const capacityProvider = new ecs.AsgCapacityProvider(stack, 'provider', { +const capacityProvider = new ecs.AsgCapacityProvider(this, 'provider', { autoScalingGroup, }); cluster.addAsgCapacityProvider(capacityProvider); -const queueProcessingFargateService = new QueueProcessingFargateService(stack, 'Service', { +const queueProcessingFargateService = new ecsPatterns.QueueProcessingFargateService(this, 'Service', { cluster, memoryLimitMiB: 512, image: ecs.ContainerImage.fromRegistry('test'), @@ -563,7 +576,8 @@ const queueProcessingFargateService = new QueueProcessingFargateService(stack, ' ### Select specific vpc subnets for ApplicationLoadBalancedFargateService ```ts -const loadBalancedFargateService = new ApplicationLoadBalancedFargateService(stack, 'Service', { +declare const cluster: ecs.Cluster; +const loadBalancedFargateService = new ecsPatterns.ApplicationLoadBalancedFargateService(this, 'Service', { cluster, memoryLimitMiB: 1024, desiredCount: 1, @@ -571,8 +585,8 @@ const loadBalancedFargateService = new ApplicationLoadBalancedFargateService(sta taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"), }, - vpcSubnets: { - subnets: [ec2.Subnet.fromSubnetId(stack, 'subnet', 'VpcISOLATEDSubnet1Subnet80F07FA0')], + taskSubnets: { + subnets: [ec2.Subnet.fromSubnetId(this, 'subnet', 'VpcISOLATEDSubnet1Subnet80F07FA0')], }, }); ``` @@ -580,13 +594,14 @@ const loadBalancedFargateService = new ApplicationLoadBalancedFargateService(sta ### Set PlatformVersion for ScheduledFargateTask ```ts -const scheduledFargateTask = new ScheduledFargateTask(stack, 'ScheduledFargateTask', { +declare const cluster: ecs.Cluster; +const scheduledFargateTask = new ecsPatterns.ScheduledFargateTask(this, 'ScheduledFargateTask', { cluster, scheduledFargateTaskImageOptions: { image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), memoryLimitMiB: 512, }, - schedule: events.Schedule.expression('rate(1 minute)'), + schedule: appscaling.Schedule.expression('rate(1 minute)'), platformVersion: ecs.FargatePlatformVersion.VERSION1_4, }); ``` @@ -594,18 +609,17 @@ const scheduledFargateTask = new ScheduledFargateTask(stack, 'ScheduledFargateTa ### Set SecurityGroups for ScheduledFargateTask ```ts -const stack = new cdk.Stack(); -const vpc = new ec2.Vpc(stack, 'Vpc', { maxAzs: 1 }); -const cluster = new ecs.Cluster(stack, 'EcsCluster', { vpc }); -const securityGroup = new ec2.SecurityGroup(stack, 'SG', { vpc }); +const vpc = new ec2.Vpc(this, 'Vpc', { maxAzs: 1 }); +const cluster = new ecs.Cluster(this, 'EcsCluster', { vpc }); +const securityGroup = new ec2.SecurityGroup(this, 'SG', { vpc }); -const scheduledFargateTask = new ScheduledFargateTask(stack, 'ScheduledFargateTask', { +const scheduledFargateTask = new ecsPatterns.ScheduledFargateTask(this, 'ScheduledFargateTask', { cluster, scheduledFargateTaskImageOptions: { image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), memoryLimitMiB: 512, }, - schedule: events.Schedule.expression('rate(1 minute)'), + schedule: appscaling.Schedule.expression('rate(1 minute)'), securityGroups: [securityGroup], }); ``` @@ -626,12 +640,20 @@ If a desiredCount is not passed in as input to the above constructs, CloudFormat To enable the feature flag, ensure that the REMOVE_DEFAULT_DESIRED_COUNT flag within an application stack context is set to true, like so: ```ts +declare const stack: Stack; stack.node.setContext(cxapi.ECS_REMOVE_DEFAULT_DESIRED_COUNT, true); ``` The following is an example of an application with the REMOVE_DEFAULT_DESIRED_COUNT feature flag enabled: -```ts +```ts nofixture +import { App, Stack } from '@aws-cdk/core'; +import * as ec2 from '@aws-cdk/aws-ec2'; +import * as ecs from '@aws-cdk/aws-ecs'; +import * as ecsPatterns from '@aws-cdk/aws-ecs-patterns'; +import * as cxapi from '@aws-cdk/cx-api'; +import * as path from 'path'; + const app = new App(); const stack = new Stack(app, 'aws-ecs-patterns-queue'); @@ -641,7 +663,7 @@ const vpc = new ec2.Vpc(stack, 'VPC', { maxAzs: 2, }); -new QueueProcessingFargateService(stack, 'QueueProcessingService', { +new ecsPatterns.QueueProcessingFargateService(stack, 'QueueProcessingService', { vpc, memoryLimitMiB: 512, image: new ecs.AssetImage(path.join(__dirname, '..', 'sqs-reader')), @@ -653,28 +675,31 @@ new QueueProcessingFargateService(stack, 'QueueProcessingService', { The following is an example of deploying an application along with a metrics sidecar container that utilizes `dockerLabels` for discovery: ```ts -const service = new ApplicationLoadBalancedFargateService(stack, 'Service', { +declare const cluster: ecs.Cluster; +declare const vpc: ec2.Vpc; +const service = new ecsPatterns.ApplicationLoadBalancedFargateService(this, 'Service', { cluster, vpc, desiredCount: 1, taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"), + dockerLabels: { + 'application.label.one': 'first_label', + 'application.label.two': 'second_label', + }, }, - dockerLabels: { - 'application.label.one': 'first_label' - 'application.label.two': 'second_label' - } }); service.taskDefinition.addContainer('Sidecar', { - image: ContainerImage.fromRegistry('example/metrics-sidecar') -} + image: ecs.ContainerImage.fromRegistry('example/metrics-sidecar'), +}); ``` ### Select specific load balancer name ApplicationLoadBalancedFargateService ```ts -const loadBalancedFargateService = new ApplicationLoadBalancedFargateService(stack, 'Service', { +declare const cluster: ecs.Cluster; +const loadBalancedFargateService = new ecsPatterns.ApplicationLoadBalancedFargateService(this, 'Service', { cluster, memoryLimitMiB: 1024, desiredCount: 1, @@ -682,8 +707,8 @@ const loadBalancedFargateService = new ApplicationLoadBalancedFargateService(sta taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"), }, - vpcSubnets: { - subnets: [ec2.Subnet.fromSubnetId(stack, 'subnet', 'VpcISOLATEDSubnet1Subnet80F07FA0')], + taskSubnets: { + subnets: [ec2.Subnet.fromSubnetId(this, 'subnet', 'VpcISOLATEDSubnet1Subnet80F07FA0')], }, loadBalancerName: 'application-lb-name', }); diff --git a/packages/@aws-cdk/aws-ecs-patterns/rosetta/default.ts-fixture b/packages/@aws-cdk/aws-ecs-patterns/rosetta/default.ts-fixture new file mode 100644 index 0000000000000..e998fef0a9210 --- /dev/null +++ b/packages/@aws-cdk/aws-ecs-patterns/rosetta/default.ts-fixture @@ -0,0 +1,17 @@ +// Fixture with packages imported, but nothing else +import { Construct } from 'constructs'; +import { Duration, Stack } from '@aws-cdk/core'; +import * as ecs from '@aws-cdk/aws-ecs'; +import * as ecsPatterns from '@aws-cdk/aws-ecs-patterns'; +import * as ec2 from '@aws-cdk/aws-ec2'; +import * as appscaling from '@aws-cdk/aws-applicationautoscaling'; +import * as cxapi from '@aws-cdk/cx-api'; + +class Fixture extends Stack { + constructor(scope: Construct, id: string) { + super(scope, id); + + /// here + } +} + From a8528577a841064ccdc11bb1fbd8d8046073fa8a Mon Sep 17 00:00:00 2001 From: Nick Lynch Date: Wed, 27 Oct 2021 12:48:43 +0100 Subject: [PATCH 50/87] chore: update DEPRECATED_APIs.md and introduce new plaintext format (#17120) As part of the upcoming v2 GA, we need to update (and lock in) the final list of deprecated APIs that will be removed from V2. At the same time, we need to create the input for `jsii`'s new `--strip-deprecated` file input, where only a subset of deprecated items are stripped away (see #16566). This change does both by introducing a new output format for `list-deprecated-apis` and feeding that value into `jsii` at compile time. fixes #16566 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- DEPRECATED_APIs.md | 286 +++++++- deprecated_apis.txt | 1121 +++++++++++++++++++++++++++++++ scripts/list-deprecated-apis.js | 81 ++- 3 files changed, 1448 insertions(+), 40 deletions(-) create mode 100644 deprecated_apis.txt diff --git a/DEPRECATED_APIs.md b/DEPRECATED_APIs.md index a08cf9de97f86..fdf0a1877b5dc 100644 --- a/DEPRECATED_APIs.md +++ b/DEPRECATED_APIs.md @@ -3,6 +3,8 @@ | Module | API Element | Message | |--------|-------------|---------| | @aws-cdk/core | AppProps.โ€‹runtimeInfo | use `versionReporting` instead | +| @aws-cdk/core | Arn.โ€‹parse() | use split instead | +| @aws-cdk/core | ArnComponents.โ€‹sep | use arnFormat instead | | @aws-cdk/core | AssetHashType.โ€‹BUNDLE | use `OUTPUT` instead | | @aws-cdk/core | AssetStaging.โ€‹sourceHash | see `assetHash`. | | @aws-cdk/core | AssetStaging.โ€‹stagedPath | Use `absoluteStagedPath` instead. | @@ -40,11 +42,13 @@ | @aws-cdk/core | Stack.โ€‹parentStack | use `nestedStackParent` | | @aws-cdk/core | Stack.โ€‹addDockerImageAsset() | Use `stack.synthesizer.addDockerImageAsset()` if you are calling, and a different `IStackSynthesizer` class if you are implementing. | | @aws-cdk/core | Stack.โ€‹addFileAsset() | Use `stack.synthesizer.addFileAsset()` if you are calling, and a different IStackSynthesizer class if you are implementing. | +| @aws-cdk/core | Stack.โ€‹parseArn() | use splitArn instead | | @aws-cdk/core | Stack.โ€‹prepareCrossReference() | cross reference handling has been moved to `App.prepare()`. | | @aws-cdk/core | Stack.โ€‹reportMissingContext() | use `reportMissingContextKey()` | | @aws-cdk/core | SynthesisOptions | use `app.synth()` or `stage.synth()` instead | | @aws-cdk/core | SynthesisOptions.โ€‹outdir | use `app.synth()` or `stage.synth()` instead | | @aws-cdk/core | SynthesisOptions.โ€‹skipValidation | use `app.synth()` or `stage.synth()` instead | +| @aws-cdk/core | SynthesisOptions.โ€‹validateOnSynthesis | use `app.synth()` or `stage.synth()` instead | | @aws-cdk/core | Tag.โ€‹add() | use `Tags.of(scope).add()` | | @aws-cdk/core | Tag.โ€‹remove() | use `Tags.of(scope).remove()` | | @aws-cdk/cloud-assembly-schema | ContainerImageAssetMetadataEntry.โ€‹imageNameParameter | specify `repositoryName` and `imageTag` instead, and then you know where the image will go. | @@ -60,7 +64,7 @@ | @aws-cdk/cx-api | MissingContext.โ€‹provider | moved to package 'cloud-assembly-schema' | | @aws-cdk/cx-api | RuntimeInfo | moved to package 'cloud-assembly-schema' | | constructs | Construct.โ€‹onValidate() | use `Node.addValidation()` to subscribe validation functions on this construct instead of overriding this method. | -| constructs | Node.โ€‹uniqueId | please avoid using this property and use `uid` instead. This algorithm uses MD5, which is not FIPS-complient and also excludes the identity of the root construct from the calculation. | +| constructs | Node.โ€‹uniqueId | please avoid using this property and use `addr` to form unique names. This algorithm uses MD5, which is not FIPS-complient and also excludes the identity of the root construct from the calculation. | | @aws-cdk/assets | CopyOptions | see `core.CopyOptions` | | @aws-cdk/assets | CopyOptions.โ€‹exclude | see `core.CopyOptions` | | @aws-cdk/assets | CopyOptions.โ€‹follow | use `followSymlinks` instead | @@ -77,10 +81,6 @@ | @aws-cdk/assets | Staging | use `core.AssetStaging` | | @aws-cdk/assets | StagingProps | use `core.AssetStagingProps` | | @aws-cdk/assets | StagingProps.โ€‹sourcePath | use `core.AssetStagingProps` | -| @aws-cdk/aws-iam | Anyone | use `AnyPrincipal` | -| @aws-cdk/aws-iam | IPrincipal.โ€‹addToPolicy() | Use `addToPrincipalPolicy` instead. | -| @aws-cdk/aws-iam | RoleProps.โ€‹externalId | see {@link externalIds} | -| @aws-cdk/aws-kms | KeyProps.โ€‹trustAccountIdentities | redundant with the `@aws-cdk/aws-kms:defaultKeyPolicies` feature flag | | @aws-cdk/aws-codebuild | LinuxBuildImage.โ€‹UBUNTU_โ€‹14_โ€‹04_โ€‹ANDROID_โ€‹JAVA8_โ€‹24_โ€‹4_โ€‹1 | Use {@link STANDARD_2_0} and specify runtime in buildspec runtime-versions section | | @aws-cdk/aws-codebuild | LinuxBuildImage.โ€‹UBUNTU_โ€‹14_โ€‹04_โ€‹ANDROID_โ€‹JAVA8_โ€‹26_โ€‹1_โ€‹1 | Use {@link STANDARD_2_0} and specify runtime in buildspec runtime-versions section | | @aws-cdk/aws-codebuild | LinuxBuildImage.โ€‹UBUNTU_โ€‹14_โ€‹04_โ€‹BASE | Use {@link STANDARD_2_0} and specify runtime in buildspec runtime-versions section | @@ -112,10 +112,11 @@ | @aws-cdk/aws-codebuild | LinuxBuildImage.โ€‹UBUNTU_โ€‹14_โ€‹04_โ€‹RUBY_โ€‹2_โ€‹5_โ€‹1 | Use {@link STANDARD_2_0} and specify runtime in buildspec runtime-versions section | | @aws-cdk/aws-codebuild | LinuxBuildImage.โ€‹UBUNTU_โ€‹14_โ€‹04_โ€‹RUBY_โ€‹2_โ€‹5_โ€‹3 | Use {@link STANDARD_2_0} and specify runtime in buildspec runtime-versions section | | @aws-cdk/aws-codebuild | WindowsBuildImage.โ€‹WIN_โ€‹SERVER_โ€‹CORE_โ€‹2016_โ€‹BASE | `WindowsBuildImage.WINDOWS_BASE_2_0` should be used instead. | +| @aws-cdk/aws-cloudwatch | CommonMetricOptions.โ€‹dimensions | Use 'dimensionsMap' instead. | | @aws-cdk/aws-cloudwatch | CreateAlarmOptions.โ€‹period | Use `metric.with({ period: ... })` to encode the period into the Metric object | | @aws-cdk/aws-cloudwatch | CreateAlarmOptions.โ€‹statistic | Use `metric.with({ statistic: ... })` to encode the period into the Metric object | -| @aws-cdk/aws-cloudwatch | IMetric.โ€‹toAlarmConfig() | Use `toMetricsConfig()` instead. | -| @aws-cdk/aws-cloudwatch | IMetric.โ€‹toGraphConfig() | Use `toMetricsConfig()` instead. | +| @aws-cdk/aws-cloudwatch | IMetric.โ€‹toAlarmConfig() | Use `toMetricConfig()` instead. | +| @aws-cdk/aws-cloudwatch | IMetric.โ€‹toGraphConfig() | Use `toMetricConfig()` instead. | | @aws-cdk/aws-cloudwatch | MathExpression.โ€‹toAlarmConfig() | use toMetricConfig() | | @aws-cdk/aws-cloudwatch | MathExpression.โ€‹toGraphConfig() | use toMetricConfig() | | @aws-cdk/aws-cloudwatch | Metric.โ€‹toAlarmConfig() | use toMetricConfig() | @@ -143,12 +144,21 @@ | @aws-cdk/aws-cloudwatch | MetricRenderingProperties.โ€‹color | Replaced by MetricConfig. | | @aws-cdk/aws-cloudwatch | MetricRenderingProperties.โ€‹label | Replaced by MetricConfig. | | @aws-cdk/aws-cloudwatch | MetricRenderingProperties.โ€‹stat | Replaced by MetricConfig. | +| @aws-cdk/aws-iam | Anyone | use `AnyPrincipal` | +| @aws-cdk/aws-iam | IPrincipal.โ€‹addToPolicy() | Use `addToPrincipalPolicy` instead. | +| @aws-cdk/aws-iam | RoleProps.โ€‹externalId | see {@link externalIds} | | @aws-cdk/aws-events | EventBus.โ€‹grantPutEvents() | use grantAllPutEvents instead | | @aws-cdk/aws-events | RuleTargetConfig.โ€‹id | no replacement. we will always use an autogenerated id. | +| @aws-cdk/aws-ec2 | ClientVpnAuthorizationRuleProps.โ€‹clientVpnEndoint | Use `clientVpnEndpoint` instead | +| @aws-cdk/aws-ec2 | ClientVpnRouteProps.โ€‹clientVpnEndoint | Use `clientVpnEndpoint` instead | | @aws-cdk/aws-ec2 | InterfaceVpcEndpoint.โ€‹securityGroupId | use the `connections` object | | @aws-cdk/aws-ec2 | InterfaceVpcEndpointAttributes.โ€‹securityGroupId | use `securityGroups` instead | +| @aws-cdk/aws-ec2 | MachineImage.โ€‹fromSSMParameter() | Use `MachineImage.fromSsmParameter()` instead | | @aws-cdk/aws-ec2 | NatInstanceProps.โ€‹allowAllTraffic | Use `defaultAllowedTraffic`. | +| @aws-cdk/aws-ec2 | SecurityGroup.โ€‹securityGroupName | returns the security group ID, rather than the name. | | @aws-cdk/aws-ec2 | SubnetSelection.โ€‹subnetName | Use `subnetGroupName` instead | +| @aws-cdk/aws-ec2 | SubnetType.โ€‹ISOLATED | use `SubnetType.PRIVATE_ISOLATED` | +| @aws-cdk/aws-ec2 | SubnetType.โ€‹PRIVATE | use `PRIVATE_WITH_NAT` | | @aws-cdk/aws-ec2 | Vpc.โ€‹natDependencies | This value is no longer used. | | @aws-cdk/aws-ec2 | Vpc.โ€‹addDynamoDbEndpoint() | use `addGatewayEndpoint()` instead | | @aws-cdk/aws-ec2 | Vpc.โ€‹addS3Endpoint() | use `addGatewayEndpoint()` instead | @@ -168,11 +178,13 @@ | @aws-cdk/aws-ec2 | WindowsVersion.โ€‹WINDOWS_โ€‹SERVER_โ€‹2012_โ€‹RTM_โ€‹PORTUGESE_โ€‹PORTUGAL_โ€‹64BIT_โ€‹BASE | use WINDOWS_SERVER_2012_RTM_PORTUGUESE_PORTUGAL_64BIT_BASE | | @aws-cdk/aws-ec2 | WindowsVersion.โ€‹WINDOWS_โ€‹SERVER_โ€‹2019_โ€‹PORTUGESE_โ€‹BRAZIL_โ€‹FULL_โ€‹BASE | use WINDOWS_SERVER_2019_PORTUGUESE_BRAZIL_FULL_BASE | | @aws-cdk/aws-ec2 | WindowsVersion.โ€‹WINDOWS_โ€‹SERVER_โ€‹2019_โ€‹PORTUGESE_โ€‹PORTUGAL_โ€‹FULL_โ€‹BASE | use WINDOWS_SERVER_2019_PORTUGUESE_PORTUGAL_FULL_BASE | +| @aws-cdk/aws-kms | KeyProps.โ€‹trustAccountIdentities | redundant with the `@aws-cdk/aws-kms:defaultKeyPolicies` feature flag | | @aws-cdk/aws-s3-assets | Asset.โ€‹s3Url | use `httpUrl` | | @aws-cdk/aws-s3-assets | Asset.โ€‹sourceHash | see `assetHash` | | @aws-cdk/aws-s3-assets | AssetOptions.โ€‹sourceHash | see `assetHash` and `assetHashType` | | @aws-cdk/aws-ecr-assets | DockerImageAsset.โ€‹sourceHash | use assetHash | | @aws-cdk/aws-ecr-assets | DockerImageAssetOptions.โ€‹repositoryName | to control the location of docker image assets, please override `Stack.addDockerImageAsset`. this feature will be removed in future releases. | +| @aws-cdk/aws-ecr-assets | TarballImageAsset.โ€‹sourceHash | use assetHash | | @aws-cdk/aws-secretsmanager | AttachedSecretOptions | use `secret.attach()` instead | | @aws-cdk/aws-secretsmanager | AttachedSecretOptions.โ€‹target | use `secret.attach()` instead | | @aws-cdk/aws-secretsmanager | AttachmentTargetType.โ€‹INSTANCE | use RDS_DB_INSTANCE instead | @@ -181,6 +193,8 @@ | @aws-cdk/aws-secretsmanager | Secret.โ€‹fromSecretName() | use `fromSecretNameV2` | | @aws-cdk/aws-secretsmanager | Secret.โ€‹addTargetAttachment() | use `attach()` instead | | @aws-cdk/aws-secretsmanager | SecretAttributes.โ€‹secretArn | use `secretCompleteArn` or `secretPartialArn` instead. | +| @aws-cdk/aws-secretsmanager | SecretRotationApplication.โ€‹applicationId | only valid when deploying to the 'aws' partition. Use `applicationArnForPartition` instead. | +| @aws-cdk/aws-secretsmanager | SecretRotationApplication.โ€‹semanticVersion | only valid when deploying to the 'aws' partition. Use `semanticVersionForPartition` instead. | | @aws-cdk/aws-lambda | Code.โ€‹isInline | this value is ignored since inline is now determined based on the the `inlineCode` field of `CodeConfig` returned from `bind()`. | | @aws-cdk/aws-lambda | Code.โ€‹asset() | use `fromAsset` | | @aws-cdk/aws-lambda | Code.โ€‹bucket() | use `fromBucket` | @@ -188,6 +202,7 @@ | @aws-cdk/aws-lambda | Code.โ€‹inline() | use `fromInline` | | @aws-cdk/aws-lambda | Function.โ€‹addVersion() | This method will create an AWS::Lambda::Version resource which snapshots the AWS Lambda function *at the time of its creation* and it won't get updated when the function changes. Instead, use `this.currentVersion` to obtain a reference to a version resource that gets automatically recreated when the function configuration (or code) changes. | | @aws-cdk/aws-lambda | FunctionAttributes.โ€‹securityGroupId | use `securityGroup` instead | +| @aws-cdk/aws-lambda | FunctionOptions.โ€‹architectures | use `architecture` | | @aws-cdk/aws-lambda | FunctionOptions.โ€‹securityGroup | This property is deprecated, use securityGroups instead | | @aws-cdk/aws-lambda | LogRetention | use `LogRetention` from ' | | @aws-cdk/aws-lambda | LogRetentionProps | use `LogRetentionProps` from ' | @@ -472,10 +487,10 @@ | @aws-cdk/aws-apigateway | CfnStageV2Props.โ€‹routeSettings | moved to package aws-apigatewayv2 | | @aws-cdk/aws-apigateway | CfnStageV2Props.โ€‹stageVariables | moved to package aws-apigatewayv2 | | @aws-cdk/aws-apigateway | CfnStageV2Props.โ€‹tags | moved to package aws-apigatewayv2 | -| @aws-cdk/aws-apigateway | EmptyModel | You should use | -| @aws-cdk/aws-apigateway | EmptyModel.โ€‹modelId | You should use | -| @aws-cdk/aws-apigateway | ErrorModel | You should use | -| @aws-cdk/aws-apigateway | ErrorModel.โ€‹modelId | You should use | +| @aws-cdk/aws-apigateway | EmptyModel | You should use Model.EMPTY_MODEL | +| @aws-cdk/aws-apigateway | EmptyModel.โ€‹modelId | You should use Model.EMPTY_MODEL | +| @aws-cdk/aws-apigateway | ErrorModel | You should use Model.ERROR_MODEL | +| @aws-cdk/aws-apigateway | ErrorModel.โ€‹modelId | You should use Model.ERROR_MODEL | | @aws-cdk/aws-apigateway | IResource.โ€‹restApi | Throws an error if this Resource is not associated with an instance of `RestApi`. Use `api` instead. | | @aws-cdk/aws-apigateway | LambdaRestApiProps.โ€‹options | the `LambdaRestApiProps` now extends `RestApiProps`, so all options are just available here. Note that the options specified in `options` will be overridden by any props specified at the root level. | | @aws-cdk/aws-apigateway | Method.โ€‹restApi | Throws an error if this Resource is not associated with an instance of `RestApi`. Use `api` instead. | @@ -489,6 +504,7 @@ | @aws-cdk/aws-certificatemanager | CertificateProps.โ€‹validationDomains | use `validation` instead. | | @aws-cdk/aws-certificatemanager | CertificateProps.โ€‹validationMethod | use `validation` instead. | | @aws-cdk/aws-route53 | AddressRecordTarget | Use RecordTarget | +| @aws-cdk/custom-resources | AwsSdkCall.โ€‹outputPath | use outputPaths instead | | @aws-cdk/custom-resources | Provider.โ€‹bind() | use `provider.serviceToken` instead | | @aws-cdk/aws-cloudformation | CloudFormationCapabilities | use `core.CfnCapabilities` | | @aws-cdk/aws-cloudformation | CloudFormationCapabilities.โ€‹NONE | use `core.CfnCapabilities` | @@ -520,6 +536,8 @@ | @aws-cdk/aws-sns | NumericConditions.โ€‹whitelist | use `allowlist` | | @aws-cdk/aws-sns | StringConditions.โ€‹blacklist | use `denylist` | | @aws-cdk/aws-sns | StringConditions.โ€‹whitelist | use `allowlist` | +| @aws-cdk/aws-cognito | StandardAttributes.โ€‹emailVerified | this is not a standard attribute and was incorrectly added to the CDK. It is a Cognito built-in attribute and cannot be controlled as part of user pool creation. | +| @aws-cdk/aws-cognito | StandardAttributes.โ€‹phoneNumberVerified | this is not a standard attribute and was incorrectly added to the CDK. It is a Cognito built-in attribute and cannot be controlled as part of user pool creation. | | @aws-cdk/aws-elasticloadbalancingv2 | AddFixedResponseProps | Use `ApplicationListener.addAction` instead. | | @aws-cdk/aws-elasticloadbalancingv2 | AddRedirectResponseProps | Use `ApplicationListener.addAction` instead. | | @aws-cdk/aws-elasticloadbalancingv2 | AddRuleProps.โ€‹hostHeader | Use `conditions` instead. | @@ -573,6 +591,11 @@ | @aws-cdk/aws-elasticloadbalancingv2 | TargetGroupAttributes.โ€‹defaultPort | This property is unused and the wrong type. No need to use it. | | @aws-cdk/aws-elasticloadbalancingv2 | TargetGroupImportProps | Use TargetGroupAttributes instead | | @aws-cdk/aws-apigatewayv2 | IHttpApi.โ€‹httpApiId | use apiId instead | +| @aws-cdk/aws-appmesh | Protocol | not for use outside package | +| @aws-cdk/aws-appmesh | Protocol.โ€‹HTTP | not for use outside package | +| @aws-cdk/aws-appmesh | Protocol.โ€‹TCP | not for use outside package | +| @aws-cdk/aws-appmesh | Protocol.โ€‹HTTP2 | not for use outside package | +| @aws-cdk/aws-appmesh | Protocol.โ€‹GRPC | not for use outside package | | @aws-cdk/aws-dynamodb | ITable.โ€‹metricSystemErrors() | use `metricSystemErrorsForOperations` | | @aws-cdk/aws-dynamodb | Table.โ€‹grantListStreams() | Use {@link #grantTableListStreams} for more granular permission | | @aws-cdk/aws-dynamodb | Table.โ€‹metricSystemErrors() | use `metricSystemErrorsForOperations`. | @@ -594,6 +617,40 @@ | @aws-cdk/aws-rds | DatabaseInstanceEngine.โ€‹oracleSe() | instances can no longer be created with this engine. See https://forums.aws.amazon.com/ann.jspa?annID=7341 | | @aws-cdk/aws-rds | DatabaseInstanceEngine.โ€‹oracleSe1() | instances can no longer be created with this engine. See https://forums.aws.amazon.com/ann.jspa?annID=7341 | | @aws-cdk/aws-rds | DatabaseInstanceNewProps.โ€‹vpcPlacement | use `vpcSubnets` | +| @aws-cdk/aws-rds | MariaDbEngineVersion.โ€‹VER_โ€‹10_โ€‹0 | MariaDB 10.0 will reach end of life on May 18, 2021 | +| @aws-cdk/aws-rds | MariaDbEngineVersion.โ€‹VER_โ€‹10_โ€‹0_โ€‹17 | MariaDB 10.0 will reach end of life on May 18, 2021 | +| @aws-cdk/aws-rds | MariaDbEngineVersion.โ€‹VER_โ€‹10_โ€‹0_โ€‹24 | MariaDB 10.0 will reach end of life on May 18, 2021 | +| @aws-cdk/aws-rds | MariaDbEngineVersion.โ€‹VER_โ€‹10_โ€‹0_โ€‹28 | MariaDB 10.0 will reach end of life on May 18, 2021 | +| @aws-cdk/aws-rds | MariaDbEngineVersion.โ€‹VER_โ€‹10_โ€‹0_โ€‹31 | MariaDB 10.0 will reach end of life on May 18, 2021 | +| @aws-cdk/aws-rds | MariaDbEngineVersion.โ€‹VER_โ€‹10_โ€‹0_โ€‹32 | MariaDB 10.0 will reach end of life on May 18, 2021 | +| @aws-cdk/aws-rds | MariaDbEngineVersion.โ€‹VER_โ€‹10_โ€‹0_โ€‹34 | MariaDB 10.0 will reach end of life on May 18, 2021 | +| @aws-cdk/aws-rds | MariaDbEngineVersion.โ€‹VER_โ€‹10_โ€‹0_โ€‹35 | MariaDB 10.0 will reach end of life on May 18, 2021 | +| @aws-cdk/aws-rds | MariaDbEngineVersion.โ€‹VER_โ€‹10_โ€‹1 | MariaDB 10.1 will reach end of life on May 18, 2021 | +| @aws-cdk/aws-rds | MariaDbEngineVersion.โ€‹VER_โ€‹10_โ€‹1_โ€‹14 | MariaDB 10.1 will reach end of life on May 18, 2021 | +| @aws-cdk/aws-rds | MariaDbEngineVersion.โ€‹VER_โ€‹10_โ€‹1_โ€‹19 | MariaDB 10.1 will reach end of life on May 18, 2021 | +| @aws-cdk/aws-rds | MariaDbEngineVersion.โ€‹VER_โ€‹10_โ€‹1_โ€‹23 | MariaDB 10.1 will reach end of life on May 18, 2021 | +| @aws-cdk/aws-rds | MariaDbEngineVersion.โ€‹VER_โ€‹10_โ€‹1_โ€‹26 | MariaDB 10.1 will reach end of life on May 18, 2021 | +| @aws-cdk/aws-rds | MariaDbEngineVersion.โ€‹VER_โ€‹10_โ€‹1_โ€‹31 | MariaDB 10.1 will reach end of life on May 18, 2021 | +| @aws-cdk/aws-rds | MariaDbEngineVersion.โ€‹VER_โ€‹10_โ€‹1_โ€‹34 | MariaDB 10.1 will reach end of life on May 18, 2021 | +| @aws-cdk/aws-rds | MysqlEngineVersion.โ€‹VER_โ€‹5_โ€‹5 | MySQL 5.5 will reach end of life on May 25, 2021 | +| @aws-cdk/aws-rds | MysqlEngineVersion.โ€‹VER_โ€‹5_โ€‹5_โ€‹46 | MySQL 5.5 will reach end of life on May 25, 2021 | +| @aws-cdk/aws-rds | MysqlEngineVersion.โ€‹VER_โ€‹5_โ€‹5_โ€‹53 | MySQL 5.5 will reach end of life on May 25, 2021 | +| @aws-cdk/aws-rds | MysqlEngineVersion.โ€‹VER_โ€‹5_โ€‹5_โ€‹57 | MySQL 5.5 will reach end of life on May 25, 2021 | +| @aws-cdk/aws-rds | MysqlEngineVersion.โ€‹VER_โ€‹5_โ€‹5_โ€‹59 | MySQL 5.5 will reach end of life on May 25, 2021 | +| @aws-cdk/aws-rds | MysqlEngineVersion.โ€‹VER_โ€‹5_โ€‹5_โ€‹61 | MySQL 5.5 will reach end of life on May 25, 2021 | +| @aws-cdk/aws-rds | MysqlEngineVersion.โ€‹VER_โ€‹5_โ€‹6 | MySQL 5.6 will reach end of life on August 3, 2021 | +| @aws-cdk/aws-rds | MysqlEngineVersion.โ€‹VER_โ€‹5_โ€‹6_โ€‹34 | MySQL 5.6 will reach end of life on August 3, 2021 | +| @aws-cdk/aws-rds | MysqlEngineVersion.โ€‹VER_โ€‹5_โ€‹6_โ€‹35 | MySQL 5.6 will reach end of life on August 3, 2021 | +| @aws-cdk/aws-rds | MysqlEngineVersion.โ€‹VER_โ€‹5_โ€‹6_โ€‹37 | MySQL 5.6 will reach end of life on August 3, 2021 | +| @aws-cdk/aws-rds | MysqlEngineVersion.โ€‹VER_โ€‹5_โ€‹6_โ€‹39 | MySQL 5.6 will reach end of life on August 3, 2021 | +| @aws-cdk/aws-rds | MysqlEngineVersion.โ€‹VER_โ€‹5_โ€‹6_โ€‹40 | MySQL 5.6 will reach end of life on August 3, 2021 | +| @aws-cdk/aws-rds | MysqlEngineVersion.โ€‹VER_โ€‹5_โ€‹6_โ€‹41 | MySQL 5.6 will reach end of life on August 3, 2021 | +| @aws-cdk/aws-rds | MysqlEngineVersion.โ€‹VER_โ€‹5_โ€‹6_โ€‹43 | MySQL 5.6 will reach end of life on August 3, 2021 | +| @aws-cdk/aws-rds | MysqlEngineVersion.โ€‹VER_โ€‹5_โ€‹6_โ€‹44 | MySQL 5.6 will reach end of life on August 3, 2021 | +| @aws-cdk/aws-rds | MysqlEngineVersion.โ€‹VER_โ€‹5_โ€‹6_โ€‹46 | MySQL 5.6 will reach end of life on August 3, 2021 | +| @aws-cdk/aws-rds | MysqlEngineVersion.โ€‹VER_โ€‹5_โ€‹6_โ€‹48 | MySQL 5.6 will reach end of life on August 3, 2021 | +| @aws-cdk/aws-rds | MysqlEngineVersion.โ€‹VER_โ€‹5_โ€‹6_โ€‹49 | MySQL 5.6 will reach end of life on August 3, 2021 | +| @aws-cdk/aws-rds | MysqlEngineVersion.โ€‹VER_โ€‹5_โ€‹6_โ€‹51 | MySQL 5.6 will reach end of life on August 3, 2021 | | @aws-cdk/aws-rds | OracleLegacyEngineVersion | instances can no longer be created with these engine versions. See https://forums.aws.amazon.com/ann.jspa?annID=7341 | | @aws-cdk/aws-rds | OracleLegacyEngineVersion.โ€‹VER_โ€‹11_โ€‹2 | instances can no longer be created with these engine versions. See https://forums.aws.amazon.com/ann.jspa?annID=7341 | | @aws-cdk/aws-rds | OracleLegacyEngineVersion.โ€‹VER_โ€‹11_โ€‹2_โ€‹0_โ€‹2_โ€‹V2 | instances can no longer be created with these engine versions. See https://forums.aws.amazon.com/ann.jspa?annID=7341 | @@ -641,6 +698,8 @@ | @aws-cdk/aws-rds | PostgresEngineVersion.โ€‹VER_โ€‹9_โ€‹5_โ€‹21 | PostgreSQL 9.5 will reach end of life on February 16, 2021 | | @aws-cdk/aws-rds | PostgresEngineVersion.โ€‹VER_โ€‹9_โ€‹5_โ€‹22 | PostgreSQL 9.5 will reach end of life on February 16, 2021 | | @aws-cdk/aws-rds | PostgresEngineVersion.โ€‹VER_โ€‹9_โ€‹5_โ€‹23 | PostgreSQL 9.5 will reach end of life on February 16, 2021 | +| @aws-cdk/aws-rds | PostgresEngineVersion.โ€‹VER_โ€‹9_โ€‹5_โ€‹24 | PostgreSQL 9.5 will reach end of life on February 16, 2021 | +| @aws-cdk/aws-rds | PostgresEngineVersion.โ€‹VER_โ€‹9_โ€‹5_โ€‹25 | PostgreSQL 9.5 will reach end of life on February 16, 2021 | | @aws-cdk/aws-rds | PostgresEngineVersion.โ€‹VER_โ€‹9_โ€‹5_โ€‹4 | PostgreSQL 9.5 will reach end of life on February 16, 2021 | | @aws-cdk/aws-rds | PostgresEngineVersion.โ€‹VER_โ€‹9_โ€‹5_โ€‹6 | PostgreSQL 9.5 will reach end of life on February 16, 2021 | | @aws-cdk/aws-rds | PostgresEngineVersion.โ€‹VER_โ€‹9_โ€‹5_โ€‹7 | PostgreSQL 9.5 will reach end of life on February 16, 2021 | @@ -657,12 +716,17 @@ | @aws-cdk/aws-rds | PostgresEngineVersion.โ€‹VER_โ€‹9_โ€‹6_โ€‹18 | PostgreSQL 9.6 will reach end of life in November 2021 | | @aws-cdk/aws-rds | PostgresEngineVersion.โ€‹VER_โ€‹9_โ€‹6_โ€‹19 | PostgreSQL 9.6 will reach end of life in November 2021 | | @aws-cdk/aws-rds | PostgresEngineVersion.โ€‹VER_โ€‹9_โ€‹6_โ€‹2 | PostgreSQL 9.6 will reach end of life in November 2021 | +| @aws-cdk/aws-rds | PostgresEngineVersion.โ€‹VER_โ€‹9_โ€‹6_โ€‹20 | PostgreSQL 9.6 will reach end of life in November 2021 | +| @aws-cdk/aws-rds | PostgresEngineVersion.โ€‹VER_โ€‹9_โ€‹6_โ€‹21 | PostgreSQL 9.6 will reach end of life in November 2021 | +| @aws-cdk/aws-rds | PostgresEngineVersion.โ€‹VER_โ€‹9_โ€‹6_โ€‹22 | PostgreSQL 9.6 will reach end of life in November 2021 | +| @aws-cdk/aws-rds | PostgresEngineVersion.โ€‹VER_โ€‹9_โ€‹6_โ€‹23 | PostgreSQL 9.6 will reach end of life in November 2021 | | @aws-cdk/aws-rds | PostgresEngineVersion.โ€‹VER_โ€‹9_โ€‹6_โ€‹3 | PostgreSQL 9.6 will reach end of life in November 2021 | | @aws-cdk/aws-rds | PostgresEngineVersion.โ€‹VER_โ€‹9_โ€‹6_โ€‹5 | PostgreSQL 9.6 will reach end of life in November 2021 | | @aws-cdk/aws-rds | PostgresEngineVersion.โ€‹VER_โ€‹9_โ€‹6_โ€‹6 | PostgreSQL 9.6 will reach end of life in November 2021 | | @aws-cdk/aws-rds | PostgresEngineVersion.โ€‹VER_โ€‹9_โ€‹6_โ€‹8 | PostgreSQL 9.6 will reach end of life in November 2021 | | @aws-cdk/aws-rds | PostgresEngineVersion.โ€‹VER_โ€‹9_โ€‹6_โ€‹9 | PostgreSQL 9.6 will reach end of life in November 2021 | | @aws-cdk/aws-rds | SnapshotCredentials.โ€‹fromGeneratedPassword() | use `fromGeneratedSecret()` for new Clusters and Instances. Note that switching from `fromGeneratedPassword()` to `fromGeneratedSecret()` for already deployed Clusters or Instances will update their master password. | +| @aws-cdk/aws-rds | SqlServerEngineVersion.โ€‹VER_โ€‹15_โ€‹00_โ€‹4043_โ€‹23_โ€‹V1 | This version is erroneous. You might be looking for {@link SqlServerEngineVersion.VER_15_00_4073_23_V1}, instead. | | @aws-cdk/aws-autoscaling | BlockDevice.โ€‹mappingEnabled | use `BlockDeviceVolume.noDevice()` as the volume to supress a mapping. | | @aws-cdk/aws-autoscaling | CommonAutoScalingGroupProps.โ€‹notificationsTopic | use `notifications` | | @aws-cdk/aws-autoscaling | CommonAutoScalingGroupProps.โ€‹replacingUpdateMinSuccessfulInstancesPercent | Use `signals` instead | @@ -683,17 +747,23 @@ | @aws-cdk/aws-autoscaling | UpdateType.โ€‹REPLACING_โ€‹UPDATE | Use UpdatePolicy instead | | @aws-cdk/aws-autoscaling | UpdateType.โ€‹ROLLING_โ€‹UPDATE | Use UpdatePolicy instead | | @aws-cdk/aws-elasticloadbalancing | LoadBalancerListener.โ€‹sslCertificateId | use sslCertificateArn instead | +| @aws-cdk/aws-ecs | AddAutoScalingGroupCapacityOptions.โ€‹taskDrainTime | The lifecycle draining hook is not configured if using the EC2 Capacity Provider. Enable managed termination protection instead. | | @aws-cdk/aws-ecs | BaseService.โ€‹configureAwsVpcNetworking() | use configureAwsVpcNetworkingWithSecurityGroups instead. | -| @aws-cdk/aws-ecs | Ec2ServiceProps.โ€‹propagateTaskTagsFrom | Use `propagateTags` instead. | +| @aws-cdk/aws-ecs | BaseServiceOptions.โ€‹propagateTaskTagsFrom | Use `propagateTags` instead. | +| @aws-cdk/aws-ecs | Cluster.โ€‹addAutoScalingGroup() | Use {@link Cluster.addAsgCapacityProvider} instead. | +| @aws-cdk/aws-ecs | Cluster.โ€‹addCapacity() | Use {@link Cluster.addAsgCapacityProvider} instead. | +| @aws-cdk/aws-ecs | Cluster.โ€‹addCapacityProvider() | Use {@link enableFargateCapacityProviders} instead. | +| @aws-cdk/aws-ecs | ClusterProps.โ€‹capacityProviders | Use {@link ClusterProps.enableFargateCapacityProviders} instead. | | @aws-cdk/aws-ecs | Ec2ServiceProps.โ€‹securityGroup | use securityGroups instead. | | @aws-cdk/aws-ecs | EcsOptimizedAmi | see {@link EcsOptimizedImage#amazonLinux}, {@link EcsOptimizedImage#amazonLinux} and {@link EcsOptimizedImage#windows} | | @aws-cdk/aws-ecs | EcsOptimizedAmi.โ€‹getImage() | see {@link EcsOptimizedImage#amazonLinux}, {@link EcsOptimizedImage#amazonLinux} and {@link EcsOptimizedImage#windows} | | @aws-cdk/aws-ecs | EcsOptimizedAmiProps | see {@link EcsOptimizedImage} | +| @aws-cdk/aws-ecs | EcsOptimizedAmiProps.โ€‹cachedInContext | see {@link EcsOptimizedImage} | | @aws-cdk/aws-ecs | EcsOptimizedAmiProps.โ€‹generation | see {@link EcsOptimizedImage} | | @aws-cdk/aws-ecs | EcsOptimizedAmiProps.โ€‹hardwareType | see {@link EcsOptimizedImage} | | @aws-cdk/aws-ecs | EcsOptimizedAmiProps.โ€‹windowsVersion | see {@link EcsOptimizedImage} | -| @aws-cdk/aws-ecs | FargateServiceProps.โ€‹propagateTaskTagsFrom | Use `propagateTags` instead. | | @aws-cdk/aws-ecs | FargateServiceProps.โ€‹securityGroup | use securityGroups instead. | +| @aws-cdk/aws-ecs | SplunkLogDriverProps.โ€‹token | Use {@link SplunkLogDriverProps.secretToken} instead. | | @aws-cdk/aws-cloudfront | AliasConfiguration | see {@link CloudFrontWebDistributionProps#viewerCertificate} with {@link ViewerCertificate#acmCertificate} | | @aws-cdk/aws-cloudfront | AliasConfiguration.โ€‹acmCertRef | see {@link CloudFrontWebDistributionProps#viewerCertificate} with {@link ViewerCertificate#acmCertificate} | | @aws-cdk/aws-cloudfront | AliasConfiguration.โ€‹names | see {@link CloudFrontWebDistributionProps#viewerCertificate} with {@link ViewerCertificate#acmCertificate} | @@ -757,6 +827,8 @@ | @aws-cdk/aws-stepfunctions | Task.โ€‹next() | replaced by service integration specific classes (i.e. LambdaInvoke, SnsPublish) | | @aws-cdk/aws-stepfunctions | Task.โ€‹toStateJson() | replaced by service integration specific classes (i.e. LambdaInvoke, SnsPublish) | | @aws-cdk/aws-stepfunctions | Task.โ€‹whenBoundToGraph() | replaced by service integration specific classes (i.e. LambdaInvoke, SnsPublish) | +| @aws-cdk/aws-stepfunctions | TaskInput.โ€‹fromContextAt() | Use `fromJsonPathAt`. | +| @aws-cdk/aws-stepfunctions | TaskInput.โ€‹fromDataAt() | Use `fromJsonPathAt`. | | @aws-cdk/aws-stepfunctions | TaskProps | replaced by service integration specific classes (i.e. LambdaInvoke, SnsPublish) | | @aws-cdk/aws-stepfunctions | TaskProps.โ€‹task | replaced by service integration specific classes (i.e. LambdaInvoke, SnsPublish) | | @aws-cdk/aws-stepfunctions | TaskProps.โ€‹comment | replaced by service integration specific classes (i.e. LambdaInvoke, SnsPublish) | @@ -861,5 +933,193 @@ | @aws-cdk/aws-stepfunctions-tasks | StartExecutionProps.โ€‹input | use 'StepFunctionsStartExecution' | | @aws-cdk/aws-stepfunctions-tasks | StartExecutionProps.โ€‹integrationPattern | use 'StepFunctionsStartExecution' | | @aws-cdk/aws-stepfunctions-tasks | StartExecutionProps.โ€‹name | use 'StepFunctionsStartExecution' | +| @aws-cdk/pipelines | AddManualApprovalOptions | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | AddManualApprovalOptions.โ€‹actionName | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | AddManualApprovalOptions.โ€‹runOrder | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | AddStackOptions | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | AddStackOptions.โ€‹executeRunOrder | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | AddStackOptions.โ€‹runOrder | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | AddStageOptions | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | AddStageOptions.โ€‹extraRunOrderSpace | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | AddStageOptions.โ€‹manualApprovals | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | AdditionalArtifact | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | AdditionalArtifact.โ€‹artifact | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | AdditionalArtifact.โ€‹directory | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | AssetPublishingCommand | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | AssetPublishingCommand.โ€‹assetId | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | AssetPublishingCommand.โ€‹assetManifestPath | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | AssetPublishingCommand.โ€‹assetPublishingRoleArn | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | AssetPublishingCommand.โ€‹assetSelector | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | AssetPublishingCommand.โ€‹assetType | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | BaseStageOptions | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | BaseStageOptions.โ€‹confirmBroadeningPermissions | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | BaseStageOptions.โ€‹securityNotificationTopic | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkPipeline | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkPipeline.โ€‹codePipeline | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkPipeline.โ€‹addApplicationStage() | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkPipeline.โ€‹addStage() | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkPipeline.โ€‹stackOutput() | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkPipeline.โ€‹stage() | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkPipeline.โ€‹validate() | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkPipelineProps | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkPipelineProps.โ€‹cloudAssemblyArtifact | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkPipelineProps.โ€‹assetBuildSpec | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkPipelineProps.โ€‹assetPreInstallCommands | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkPipelineProps.โ€‹cdkCliVersion | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkPipelineProps.โ€‹codePipeline | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkPipelineProps.โ€‹crossAccountKeys | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkPipelineProps.โ€‹dockerCredentials | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkPipelineProps.โ€‹enableKeyRotation | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkPipelineProps.โ€‹pipelineName | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkPipelineProps.โ€‹selfMutating | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkPipelineProps.โ€‹selfMutationBuildSpec | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkPipelineProps.โ€‹singlePublisherPerType | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkPipelineProps.โ€‹sourceAction | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkPipelineProps.โ€‹subnetSelection | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkPipelineProps.โ€‹supportDockerAssets | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkPipelineProps.โ€‹synthAction | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkPipelineProps.โ€‹vpc | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkStackActionFromArtifactOptions | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkStackActionFromArtifactOptions.โ€‹stackName | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkStage | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkStage.โ€‹addActions() | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkStage.โ€‹addApplication() | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkStage.โ€‹addManualApprovalAction() | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkStage.โ€‹addStackArtifactDeployment() | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkStage.โ€‹deploysStack() | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkStage.โ€‹nextSequentialRunOrder() | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkStageProps | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkStageProps.โ€‹cloudAssemblyArtifact | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkStageProps.โ€‹host | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkStageProps.โ€‹pipelineStage | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkStageProps.โ€‹stageName | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkStageProps.โ€‹confirmBroadeningPermissions | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | CdkStageProps.โ€‹securityNotificationTopic | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | DeployCdkStackAction | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | DeployCdkStackAction.โ€‹actionProperties | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | DeployCdkStackAction.โ€‹dependencyStackArtifactIds | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | DeployCdkStackAction.โ€‹executeRunOrder | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | DeployCdkStackAction.โ€‹prepareRunOrder | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | DeployCdkStackAction.โ€‹stackName | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | DeployCdkStackAction.โ€‹stackArtifactId | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | DeployCdkStackAction.โ€‹fromStackArtifact() | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | DeployCdkStackAction.โ€‹bind() | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | DeployCdkStackAction.โ€‹onStateChange() | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | DeployCdkStackActionOptions | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | DeployCdkStackActionOptions.โ€‹cloudAssemblyInput | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | DeployCdkStackActionOptions.โ€‹baseActionName | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | DeployCdkStackActionOptions.โ€‹changeSetName | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | DeployCdkStackActionOptions.โ€‹executeRunOrder | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | DeployCdkStackActionOptions.โ€‹output | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | DeployCdkStackActionOptions.โ€‹outputFileName | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | DeployCdkStackActionOptions.โ€‹prepareRunOrder | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | DeployCdkStackActionProps | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | DeployCdkStackActionProps.โ€‹actionRole | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | DeployCdkStackActionProps.โ€‹stackName | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | DeployCdkStackActionProps.โ€‹templatePath | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | DeployCdkStackActionProps.โ€‹cloudFormationExecutionRole | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | DeployCdkStackActionProps.โ€‹dependencyStackArtifactIds | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | DeployCdkStackActionProps.โ€‹region | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | DeployCdkStackActionProps.โ€‹stackArtifactId | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | DeployCdkStackActionProps.โ€‹templateConfigurationPath | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | FromStackArtifactOptions | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | FromStackArtifactOptions.โ€‹cloudAssemblyInput | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | FromStackArtifactOptions.โ€‹executeRunOrder | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | FromStackArtifactOptions.โ€‹output | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | FromStackArtifactOptions.โ€‹outputFileName | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | FromStackArtifactOptions.โ€‹prepareRunOrder | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | IStageHost | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | IStageHost.โ€‹publishAsset() | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | IStageHost.โ€‹stackOutputArtifact() | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | PublishAssetsAction | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | PublishAssetsAction.โ€‹actionProperties | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | PublishAssetsAction.โ€‹addPublishCommand() | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | PublishAssetsAction.โ€‹bind() | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | PublishAssetsAction.โ€‹onStateChange() | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | PublishAssetsActionProps | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | PublishAssetsActionProps.โ€‹actionName | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | PublishAssetsActionProps.โ€‹assetType | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | PublishAssetsActionProps.โ€‹cloudAssemblyInput | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | PublishAssetsActionProps.โ€‹buildSpec | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | PublishAssetsActionProps.โ€‹cdkCliVersion | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | PublishAssetsActionProps.โ€‹createBuildspecFile | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | PublishAssetsActionProps.โ€‹dependable | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | PublishAssetsActionProps.โ€‹preInstallCommands | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | PublishAssetsActionProps.โ€‹projectName | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | PublishAssetsActionProps.โ€‹role | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | PublishAssetsActionProps.โ€‹subnetSelection | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | PublishAssetsActionProps.โ€‹vpc | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | ShellScriptAction | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | ShellScriptAction.โ€‹actionProperties | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | ShellScriptAction.โ€‹grantPrincipal | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | ShellScriptAction.โ€‹project | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | ShellScriptAction.โ€‹bind() | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | ShellScriptAction.โ€‹onStateChange() | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | ShellScriptActionProps | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | ShellScriptActionProps.โ€‹actionName | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | ShellScriptActionProps.โ€‹commands | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | ShellScriptActionProps.โ€‹additionalArtifacts | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | ShellScriptActionProps.โ€‹bashOptions | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | ShellScriptActionProps.โ€‹environment | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | ShellScriptActionProps.โ€‹environmentVariables | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | ShellScriptActionProps.โ€‹rolePolicyStatements | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | ShellScriptActionProps.โ€‹runOrder | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | ShellScriptActionProps.โ€‹securityGroups | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | ShellScriptActionProps.โ€‹subnetSelection | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | ShellScriptActionProps.โ€‹useOutputs | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | ShellScriptActionProps.โ€‹vpc | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | SimpleSynthAction | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | SimpleSynthAction.โ€‹actionProperties | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | SimpleSynthAction.โ€‹grantPrincipal | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | SimpleSynthAction.โ€‹project | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | SimpleSynthAction.โ€‹standardNpmSynth() | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | SimpleSynthAction.โ€‹standardYarnSynth() | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | SimpleSynthAction.โ€‹bind() | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | SimpleSynthAction.โ€‹onStateChange() | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | SimpleSynthActionProps | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | SimpleSynthActionProps.โ€‹synthCommand | This class is part of the old API. Use the API based on the `CodePipeline` class instead | | @aws-cdk/pipelines | SimpleSynthActionProps.โ€‹buildCommand | Use `buildCommands` instead | +| @aws-cdk/pipelines | SimpleSynthActionProps.โ€‹buildCommands | This class is part of the old API. Use the API based on the `CodePipeline` class instead | | @aws-cdk/pipelines | SimpleSynthActionProps.โ€‹installCommand | Use `installCommands` instead | +| @aws-cdk/pipelines | SimpleSynthActionProps.โ€‹installCommands | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | SimpleSynthActionProps.โ€‹testCommands | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | SimpleSynthOptions | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | SimpleSynthOptions.โ€‹cloudAssemblyArtifact | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | SimpleSynthOptions.โ€‹sourceArtifact | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | SimpleSynthOptions.โ€‹actionName | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | SimpleSynthOptions.โ€‹additionalArtifacts | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | SimpleSynthOptions.โ€‹buildSpec | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | SimpleSynthOptions.โ€‹copyEnvironmentVariables | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | SimpleSynthOptions.โ€‹environment | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | SimpleSynthOptions.โ€‹environmentVariables | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | SimpleSynthOptions.โ€‹projectName | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | SimpleSynthOptions.โ€‹rolePolicyStatements | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | SimpleSynthOptions.โ€‹subdirectory | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | SimpleSynthOptions.โ€‹subnetSelection | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | SimpleSynthOptions.โ€‹vpc | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | StackOutput | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | StackOutput.โ€‹artifactFile | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | StackOutput.โ€‹outputName | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | StandardNpmSynthOptions | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | StandardNpmSynthOptions.โ€‹buildCommand | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | StandardNpmSynthOptions.โ€‹installCommand | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | StandardNpmSynthOptions.โ€‹synthCommand | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | StandardNpmSynthOptions.โ€‹testCommands | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | StandardYarnSynthOptions | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | StandardYarnSynthOptions.โ€‹buildCommand | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | StandardYarnSynthOptions.โ€‹installCommand | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | StandardYarnSynthOptions.โ€‹synthCommand | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | StandardYarnSynthOptions.โ€‹testCommands | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | UpdatePipelineAction | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | UpdatePipelineAction.โ€‹actionProperties | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | UpdatePipelineAction.โ€‹bind() | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | UpdatePipelineAction.โ€‹onStateChange() | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | UpdatePipelineActionProps | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | UpdatePipelineActionProps.โ€‹cloudAssemblyInput | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | UpdatePipelineActionProps.โ€‹pipelineStackHierarchicalId | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | UpdatePipelineActionProps.โ€‹buildSpec | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | UpdatePipelineActionProps.โ€‹cdkCliVersion | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | UpdatePipelineActionProps.โ€‹dockerCredentials | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | UpdatePipelineActionProps.โ€‹pipelineStackName | Use `pipelineStackHierarchicalId` instead. | +| @aws-cdk/pipelines | UpdatePipelineActionProps.โ€‹privileged | This class is part of the old API. Use the API based on the `CodePipeline` class instead | +| @aws-cdk/pipelines | UpdatePipelineActionProps.โ€‹projectName | This class is part of the old API. Use the API based on the `CodePipeline` class instead | diff --git a/deprecated_apis.txt b/deprecated_apis.txt new file mode 100644 index 0000000000000..cfda6c5068605 --- /dev/null +++ b/deprecated_apis.txt @@ -0,0 +1,1121 @@ +@aws-cdk/core.AppProps#runtimeInfo +@aws-cdk/core.Arn#parse +@aws-cdk/core.ArnComponents#sep +@aws-cdk/core.AssetHashType#BUNDLE +@aws-cdk/core.AssetStaging#sourceHash +@aws-cdk/core.AssetStaging#stagedPath +@aws-cdk/core.BundlingDockerImage +@aws-cdk/core.BundlingDockerImage#image +@aws-cdk/core.BundlingDockerImage#fromAsset +@aws-cdk/core.BundlingDockerImage#fromRegistry +@aws-cdk/core.BundlingDockerImage#cp +@aws-cdk/core.BundlingDockerImage#run +@aws-cdk/core.BundlingDockerImage#toJSON +@aws-cdk/core.CfnInclude +@aws-cdk/core.CfnInclude#template +@aws-cdk/core.CfnIncludeProps +@aws-cdk/core.CfnIncludeProps#template +@aws-cdk/core.ConstructNode#metadata +@aws-cdk/core.ConstructNode#uniqueId +@aws-cdk/core.ConstructNode#prepare +@aws-cdk/core.ConstructNode#synth +@aws-cdk/core.ConstructNode#addError +@aws-cdk/core.ConstructNode#addInfo +@aws-cdk/core.ConstructNode#addWarning +@aws-cdk/core.ConstructNode#applyAspect +@aws-cdk/core.CustomResourceProviderRuntime#NODEJS_12 +@aws-cdk/core.DefaultStackSynthesizerProps#fileAssetKeyArnExportName +@aws-cdk/core.DockerImageAssetSource#repositoryName +@aws-cdk/core.Duration#toISOString +@aws-cdk/core.FileAssetLocation#kmsKeyArn +@aws-cdk/core.FileAssetLocation#s3Url +@aws-cdk/core.ITemplateOptions#transform +@aws-cdk/core.Lazy#anyValue +@aws-cdk/core.Lazy#listValue +@aws-cdk/core.Lazy#numberValue +@aws-cdk/core.Lazy#stringValue +@aws-cdk/core.Size#pebibyte +@aws-cdk/core.Stack#parentStack +@aws-cdk/core.Stack#addDockerImageAsset +@aws-cdk/core.Stack#addFileAsset +@aws-cdk/core.Stack#parseArn +@aws-cdk/core.Stack#prepareCrossReference +@aws-cdk/core.Stack#reportMissingContext +@aws-cdk/core.SynthesisOptions +@aws-cdk/core.SynthesisOptions#outdir +@aws-cdk/core.SynthesisOptions#skipValidation +@aws-cdk/core.SynthesisOptions#validateOnSynthesis +@aws-cdk/core.Tag#add +@aws-cdk/core.Tag#remove +@aws-cdk/cloud-assembly-schema.ContainerImageAssetMetadataEntry#imageNameParameter +@aws-cdk/cloud-assembly-schema.Manifest#load +@aws-cdk/cloud-assembly-schema.Manifest#save +@aws-cdk/cx-api.AssemblyBuildOptions#runtimeInfo +@aws-cdk/cx-api.CloudAssembly#getStack +@aws-cdk/cx-api.CloudFormationStackArtifact#name +@aws-cdk/cx-api.MetadataEntry +@aws-cdk/cx-api.MissingContext +@aws-cdk/cx-api.MissingContext#key +@aws-cdk/cx-api.MissingContext#props +@aws-cdk/cx-api.MissingContext#provider +@aws-cdk/cx-api.RuntimeInfo +constructs.Construct#onValidate +constructs.Node#uniqueId +@aws-cdk/assets.CopyOptions +@aws-cdk/assets.CopyOptions#exclude +@aws-cdk/assets.CopyOptions#follow +@aws-cdk/assets.CopyOptions#ignoreMode +@aws-cdk/assets.FingerprintOptions +@aws-cdk/assets.FingerprintOptions#extraHash +@aws-cdk/assets.FollowMode +@aws-cdk/assets.FollowMode#NEVER +@aws-cdk/assets.FollowMode#ALWAYS +@aws-cdk/assets.FollowMode#EXTERNAL +@aws-cdk/assets.FollowMode#BLOCK_EXTERNAL +@aws-cdk/assets.IAsset +@aws-cdk/assets.IAsset#sourceHash +@aws-cdk/assets.Staging +@aws-cdk/assets.StagingProps +@aws-cdk/assets.StagingProps#sourcePath +@aws-cdk/aws-codebuild.LinuxBuildImage#UBUNTU_14_04_ANDROID_JAVA8_24_4_1 +@aws-cdk/aws-codebuild.LinuxBuildImage#UBUNTU_14_04_ANDROID_JAVA8_26_1_1 +@aws-cdk/aws-codebuild.LinuxBuildImage#UBUNTU_14_04_BASE +@aws-cdk/aws-codebuild.LinuxBuildImage#UBUNTU_14_04_DOCKER_17_09_0 +@aws-cdk/aws-codebuild.LinuxBuildImage#UBUNTU_14_04_DOCKER_18_09_0 +@aws-cdk/aws-codebuild.LinuxBuildImage#UBUNTU_14_04_DOTNET_CORE_1_1 +@aws-cdk/aws-codebuild.LinuxBuildImage#UBUNTU_14_04_DOTNET_CORE_2_0 +@aws-cdk/aws-codebuild.LinuxBuildImage#UBUNTU_14_04_DOTNET_CORE_2_1 +@aws-cdk/aws-codebuild.LinuxBuildImage#UBUNTU_14_04_GOLANG_1_10 +@aws-cdk/aws-codebuild.LinuxBuildImage#UBUNTU_14_04_GOLANG_1_11 +@aws-cdk/aws-codebuild.LinuxBuildImage#UBUNTU_14_04_NODEJS_10_1_0 +@aws-cdk/aws-codebuild.LinuxBuildImage#UBUNTU_14_04_NODEJS_10_14_1 +@aws-cdk/aws-codebuild.LinuxBuildImage#UBUNTU_14_04_NODEJS_6_3_1 +@aws-cdk/aws-codebuild.LinuxBuildImage#UBUNTU_14_04_NODEJS_8_11_0 +@aws-cdk/aws-codebuild.LinuxBuildImage#UBUNTU_14_04_OPEN_JDK_11 +@aws-cdk/aws-codebuild.LinuxBuildImage#UBUNTU_14_04_OPEN_JDK_8 +@aws-cdk/aws-codebuild.LinuxBuildImage#UBUNTU_14_04_OPEN_JDK_9 +@aws-cdk/aws-codebuild.LinuxBuildImage#UBUNTU_14_04_PHP_5_6 +@aws-cdk/aws-codebuild.LinuxBuildImage#UBUNTU_14_04_PHP_7_0 +@aws-cdk/aws-codebuild.LinuxBuildImage#UBUNTU_14_04_PHP_7_1 +@aws-cdk/aws-codebuild.LinuxBuildImage#UBUNTU_14_04_PYTHON_2_7_12 +@aws-cdk/aws-codebuild.LinuxBuildImage#UBUNTU_14_04_PYTHON_3_3_6 +@aws-cdk/aws-codebuild.LinuxBuildImage#UBUNTU_14_04_PYTHON_3_4_5 +@aws-cdk/aws-codebuild.LinuxBuildImage#UBUNTU_14_04_PYTHON_3_5_2 +@aws-cdk/aws-codebuild.LinuxBuildImage#UBUNTU_14_04_PYTHON_3_6_5 +@aws-cdk/aws-codebuild.LinuxBuildImage#UBUNTU_14_04_PYTHON_3_7_1 +@aws-cdk/aws-codebuild.LinuxBuildImage#UBUNTU_14_04_RUBY_2_2_5 +@aws-cdk/aws-codebuild.LinuxBuildImage#UBUNTU_14_04_RUBY_2_3_1 +@aws-cdk/aws-codebuild.LinuxBuildImage#UBUNTU_14_04_RUBY_2_5_1 +@aws-cdk/aws-codebuild.LinuxBuildImage#UBUNTU_14_04_RUBY_2_5_3 +@aws-cdk/aws-codebuild.WindowsBuildImage#WIN_SERVER_CORE_2016_BASE +@aws-cdk/aws-cloudwatch.CommonMetricOptions#dimensions +@aws-cdk/aws-cloudwatch.CreateAlarmOptions#period +@aws-cdk/aws-cloudwatch.CreateAlarmOptions#statistic +@aws-cdk/aws-cloudwatch.IMetric#toAlarmConfig +@aws-cdk/aws-cloudwatch.IMetric#toGraphConfig +@aws-cdk/aws-cloudwatch.MathExpression#toAlarmConfig +@aws-cdk/aws-cloudwatch.MathExpression#toGraphConfig +@aws-cdk/aws-cloudwatch.Metric#toAlarmConfig +@aws-cdk/aws-cloudwatch.Metric#toGraphConfig +@aws-cdk/aws-cloudwatch.MetricAlarmConfig +@aws-cdk/aws-cloudwatch.MetricAlarmConfig#metricName +@aws-cdk/aws-cloudwatch.MetricAlarmConfig#namespace +@aws-cdk/aws-cloudwatch.MetricAlarmConfig#period +@aws-cdk/aws-cloudwatch.MetricAlarmConfig#dimensions +@aws-cdk/aws-cloudwatch.MetricAlarmConfig#extendedStatistic +@aws-cdk/aws-cloudwatch.MetricAlarmConfig#statistic +@aws-cdk/aws-cloudwatch.MetricAlarmConfig#unit +@aws-cdk/aws-cloudwatch.MetricGraphConfig +@aws-cdk/aws-cloudwatch.MetricGraphConfig#metricName +@aws-cdk/aws-cloudwatch.MetricGraphConfig#namespace +@aws-cdk/aws-cloudwatch.MetricGraphConfig#period +@aws-cdk/aws-cloudwatch.MetricGraphConfig#renderingProperties +@aws-cdk/aws-cloudwatch.MetricGraphConfig#color +@aws-cdk/aws-cloudwatch.MetricGraphConfig#dimensions +@aws-cdk/aws-cloudwatch.MetricGraphConfig#label +@aws-cdk/aws-cloudwatch.MetricGraphConfig#statistic +@aws-cdk/aws-cloudwatch.MetricGraphConfig#unit +@aws-cdk/aws-cloudwatch.MetricRenderingProperties +@aws-cdk/aws-cloudwatch.MetricRenderingProperties#period +@aws-cdk/aws-cloudwatch.MetricRenderingProperties#color +@aws-cdk/aws-cloudwatch.MetricRenderingProperties#label +@aws-cdk/aws-cloudwatch.MetricRenderingProperties#stat +@aws-cdk/aws-iam.Anyone +@aws-cdk/aws-iam.IPrincipal#addToPolicy +@aws-cdk/aws-iam.RoleProps#externalId +@aws-cdk/aws-events.EventBus#grantPutEvents +@aws-cdk/aws-events.RuleTargetConfig#id +@aws-cdk/aws-ec2.ClientVpnAuthorizationRuleProps#clientVpnEndoint +@aws-cdk/aws-ec2.ClientVpnRouteProps#clientVpnEndoint +@aws-cdk/aws-ec2.InterfaceVpcEndpoint#securityGroupId +@aws-cdk/aws-ec2.InterfaceVpcEndpointAttributes#securityGroupId +@aws-cdk/aws-ec2.MachineImage#fromSSMParameter +@aws-cdk/aws-ec2.NatInstanceProps#allowAllTraffic +@aws-cdk/aws-ec2.SecurityGroup#securityGroupName +@aws-cdk/aws-ec2.SubnetSelection#subnetName +@aws-cdk/aws-ec2.SubnetType#ISOLATED +@aws-cdk/aws-ec2.SubnetType#PRIVATE +@aws-cdk/aws-ec2.Vpc#natDependencies +@aws-cdk/aws-ec2.Vpc#addDynamoDbEndpoint +@aws-cdk/aws-ec2.Vpc#addS3Endpoint +@aws-cdk/aws-ec2.VpcEndpointService#whitelistedPrincipals +@aws-cdk/aws-ec2.VpcEndpointServiceProps#vpcEndpointServiceName +@aws-cdk/aws-ec2.VpcEndpointServiceProps#whitelistedPrincipals +@aws-cdk/aws-ec2.WindowsVersion#WINDOWS_SERVER_2016_GERMAL_FULL_BASE +@aws-cdk/aws-ec2.WindowsVersion#WINDOWS_SERVER_2012_R2_SP1_PORTUGESE_BRAZIL_64BIT_CORE +@aws-cdk/aws-ec2.WindowsVersion#WINDOWS_SERVER_2016_PORTUGESE_PORTUGAL_FULL_BASE +@aws-cdk/aws-ec2.WindowsVersion#WINDOWS_SERVER_2012_R2_RTM_PORTUGESE_BRAZIL_64BIT_BASE +@aws-cdk/aws-ec2.WindowsVersion#WINDOWS_SERVER_2012_R2_RTM_PORTUGESE_PORTUGAL_64BIT_BASE +@aws-cdk/aws-ec2.WindowsVersion#WINDOWS_SERVER_2016_PORTUGESE_BRAZIL_FULL_BASE +@aws-cdk/aws-ec2.WindowsVersion#WINDOWS_SERVER_2012_SP2_PORTUGESE_BRAZIL_64BIT_BASE +@aws-cdk/aws-ec2.WindowsVersion#WINDOWS_SERVER_2012_RTM_PORTUGESE_BRAZIL_64BIT_BASE +@aws-cdk/aws-ec2.WindowsVersion#WINDOWS_SERVER_2008_R2_SP1_PORTUGESE_BRAZIL_64BIT_BASE +@aws-cdk/aws-ec2.WindowsVersion#WINDOWS_SERVER_2008_SP2_PORTUGESE_BRAZIL_32BIT_BASE +@aws-cdk/aws-ec2.WindowsVersion#WINDOWS_SERVER_2012_RTM_PORTUGESE_PORTUGAL_64BIT_BASE +@aws-cdk/aws-ec2.WindowsVersion#WINDOWS_SERVER_2019_PORTUGESE_BRAZIL_FULL_BASE +@aws-cdk/aws-ec2.WindowsVersion#WINDOWS_SERVER_2019_PORTUGESE_PORTUGAL_FULL_BASE +@aws-cdk/aws-kms.KeyProps#trustAccountIdentities +@aws-cdk/aws-s3-assets.Asset#s3Url +@aws-cdk/aws-s3-assets.Asset#sourceHash +@aws-cdk/aws-s3-assets.AssetOptions#sourceHash +@aws-cdk/aws-ecr-assets.DockerImageAsset#sourceHash +@aws-cdk/aws-ecr-assets.DockerImageAssetOptions#repositoryName +@aws-cdk/aws-ecr-assets.TarballImageAsset#sourceHash +@aws-cdk/aws-secretsmanager.AttachedSecretOptions +@aws-cdk/aws-secretsmanager.AttachedSecretOptions#target +@aws-cdk/aws-secretsmanager.AttachmentTargetType#INSTANCE +@aws-cdk/aws-secretsmanager.AttachmentTargetType#CLUSTER +@aws-cdk/aws-secretsmanager.Secret#fromSecretArn +@aws-cdk/aws-secretsmanager.Secret#fromSecretName +@aws-cdk/aws-secretsmanager.Secret#addTargetAttachment +@aws-cdk/aws-secretsmanager.SecretAttributes#secretArn +@aws-cdk/aws-secretsmanager.SecretRotationApplication#applicationId +@aws-cdk/aws-secretsmanager.SecretRotationApplication#semanticVersion +@aws-cdk/aws-lambda.Code#isInline +@aws-cdk/aws-lambda.Code#asset +@aws-cdk/aws-lambda.Code#bucket +@aws-cdk/aws-lambda.Code#cfnParameters +@aws-cdk/aws-lambda.Code#inline +@aws-cdk/aws-lambda.Function#addVersion +@aws-cdk/aws-lambda.FunctionAttributes#securityGroupId +@aws-cdk/aws-lambda.FunctionOptions#architectures +@aws-cdk/aws-lambda.FunctionOptions#securityGroup +@aws-cdk/aws-lambda.LogRetention +@aws-cdk/aws-lambda.LogRetentionProps +@aws-cdk/aws-lambda.Runtime#bundlingDockerImage +@aws-cdk/aws-apigateway.CfnApiMappingV2 +@aws-cdk/aws-apigateway.CfnApiMappingV2#CFN_RESOURCE_TYPE_NAME +@aws-cdk/aws-apigateway.CfnApiMappingV2#cfnProperties +@aws-cdk/aws-apigateway.CfnApiMappingV2#apiId +@aws-cdk/aws-apigateway.CfnApiMappingV2#domainName +@aws-cdk/aws-apigateway.CfnApiMappingV2#stage +@aws-cdk/aws-apigateway.CfnApiMappingV2#apiMappingKey +@aws-cdk/aws-apigateway.CfnApiMappingV2#inspect +@aws-cdk/aws-apigateway.CfnApiMappingV2#renderProperties +@aws-cdk/aws-apigateway.CfnApiMappingV2Props +@aws-cdk/aws-apigateway.CfnApiMappingV2Props#apiId +@aws-cdk/aws-apigateway.CfnApiMappingV2Props#domainName +@aws-cdk/aws-apigateway.CfnApiMappingV2Props#stage +@aws-cdk/aws-apigateway.CfnApiMappingV2Props#apiMappingKey +@aws-cdk/aws-apigateway.CfnApiV2 +@aws-cdk/aws-apigateway.CfnApiV2#CFN_RESOURCE_TYPE_NAME +@aws-cdk/aws-apigateway.CfnApiV2#cfnProperties +@aws-cdk/aws-apigateway.CfnApiV2#tags +@aws-cdk/aws-apigateway.CfnApiV2#body +@aws-cdk/aws-apigateway.CfnApiV2#apiKeySelectionExpression +@aws-cdk/aws-apigateway.CfnApiV2#basePath +@aws-cdk/aws-apigateway.CfnApiV2#bodyS3Location +@aws-cdk/aws-apigateway.CfnApiV2#corsConfiguration +@aws-cdk/aws-apigateway.CfnApiV2#credentialsArn +@aws-cdk/aws-apigateway.CfnApiV2#description +@aws-cdk/aws-apigateway.CfnApiV2#disableSchemaValidation +@aws-cdk/aws-apigateway.CfnApiV2#failOnWarnings +@aws-cdk/aws-apigateway.CfnApiV2#name +@aws-cdk/aws-apigateway.CfnApiV2#protocolType +@aws-cdk/aws-apigateway.CfnApiV2#routeKey +@aws-cdk/aws-apigateway.CfnApiV2#routeSelectionExpression +@aws-cdk/aws-apigateway.CfnApiV2#target +@aws-cdk/aws-apigateway.CfnApiV2#version +@aws-cdk/aws-apigateway.CfnApiV2#inspect +@aws-cdk/aws-apigateway.CfnApiV2#renderProperties +@aws-cdk/aws-apigateway.BodyS3LocationProperty +@aws-cdk/aws-apigateway.BodyS3LocationProperty#bucket +@aws-cdk/aws-apigateway.BodyS3LocationProperty#etag +@aws-cdk/aws-apigateway.BodyS3LocationProperty#key +@aws-cdk/aws-apigateway.BodyS3LocationProperty#version +@aws-cdk/aws-apigateway.CorsProperty +@aws-cdk/aws-apigateway.CorsProperty#allowCredentials +@aws-cdk/aws-apigateway.CorsProperty#allowHeaders +@aws-cdk/aws-apigateway.CorsProperty#allowMethods +@aws-cdk/aws-apigateway.CorsProperty#allowOrigins +@aws-cdk/aws-apigateway.CorsProperty#exposeHeaders +@aws-cdk/aws-apigateway.CorsProperty#maxAge +@aws-cdk/aws-apigateway.CfnApiV2Props +@aws-cdk/aws-apigateway.CfnApiV2Props#apiKeySelectionExpression +@aws-cdk/aws-apigateway.CfnApiV2Props#basePath +@aws-cdk/aws-apigateway.CfnApiV2Props#body +@aws-cdk/aws-apigateway.CfnApiV2Props#bodyS3Location +@aws-cdk/aws-apigateway.CfnApiV2Props#corsConfiguration +@aws-cdk/aws-apigateway.CfnApiV2Props#credentialsArn +@aws-cdk/aws-apigateway.CfnApiV2Props#description +@aws-cdk/aws-apigateway.CfnApiV2Props#disableSchemaValidation +@aws-cdk/aws-apigateway.CfnApiV2Props#failOnWarnings +@aws-cdk/aws-apigateway.CfnApiV2Props#name +@aws-cdk/aws-apigateway.CfnApiV2Props#protocolType +@aws-cdk/aws-apigateway.CfnApiV2Props#routeKey +@aws-cdk/aws-apigateway.CfnApiV2Props#routeSelectionExpression +@aws-cdk/aws-apigateway.CfnApiV2Props#tags +@aws-cdk/aws-apigateway.CfnApiV2Props#target +@aws-cdk/aws-apigateway.CfnApiV2Props#version +@aws-cdk/aws-apigateway.CfnAuthorizerV2 +@aws-cdk/aws-apigateway.CfnAuthorizerV2#CFN_RESOURCE_TYPE_NAME +@aws-cdk/aws-apigateway.CfnAuthorizerV2#cfnProperties +@aws-cdk/aws-apigateway.CfnAuthorizerV2#apiId +@aws-cdk/aws-apigateway.CfnAuthorizerV2#authorizerType +@aws-cdk/aws-apigateway.CfnAuthorizerV2#identitySource +@aws-cdk/aws-apigateway.CfnAuthorizerV2#name +@aws-cdk/aws-apigateway.CfnAuthorizerV2#authorizerCredentialsArn +@aws-cdk/aws-apigateway.CfnAuthorizerV2#authorizerResultTtlInSeconds +@aws-cdk/aws-apigateway.CfnAuthorizerV2#authorizerUri +@aws-cdk/aws-apigateway.CfnAuthorizerV2#identityValidationExpression +@aws-cdk/aws-apigateway.CfnAuthorizerV2#jwtConfiguration +@aws-cdk/aws-apigateway.CfnAuthorizerV2#inspect +@aws-cdk/aws-apigateway.CfnAuthorizerV2#renderProperties +@aws-cdk/aws-apigateway.JWTConfigurationProperty +@aws-cdk/aws-apigateway.JWTConfigurationProperty#audience +@aws-cdk/aws-apigateway.JWTConfigurationProperty#issuer +@aws-cdk/aws-apigateway.CfnAuthorizerV2Props +@aws-cdk/aws-apigateway.CfnAuthorizerV2Props#apiId +@aws-cdk/aws-apigateway.CfnAuthorizerV2Props#authorizerType +@aws-cdk/aws-apigateway.CfnAuthorizerV2Props#identitySource +@aws-cdk/aws-apigateway.CfnAuthorizerV2Props#name +@aws-cdk/aws-apigateway.CfnAuthorizerV2Props#authorizerCredentialsArn +@aws-cdk/aws-apigateway.CfnAuthorizerV2Props#authorizerResultTtlInSeconds +@aws-cdk/aws-apigateway.CfnAuthorizerV2Props#authorizerUri +@aws-cdk/aws-apigateway.CfnAuthorizerV2Props#identityValidationExpression +@aws-cdk/aws-apigateway.CfnAuthorizerV2Props#jwtConfiguration +@aws-cdk/aws-apigateway.CfnDeploymentV2 +@aws-cdk/aws-apigateway.CfnDeploymentV2#CFN_RESOURCE_TYPE_NAME +@aws-cdk/aws-apigateway.CfnDeploymentV2#cfnProperties +@aws-cdk/aws-apigateway.CfnDeploymentV2#apiId +@aws-cdk/aws-apigateway.CfnDeploymentV2#description +@aws-cdk/aws-apigateway.CfnDeploymentV2#stageName +@aws-cdk/aws-apigateway.CfnDeploymentV2#inspect +@aws-cdk/aws-apigateway.CfnDeploymentV2#renderProperties +@aws-cdk/aws-apigateway.CfnDeploymentV2Props +@aws-cdk/aws-apigateway.CfnDeploymentV2Props#apiId +@aws-cdk/aws-apigateway.CfnDeploymentV2Props#description +@aws-cdk/aws-apigateway.CfnDeploymentV2Props#stageName +@aws-cdk/aws-apigateway.CfnDomainNameV2 +@aws-cdk/aws-apigateway.CfnDomainNameV2#CFN_RESOURCE_TYPE_NAME +@aws-cdk/aws-apigateway.CfnDomainNameV2#attrRegionalDomainName +@aws-cdk/aws-apigateway.CfnDomainNameV2#attrRegionalHostedZoneId +@aws-cdk/aws-apigateway.CfnDomainNameV2#cfnProperties +@aws-cdk/aws-apigateway.CfnDomainNameV2#tags +@aws-cdk/aws-apigateway.CfnDomainNameV2#domainName +@aws-cdk/aws-apigateway.CfnDomainNameV2#domainNameConfigurations +@aws-cdk/aws-apigateway.CfnDomainNameV2#inspect +@aws-cdk/aws-apigateway.CfnDomainNameV2#renderProperties +@aws-cdk/aws-apigateway.DomainNameConfigurationProperty +@aws-cdk/aws-apigateway.DomainNameConfigurationProperty#certificateArn +@aws-cdk/aws-apigateway.DomainNameConfigurationProperty#certificateName +@aws-cdk/aws-apigateway.DomainNameConfigurationProperty#endpointType +@aws-cdk/aws-apigateway.CfnDomainNameV2Props +@aws-cdk/aws-apigateway.CfnDomainNameV2Props#domainName +@aws-cdk/aws-apigateway.CfnDomainNameV2Props#domainNameConfigurations +@aws-cdk/aws-apigateway.CfnDomainNameV2Props#tags +@aws-cdk/aws-apigateway.CfnIntegrationResponseV2 +@aws-cdk/aws-apigateway.CfnIntegrationResponseV2#CFN_RESOURCE_TYPE_NAME +@aws-cdk/aws-apigateway.CfnIntegrationResponseV2#cfnProperties +@aws-cdk/aws-apigateway.CfnIntegrationResponseV2#apiId +@aws-cdk/aws-apigateway.CfnIntegrationResponseV2#integrationId +@aws-cdk/aws-apigateway.CfnIntegrationResponseV2#integrationResponseKey +@aws-cdk/aws-apigateway.CfnIntegrationResponseV2#responseParameters +@aws-cdk/aws-apigateway.CfnIntegrationResponseV2#responseTemplates +@aws-cdk/aws-apigateway.CfnIntegrationResponseV2#contentHandlingStrategy +@aws-cdk/aws-apigateway.CfnIntegrationResponseV2#templateSelectionExpression +@aws-cdk/aws-apigateway.CfnIntegrationResponseV2#inspect +@aws-cdk/aws-apigateway.CfnIntegrationResponseV2#renderProperties +@aws-cdk/aws-apigateway.CfnIntegrationResponseV2Props +@aws-cdk/aws-apigateway.CfnIntegrationResponseV2Props#apiId +@aws-cdk/aws-apigateway.CfnIntegrationResponseV2Props#integrationId +@aws-cdk/aws-apigateway.CfnIntegrationResponseV2Props#integrationResponseKey +@aws-cdk/aws-apigateway.CfnIntegrationResponseV2Props#contentHandlingStrategy +@aws-cdk/aws-apigateway.CfnIntegrationResponseV2Props#responseParameters +@aws-cdk/aws-apigateway.CfnIntegrationResponseV2Props#responseTemplates +@aws-cdk/aws-apigateway.CfnIntegrationResponseV2Props#templateSelectionExpression +@aws-cdk/aws-apigateway.CfnIntegrationV2 +@aws-cdk/aws-apigateway.CfnIntegrationV2#CFN_RESOURCE_TYPE_NAME +@aws-cdk/aws-apigateway.CfnIntegrationV2#cfnProperties +@aws-cdk/aws-apigateway.CfnIntegrationV2#apiId +@aws-cdk/aws-apigateway.CfnIntegrationV2#integrationType +@aws-cdk/aws-apigateway.CfnIntegrationV2#requestParameters +@aws-cdk/aws-apigateway.CfnIntegrationV2#requestTemplates +@aws-cdk/aws-apigateway.CfnIntegrationV2#connectionType +@aws-cdk/aws-apigateway.CfnIntegrationV2#contentHandlingStrategy +@aws-cdk/aws-apigateway.CfnIntegrationV2#credentialsArn +@aws-cdk/aws-apigateway.CfnIntegrationV2#description +@aws-cdk/aws-apigateway.CfnIntegrationV2#integrationMethod +@aws-cdk/aws-apigateway.CfnIntegrationV2#integrationUri +@aws-cdk/aws-apigateway.CfnIntegrationV2#passthroughBehavior +@aws-cdk/aws-apigateway.CfnIntegrationV2#payloadFormatVersion +@aws-cdk/aws-apigateway.CfnIntegrationV2#templateSelectionExpression +@aws-cdk/aws-apigateway.CfnIntegrationV2#timeoutInMillis +@aws-cdk/aws-apigateway.CfnIntegrationV2#inspect +@aws-cdk/aws-apigateway.CfnIntegrationV2#renderProperties +@aws-cdk/aws-apigateway.CfnIntegrationV2Props +@aws-cdk/aws-apigateway.CfnIntegrationV2Props#apiId +@aws-cdk/aws-apigateway.CfnIntegrationV2Props#integrationType +@aws-cdk/aws-apigateway.CfnIntegrationV2Props#connectionType +@aws-cdk/aws-apigateway.CfnIntegrationV2Props#contentHandlingStrategy +@aws-cdk/aws-apigateway.CfnIntegrationV2Props#credentialsArn +@aws-cdk/aws-apigateway.CfnIntegrationV2Props#description +@aws-cdk/aws-apigateway.CfnIntegrationV2Props#integrationMethod +@aws-cdk/aws-apigateway.CfnIntegrationV2Props#integrationUri +@aws-cdk/aws-apigateway.CfnIntegrationV2Props#passthroughBehavior +@aws-cdk/aws-apigateway.CfnIntegrationV2Props#payloadFormatVersion +@aws-cdk/aws-apigateway.CfnIntegrationV2Props#requestParameters +@aws-cdk/aws-apigateway.CfnIntegrationV2Props#requestTemplates +@aws-cdk/aws-apigateway.CfnIntegrationV2Props#templateSelectionExpression +@aws-cdk/aws-apigateway.CfnIntegrationV2Props#timeoutInMillis +@aws-cdk/aws-apigateway.CfnModelV2 +@aws-cdk/aws-apigateway.CfnModelV2#CFN_RESOURCE_TYPE_NAME +@aws-cdk/aws-apigateway.CfnModelV2#cfnProperties +@aws-cdk/aws-apigateway.CfnModelV2#apiId +@aws-cdk/aws-apigateway.CfnModelV2#name +@aws-cdk/aws-apigateway.CfnModelV2#schema +@aws-cdk/aws-apigateway.CfnModelV2#contentType +@aws-cdk/aws-apigateway.CfnModelV2#description +@aws-cdk/aws-apigateway.CfnModelV2#inspect +@aws-cdk/aws-apigateway.CfnModelV2#renderProperties +@aws-cdk/aws-apigateway.CfnModelV2Props +@aws-cdk/aws-apigateway.CfnModelV2Props#apiId +@aws-cdk/aws-apigateway.CfnModelV2Props#name +@aws-cdk/aws-apigateway.CfnModelV2Props#schema +@aws-cdk/aws-apigateway.CfnModelV2Props#contentType +@aws-cdk/aws-apigateway.CfnModelV2Props#description +@aws-cdk/aws-apigateway.CfnRouteResponseV2 +@aws-cdk/aws-apigateway.CfnRouteResponseV2#CFN_RESOURCE_TYPE_NAME +@aws-cdk/aws-apigateway.CfnRouteResponseV2#cfnProperties +@aws-cdk/aws-apigateway.CfnRouteResponseV2#apiId +@aws-cdk/aws-apigateway.CfnRouteResponseV2#responseModels +@aws-cdk/aws-apigateway.CfnRouteResponseV2#responseParameters +@aws-cdk/aws-apigateway.CfnRouteResponseV2#routeId +@aws-cdk/aws-apigateway.CfnRouteResponseV2#routeResponseKey +@aws-cdk/aws-apigateway.CfnRouteResponseV2#modelSelectionExpression +@aws-cdk/aws-apigateway.CfnRouteResponseV2#inspect +@aws-cdk/aws-apigateway.CfnRouteResponseV2#renderProperties +@aws-cdk/aws-apigateway.ParameterConstraintsProperty +@aws-cdk/aws-apigateway.ParameterConstraintsProperty#required +@aws-cdk/aws-apigateway.CfnRouteResponseV2Props +@aws-cdk/aws-apigateway.CfnRouteResponseV2Props#apiId +@aws-cdk/aws-apigateway.CfnRouteResponseV2Props#routeId +@aws-cdk/aws-apigateway.CfnRouteResponseV2Props#routeResponseKey +@aws-cdk/aws-apigateway.CfnRouteResponseV2Props#modelSelectionExpression +@aws-cdk/aws-apigateway.CfnRouteResponseV2Props#responseModels +@aws-cdk/aws-apigateway.CfnRouteResponseV2Props#responseParameters +@aws-cdk/aws-apigateway.CfnRouteV2 +@aws-cdk/aws-apigateway.CfnRouteV2#CFN_RESOURCE_TYPE_NAME +@aws-cdk/aws-apigateway.CfnRouteV2#cfnProperties +@aws-cdk/aws-apigateway.CfnRouteV2#apiId +@aws-cdk/aws-apigateway.CfnRouteV2#requestModels +@aws-cdk/aws-apigateway.CfnRouteV2#requestParameters +@aws-cdk/aws-apigateway.CfnRouteV2#routeKey +@aws-cdk/aws-apigateway.CfnRouteV2#apiKeyRequired +@aws-cdk/aws-apigateway.CfnRouteV2#authorizationScopes +@aws-cdk/aws-apigateway.CfnRouteV2#authorizationType +@aws-cdk/aws-apigateway.CfnRouteV2#authorizerId +@aws-cdk/aws-apigateway.CfnRouteV2#modelSelectionExpression +@aws-cdk/aws-apigateway.CfnRouteV2#operationName +@aws-cdk/aws-apigateway.CfnRouteV2#routeResponseSelectionExpression +@aws-cdk/aws-apigateway.CfnRouteV2#target +@aws-cdk/aws-apigateway.CfnRouteV2#inspect +@aws-cdk/aws-apigateway.CfnRouteV2#renderProperties +@aws-cdk/aws-apigateway.ParameterConstraintsProperty +@aws-cdk/aws-apigateway.ParameterConstraintsProperty#required +@aws-cdk/aws-apigateway.CfnRouteV2Props +@aws-cdk/aws-apigateway.CfnRouteV2Props#apiId +@aws-cdk/aws-apigateway.CfnRouteV2Props#routeKey +@aws-cdk/aws-apigateway.CfnRouteV2Props#apiKeyRequired +@aws-cdk/aws-apigateway.CfnRouteV2Props#authorizationScopes +@aws-cdk/aws-apigateway.CfnRouteV2Props#authorizationType +@aws-cdk/aws-apigateway.CfnRouteV2Props#authorizerId +@aws-cdk/aws-apigateway.CfnRouteV2Props#modelSelectionExpression +@aws-cdk/aws-apigateway.CfnRouteV2Props#operationName +@aws-cdk/aws-apigateway.CfnRouteV2Props#requestModels +@aws-cdk/aws-apigateway.CfnRouteV2Props#requestParameters +@aws-cdk/aws-apigateway.CfnRouteV2Props#routeResponseSelectionExpression +@aws-cdk/aws-apigateway.CfnRouteV2Props#target +@aws-cdk/aws-apigateway.CfnStageV2 +@aws-cdk/aws-apigateway.CfnStageV2#CFN_RESOURCE_TYPE_NAME +@aws-cdk/aws-apigateway.CfnStageV2#cfnProperties +@aws-cdk/aws-apigateway.CfnStageV2#tags +@aws-cdk/aws-apigateway.CfnStageV2#apiId +@aws-cdk/aws-apigateway.CfnStageV2#routeSettings +@aws-cdk/aws-apigateway.CfnStageV2#stageName +@aws-cdk/aws-apigateway.CfnStageV2#stageVariables +@aws-cdk/aws-apigateway.CfnStageV2#accessLogSettings +@aws-cdk/aws-apigateway.CfnStageV2#autoDeploy +@aws-cdk/aws-apigateway.CfnStageV2#clientCertificateId +@aws-cdk/aws-apigateway.CfnStageV2#defaultRouteSettings +@aws-cdk/aws-apigateway.CfnStageV2#deploymentId +@aws-cdk/aws-apigateway.CfnStageV2#description +@aws-cdk/aws-apigateway.CfnStageV2#inspect +@aws-cdk/aws-apigateway.CfnStageV2#renderProperties +@aws-cdk/aws-apigateway.AccessLogSettingsProperty +@aws-cdk/aws-apigateway.AccessLogSettingsProperty#destinationArn +@aws-cdk/aws-apigateway.AccessLogSettingsProperty#format +@aws-cdk/aws-apigateway.RouteSettingsProperty +@aws-cdk/aws-apigateway.RouteSettingsProperty#dataTraceEnabled +@aws-cdk/aws-apigateway.RouteSettingsProperty#detailedMetricsEnabled +@aws-cdk/aws-apigateway.RouteSettingsProperty#loggingLevel +@aws-cdk/aws-apigateway.RouteSettingsProperty#throttlingBurstLimit +@aws-cdk/aws-apigateway.RouteSettingsProperty#throttlingRateLimit +@aws-cdk/aws-apigateway.CfnStageV2Props +@aws-cdk/aws-apigateway.CfnStageV2Props#apiId +@aws-cdk/aws-apigateway.CfnStageV2Props#stageName +@aws-cdk/aws-apigateway.CfnStageV2Props#accessLogSettings +@aws-cdk/aws-apigateway.CfnStageV2Props#autoDeploy +@aws-cdk/aws-apigateway.CfnStageV2Props#clientCertificateId +@aws-cdk/aws-apigateway.CfnStageV2Props#defaultRouteSettings +@aws-cdk/aws-apigateway.CfnStageV2Props#deploymentId +@aws-cdk/aws-apigateway.CfnStageV2Props#description +@aws-cdk/aws-apigateway.CfnStageV2Props#routeSettings +@aws-cdk/aws-apigateway.CfnStageV2Props#stageVariables +@aws-cdk/aws-apigateway.CfnStageV2Props#tags +@aws-cdk/aws-apigateway.EmptyModel +@aws-cdk/aws-apigateway.EmptyModel#modelId +@aws-cdk/aws-apigateway.ErrorModel +@aws-cdk/aws-apigateway.ErrorModel#modelId +@aws-cdk/aws-apigateway.IResource#restApi +@aws-cdk/aws-apigateway.LambdaRestApiProps#options +@aws-cdk/aws-apigateway.Method#restApi +@aws-cdk/aws-apigateway.Resource#restApi +@aws-cdk/aws-apigateway.ResourceBase#restApi +@aws-cdk/aws-apigateway.ResourceBase#url +@aws-cdk/aws-apigateway.RestApiBase#configureCloudWatchRole +@aws-cdk/aws-apigateway.RestApiBase#configureDeployment +@aws-cdk/aws-apigateway.RestApiOptions +@aws-cdk/aws-apigateway.UsagePlanProps#apiKey +@aws-cdk/aws-certificatemanager.CertificateProps#validationDomains +@aws-cdk/aws-certificatemanager.CertificateProps#validationMethod +@aws-cdk/aws-route53.AddressRecordTarget +@aws-cdk/custom-resources.AwsSdkCall#outputPath +@aws-cdk/custom-resources.Provider#bind +@aws-cdk/aws-cloudformation.CloudFormationCapabilities +@aws-cdk/aws-cloudformation.CloudFormationCapabilities#NONE +@aws-cdk/aws-cloudformation.CloudFormationCapabilities#ANONYMOUS_IAM +@aws-cdk/aws-cloudformation.CloudFormationCapabilities#NAMED_IAM +@aws-cdk/aws-cloudformation.CloudFormationCapabilities#AUTO_EXPAND +@aws-cdk/aws-cloudformation.CustomResource +@aws-cdk/aws-cloudformation.CustomResourceProps +@aws-cdk/aws-cloudformation.CustomResourceProps#provider +@aws-cdk/aws-cloudformation.CustomResourceProps#properties +@aws-cdk/aws-cloudformation.CustomResourceProps#removalPolicy +@aws-cdk/aws-cloudformation.CustomResourceProps#resourceType +@aws-cdk/aws-cloudformation.CustomResourceProvider +@aws-cdk/aws-cloudformation.CustomResourceProvider#serviceToken +@aws-cdk/aws-cloudformation.CustomResourceProvider#fromLambda +@aws-cdk/aws-cloudformation.CustomResourceProvider#fromTopic +@aws-cdk/aws-cloudformation.CustomResourceProvider#lambda +@aws-cdk/aws-cloudformation.CustomResourceProvider#topic +@aws-cdk/aws-cloudformation.CustomResourceProvider#bind +@aws-cdk/aws-cloudformation.CustomResourceProviderConfig +@aws-cdk/aws-cloudformation.CustomResourceProviderConfig#serviceToken +@aws-cdk/aws-cloudformation.ICustomResourceProvider +@aws-cdk/aws-cloudformation.ICustomResourceProvider#bind +@aws-cdk/aws-cloudformation.NestedStack +@aws-cdk/aws-cloudformation.NestedStackProps +@aws-cdk/aws-cloudformation.NestedStackProps#notifications +@aws-cdk/aws-cloudformation.NestedStackProps#parameters +@aws-cdk/aws-cloudformation.NestedStackProps#timeout +@aws-cdk/aws-sns.NumericConditions#whitelist +@aws-cdk/aws-sns.StringConditions#blacklist +@aws-cdk/aws-sns.StringConditions#whitelist +@aws-cdk/aws-cognito.StandardAttributes#emailVerified +@aws-cdk/aws-cognito.StandardAttributes#phoneNumberVerified +@aws-cdk/aws-elasticloadbalancingv2.AddFixedResponseProps +@aws-cdk/aws-elasticloadbalancingv2.AddRedirectResponseProps +@aws-cdk/aws-elasticloadbalancingv2.AddRuleProps#hostHeader +@aws-cdk/aws-elasticloadbalancingv2.AddRuleProps#pathPattern +@aws-cdk/aws-elasticloadbalancingv2.AddRuleProps#pathPatterns +@aws-cdk/aws-elasticloadbalancingv2.ApplicationListener#addCertificateArns +@aws-cdk/aws-elasticloadbalancingv2.ApplicationListener#addFixedResponse +@aws-cdk/aws-elasticloadbalancingv2.ApplicationListener#addRedirectResponse +@aws-cdk/aws-elasticloadbalancingv2.ApplicationListenerAttributes#securityGroupAllowsAllOutbound +@aws-cdk/aws-elasticloadbalancingv2.ApplicationListenerAttributes#securityGroupId +@aws-cdk/aws-elasticloadbalancingv2.ApplicationListenerCertificateProps#certificateArns +@aws-cdk/aws-elasticloadbalancingv2.ApplicationListenerRule#addFixedResponse +@aws-cdk/aws-elasticloadbalancingv2.ApplicationListenerRule#addRedirectResponse +@aws-cdk/aws-elasticloadbalancingv2.ApplicationListenerRule#addTargetGroup +@aws-cdk/aws-elasticloadbalancingv2.ApplicationListenerRule#setCondition +@aws-cdk/aws-elasticloadbalancingv2.ApplicationTargetGroup#import +@aws-cdk/aws-elasticloadbalancingv2.BaseApplicationListenerProps#certificateArns +@aws-cdk/aws-elasticloadbalancingv2.BaseApplicationListenerRuleProps#fixedResponse +@aws-cdk/aws-elasticloadbalancingv2.BaseApplicationListenerRuleProps#hostHeader +@aws-cdk/aws-elasticloadbalancingv2.BaseApplicationListenerRuleProps#pathPattern +@aws-cdk/aws-elasticloadbalancingv2.BaseApplicationListenerRuleProps#pathPatterns +@aws-cdk/aws-elasticloadbalancingv2.BaseApplicationListenerRuleProps#redirectResponse +@aws-cdk/aws-elasticloadbalancingv2.ContentType +@aws-cdk/aws-elasticloadbalancingv2.ContentType#TEXT_PLAIN +@aws-cdk/aws-elasticloadbalancingv2.ContentType#TEXT_CSS +@aws-cdk/aws-elasticloadbalancingv2.ContentType#TEXT_HTML +@aws-cdk/aws-elasticloadbalancingv2.ContentType#APPLICATION_JAVASCRIPT +@aws-cdk/aws-elasticloadbalancingv2.ContentType#APPLICATION_JSON +@aws-cdk/aws-elasticloadbalancingv2.FixedResponse +@aws-cdk/aws-elasticloadbalancingv2.FixedResponse#statusCode +@aws-cdk/aws-elasticloadbalancingv2.FixedResponse#contentType +@aws-cdk/aws-elasticloadbalancingv2.FixedResponse#messageBody +@aws-cdk/aws-elasticloadbalancingv2.IApplicationListener#addCertificateArns +@aws-cdk/aws-elasticloadbalancingv2.INetworkListenerCertificateProps +@aws-cdk/aws-elasticloadbalancingv2.InstanceTarget +@aws-cdk/aws-elasticloadbalancingv2.InstanceTarget#attachToApplicationTargetGroup +@aws-cdk/aws-elasticloadbalancingv2.InstanceTarget#attachToNetworkTargetGroup +@aws-cdk/aws-elasticloadbalancingv2.IpTarget +@aws-cdk/aws-elasticloadbalancingv2.IpTarget#attachToApplicationTargetGroup +@aws-cdk/aws-elasticloadbalancingv2.IpTarget#attachToNetworkTargetGroup +@aws-cdk/aws-elasticloadbalancingv2.NetworkLoadBalancer#metricHealthyHostCount +@aws-cdk/aws-elasticloadbalancingv2.NetworkLoadBalancer#metricUnHealthyHostCount +@aws-cdk/aws-elasticloadbalancingv2.NetworkTargetGroup#import +@aws-cdk/aws-elasticloadbalancingv2.RedirectResponse +@aws-cdk/aws-elasticloadbalancingv2.RedirectResponse#statusCode +@aws-cdk/aws-elasticloadbalancingv2.RedirectResponse#host +@aws-cdk/aws-elasticloadbalancingv2.RedirectResponse#path +@aws-cdk/aws-elasticloadbalancingv2.RedirectResponse#port +@aws-cdk/aws-elasticloadbalancingv2.RedirectResponse#protocol +@aws-cdk/aws-elasticloadbalancingv2.RedirectResponse#query +@aws-cdk/aws-elasticloadbalancingv2.TargetGroupAttributes#defaultPort +@aws-cdk/aws-elasticloadbalancingv2.TargetGroupImportProps +@aws-cdk/aws-apigatewayv2.IHttpApi#httpApiId +@aws-cdk/aws-appmesh.Protocol +@aws-cdk/aws-appmesh.Protocol#HTTP +@aws-cdk/aws-appmesh.Protocol#TCP +@aws-cdk/aws-appmesh.Protocol#HTTP2 +@aws-cdk/aws-appmesh.Protocol#GRPC +@aws-cdk/aws-dynamodb.ITable#metricSystemErrors +@aws-cdk/aws-dynamodb.Table#grantListStreams +@aws-cdk/aws-dynamodb.Table#metricSystemErrors +@aws-cdk/aws-dynamodb.TableOptions#serverSideEncryption +@aws-cdk/aws-rds.Credentials#fromUsername +@aws-cdk/aws-rds.CredentialsFromUsernameOptions +@aws-cdk/aws-rds.CredentialsFromUsernameOptions#password +@aws-cdk/aws-rds.DatabaseInstanceEngine#MARIADB +@aws-cdk/aws-rds.DatabaseInstanceEngine#MYSQL +@aws-cdk/aws-rds.DatabaseInstanceEngine#ORACLE_EE +@aws-cdk/aws-rds.DatabaseInstanceEngine#ORACLE_SE +@aws-cdk/aws-rds.DatabaseInstanceEngine#ORACLE_SE1 +@aws-cdk/aws-rds.DatabaseInstanceEngine#ORACLE_SE2 +@aws-cdk/aws-rds.DatabaseInstanceEngine#POSTGRES +@aws-cdk/aws-rds.DatabaseInstanceEngine#SQL_SERVER_EE +@aws-cdk/aws-rds.DatabaseInstanceEngine#SQL_SERVER_EX +@aws-cdk/aws-rds.DatabaseInstanceEngine#SQL_SERVER_SE +@aws-cdk/aws-rds.DatabaseInstanceEngine#SQL_SERVER_WEB +@aws-cdk/aws-rds.DatabaseInstanceEngine#oracleSe +@aws-cdk/aws-rds.DatabaseInstanceEngine#oracleSe1 +@aws-cdk/aws-rds.DatabaseInstanceNewProps#vpcPlacement +@aws-cdk/aws-rds.MariaDbEngineVersion#VER_10_0 +@aws-cdk/aws-rds.MariaDbEngineVersion#VER_10_0_17 +@aws-cdk/aws-rds.MariaDbEngineVersion#VER_10_0_24 +@aws-cdk/aws-rds.MariaDbEngineVersion#VER_10_0_28 +@aws-cdk/aws-rds.MariaDbEngineVersion#VER_10_0_31 +@aws-cdk/aws-rds.MariaDbEngineVersion#VER_10_0_32 +@aws-cdk/aws-rds.MariaDbEngineVersion#VER_10_0_34 +@aws-cdk/aws-rds.MariaDbEngineVersion#VER_10_0_35 +@aws-cdk/aws-rds.MariaDbEngineVersion#VER_10_1 +@aws-cdk/aws-rds.MariaDbEngineVersion#VER_10_1_14 +@aws-cdk/aws-rds.MariaDbEngineVersion#VER_10_1_19 +@aws-cdk/aws-rds.MariaDbEngineVersion#VER_10_1_23 +@aws-cdk/aws-rds.MariaDbEngineVersion#VER_10_1_26 +@aws-cdk/aws-rds.MariaDbEngineVersion#VER_10_1_31 +@aws-cdk/aws-rds.MariaDbEngineVersion#VER_10_1_34 +@aws-cdk/aws-rds.MysqlEngineVersion#VER_5_5 +@aws-cdk/aws-rds.MysqlEngineVersion#VER_5_5_46 +@aws-cdk/aws-rds.MysqlEngineVersion#VER_5_5_53 +@aws-cdk/aws-rds.MysqlEngineVersion#VER_5_5_57 +@aws-cdk/aws-rds.MysqlEngineVersion#VER_5_5_59 +@aws-cdk/aws-rds.MysqlEngineVersion#VER_5_5_61 +@aws-cdk/aws-rds.MysqlEngineVersion#VER_5_6 +@aws-cdk/aws-rds.MysqlEngineVersion#VER_5_6_34 +@aws-cdk/aws-rds.MysqlEngineVersion#VER_5_6_35 +@aws-cdk/aws-rds.MysqlEngineVersion#VER_5_6_37 +@aws-cdk/aws-rds.MysqlEngineVersion#VER_5_6_39 +@aws-cdk/aws-rds.MysqlEngineVersion#VER_5_6_40 +@aws-cdk/aws-rds.MysqlEngineVersion#VER_5_6_41 +@aws-cdk/aws-rds.MysqlEngineVersion#VER_5_6_43 +@aws-cdk/aws-rds.MysqlEngineVersion#VER_5_6_44 +@aws-cdk/aws-rds.MysqlEngineVersion#VER_5_6_46 +@aws-cdk/aws-rds.MysqlEngineVersion#VER_5_6_48 +@aws-cdk/aws-rds.MysqlEngineVersion#VER_5_6_49 +@aws-cdk/aws-rds.MysqlEngineVersion#VER_5_6_51 +@aws-cdk/aws-rds.OracleLegacyEngineVersion +@aws-cdk/aws-rds.OracleLegacyEngineVersion#VER_11_2 +@aws-cdk/aws-rds.OracleLegacyEngineVersion#VER_11_2_0_2_V2 +@aws-cdk/aws-rds.OracleLegacyEngineVersion#VER_11_2_0_4_V1 +@aws-cdk/aws-rds.OracleLegacyEngineVersion#VER_11_2_0_4_V10 +@aws-cdk/aws-rds.OracleLegacyEngineVersion#VER_11_2_0_4_V11 +@aws-cdk/aws-rds.OracleLegacyEngineVersion#VER_11_2_0_4_V12 +@aws-cdk/aws-rds.OracleLegacyEngineVersion#VER_11_2_0_4_V13 +@aws-cdk/aws-rds.OracleLegacyEngineVersion#VER_11_2_0_4_V14 +@aws-cdk/aws-rds.OracleLegacyEngineVersion#VER_11_2_0_4_V15 +@aws-cdk/aws-rds.OracleLegacyEngineVersion#VER_11_2_0_4_V16 +@aws-cdk/aws-rds.OracleLegacyEngineVersion#VER_11_2_0_4_V17 +@aws-cdk/aws-rds.OracleLegacyEngineVersion#VER_11_2_0_4_V18 +@aws-cdk/aws-rds.OracleLegacyEngineVersion#VER_11_2_0_4_V19 +@aws-cdk/aws-rds.OracleLegacyEngineVersion#VER_11_2_0_4_V20 +@aws-cdk/aws-rds.OracleLegacyEngineVersion#VER_11_2_0_4_V21 +@aws-cdk/aws-rds.OracleLegacyEngineVersion#VER_11_2_0_4_V22 +@aws-cdk/aws-rds.OracleLegacyEngineVersion#VER_11_2_0_4_V23 +@aws-cdk/aws-rds.OracleLegacyEngineVersion#VER_11_2_0_4_V24 +@aws-cdk/aws-rds.OracleLegacyEngineVersion#VER_11_2_0_4_V25 +@aws-cdk/aws-rds.OracleLegacyEngineVersion#VER_11_2_0_4_V3 +@aws-cdk/aws-rds.OracleLegacyEngineVersion#VER_11_2_0_4_V4 +@aws-cdk/aws-rds.OracleLegacyEngineVersion#VER_11_2_0_4_V5 +@aws-cdk/aws-rds.OracleLegacyEngineVersion#VER_11_2_0_4_V6 +@aws-cdk/aws-rds.OracleLegacyEngineVersion#VER_11_2_0_4_V7 +@aws-cdk/aws-rds.OracleLegacyEngineVersion#VER_11_2_0_4_V8 +@aws-cdk/aws-rds.OracleLegacyEngineVersion#VER_11_2_0_4_V9 +@aws-cdk/aws-rds.OracleLegacyEngineVersion#oracleLegacyFullVersion +@aws-cdk/aws-rds.OracleLegacyEngineVersion#oracleLegacyMajorVersion +@aws-cdk/aws-rds.OracleSe1InstanceEngineProps +@aws-cdk/aws-rds.OracleSe1InstanceEngineProps#version +@aws-cdk/aws-rds.OracleSeInstanceEngineProps +@aws-cdk/aws-rds.OracleSeInstanceEngineProps#version +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_5 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_5_10 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_5_12 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_5_13 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_5_14 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_5_15 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_5_16 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_5_18 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_5_19 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_5_2 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_5_20 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_5_21 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_5_22 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_5_23 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_5_24 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_5_25 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_5_4 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_5_6 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_5_7 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_5_9 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_6 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_6_1 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_6_10 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_6_11 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_6_12 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_6_14 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_6_15 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_6_16 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_6_17 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_6_18 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_6_19 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_6_2 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_6_20 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_6_21 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_6_22 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_6_23 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_6_3 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_6_5 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_6_6 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_6_8 +@aws-cdk/aws-rds.PostgresEngineVersion#VER_9_6_9 +@aws-cdk/aws-rds.SnapshotCredentials#fromGeneratedPassword +@aws-cdk/aws-rds.SqlServerEngineVersion#VER_15_00_4043_23_V1 +@aws-cdk/aws-autoscaling.BlockDevice#mappingEnabled +@aws-cdk/aws-autoscaling.CommonAutoScalingGroupProps#notificationsTopic +@aws-cdk/aws-autoscaling.CommonAutoScalingGroupProps#replacingUpdateMinSuccessfulInstancesPercent +@aws-cdk/aws-autoscaling.CommonAutoScalingGroupProps#resourceSignalCount +@aws-cdk/aws-autoscaling.CommonAutoScalingGroupProps#resourceSignalTimeout +@aws-cdk/aws-autoscaling.CommonAutoScalingGroupProps#rollingUpdateConfiguration +@aws-cdk/aws-autoscaling.CommonAutoScalingGroupProps#updateType +@aws-cdk/aws-autoscaling.RequestCountScalingProps#targetRequestsPerSecond +@aws-cdk/aws-autoscaling.RollingUpdateConfiguration +@aws-cdk/aws-autoscaling.RollingUpdateConfiguration#maxBatchSize +@aws-cdk/aws-autoscaling.RollingUpdateConfiguration#minInstancesInService +@aws-cdk/aws-autoscaling.RollingUpdateConfiguration#minSuccessfulInstancesPercent +@aws-cdk/aws-autoscaling.RollingUpdateConfiguration#pauseTime +@aws-cdk/aws-autoscaling.RollingUpdateConfiguration#suspendProcesses +@aws-cdk/aws-autoscaling.RollingUpdateConfiguration#waitOnResourceSignals +@aws-cdk/aws-autoscaling.UpdateType +@aws-cdk/aws-autoscaling.UpdateType#NONE +@aws-cdk/aws-autoscaling.UpdateType#REPLACING_UPDATE +@aws-cdk/aws-autoscaling.UpdateType#ROLLING_UPDATE +@aws-cdk/aws-elasticloadbalancing.LoadBalancerListener#sslCertificateId +@aws-cdk/aws-ecs.AddAutoScalingGroupCapacityOptions#taskDrainTime +@aws-cdk/aws-ecs.BaseService#configureAwsVpcNetworking +@aws-cdk/aws-ecs.BaseServiceOptions#propagateTaskTagsFrom +@aws-cdk/aws-ecs.Cluster#addAutoScalingGroup +@aws-cdk/aws-ecs.Cluster#addCapacity +@aws-cdk/aws-ecs.Cluster#addCapacityProvider +@aws-cdk/aws-ecs.ClusterProps#capacityProviders +@aws-cdk/aws-ecs.Ec2ServiceProps#securityGroup +@aws-cdk/aws-ecs.EcsOptimizedAmi +@aws-cdk/aws-ecs.EcsOptimizedAmi#getImage +@aws-cdk/aws-ecs.EcsOptimizedAmiProps +@aws-cdk/aws-ecs.EcsOptimizedAmiProps#cachedInContext +@aws-cdk/aws-ecs.EcsOptimizedAmiProps#generation +@aws-cdk/aws-ecs.EcsOptimizedAmiProps#hardwareType +@aws-cdk/aws-ecs.EcsOptimizedAmiProps#windowsVersion +@aws-cdk/aws-ecs.FargateServiceProps#securityGroup +@aws-cdk/aws-ecs.SplunkLogDriverProps#token +@aws-cdk/aws-cloudfront.AliasConfiguration +@aws-cdk/aws-cloudfront.AliasConfiguration#acmCertRef +@aws-cdk/aws-cloudfront.AliasConfiguration#names +@aws-cdk/aws-cloudfront.AliasConfiguration#securityPolicy +@aws-cdk/aws-cloudfront.AliasConfiguration#sslMethod +@aws-cdk/aws-cloudfront.Behavior#trustedSigners +@aws-cdk/aws-cloudfront.CloudFrontWebDistribution#domainName +@aws-cdk/aws-cloudfront.CloudFrontWebDistributionProps#aliasConfiguration +@aws-cdk/aws-cloudfront.GeoRestriction#blacklist +@aws-cdk/aws-cloudfront.GeoRestriction#whitelist +@aws-cdk/aws-cloudfront.IDistribution#domainName +@aws-cdk/aws-cloudfront.SourceConfiguration#originHeaders +@aws-cdk/aws-cloudfront.SourceConfiguration#originPath +@aws-cdk/aws-cloudtrail.Trail#onCloudTrailEvent +@aws-cdk/aws-cloudtrail.TrailProps#kmsKey +@aws-cdk/aws-codepipeline-actions.BitBucketSourceAction +@aws-cdk/aws-codepipeline-actions.BitBucketSourceAction#actionProperties +@aws-cdk/aws-codepipeline-actions.BitBucketSourceAction#bind +@aws-cdk/aws-codepipeline-actions.BitBucketSourceAction#onStateChange +@aws-cdk/aws-codepipeline-actions.BitBucketSourceActionProps +@aws-cdk/aws-codepipeline-actions.CloudFormationCreateReplaceChangeSetActionProps#capabilities +@aws-cdk/aws-codepipeline-actions.CloudFormationCreateUpdateStackActionProps#capabilities +@aws-cdk/aws-codepipeline-actions.CloudFormationDeleteStackActionProps#capabilities +@aws-cdk/aws-events-targets.EcsTask#securityGroup +@aws-cdk/aws-events-targets.EcsTaskProps#securityGroup +@aws-cdk/aws-stepfunctions.Context +@aws-cdk/aws-stepfunctions.Context#entireContext +@aws-cdk/aws-stepfunctions.Context#taskToken +@aws-cdk/aws-stepfunctions.Context#numberAt +@aws-cdk/aws-stepfunctions.Context#stringAt +@aws-cdk/aws-stepfunctions.Data +@aws-cdk/aws-stepfunctions.Data#entirePayload +@aws-cdk/aws-stepfunctions.Data#isJsonPathString +@aws-cdk/aws-stepfunctions.Data#listAt +@aws-cdk/aws-stepfunctions.Data#numberAt +@aws-cdk/aws-stepfunctions.Data#stringAt +@aws-cdk/aws-stepfunctions.IStepFunctionsTask +@aws-cdk/aws-stepfunctions.IStepFunctionsTask#bind +@aws-cdk/aws-stepfunctions.StepFunctionsTaskConfig +@aws-cdk/aws-stepfunctions.StepFunctionsTaskConfig#resourceArn +@aws-cdk/aws-stepfunctions.StepFunctionsTaskConfig#heartbeat +@aws-cdk/aws-stepfunctions.StepFunctionsTaskConfig#metricDimensions +@aws-cdk/aws-stepfunctions.StepFunctionsTaskConfig#metricPrefixPlural +@aws-cdk/aws-stepfunctions.StepFunctionsTaskConfig#metricPrefixSingular +@aws-cdk/aws-stepfunctions.StepFunctionsTaskConfig#parameters +@aws-cdk/aws-stepfunctions.StepFunctionsTaskConfig#policyStatements +@aws-cdk/aws-stepfunctions.Task +@aws-cdk/aws-stepfunctions.Task#endStates +@aws-cdk/aws-stepfunctions.Task#addCatch +@aws-cdk/aws-stepfunctions.Task#addRetry +@aws-cdk/aws-stepfunctions.Task#metric +@aws-cdk/aws-stepfunctions.Task#metricFailed +@aws-cdk/aws-stepfunctions.Task#metricHeartbeatTimedOut +@aws-cdk/aws-stepfunctions.Task#metricRunTime +@aws-cdk/aws-stepfunctions.Task#metricScheduled +@aws-cdk/aws-stepfunctions.Task#metricScheduleTime +@aws-cdk/aws-stepfunctions.Task#metricStarted +@aws-cdk/aws-stepfunctions.Task#metricSucceeded +@aws-cdk/aws-stepfunctions.Task#metricTime +@aws-cdk/aws-stepfunctions.Task#metricTimedOut +@aws-cdk/aws-stepfunctions.Task#next +@aws-cdk/aws-stepfunctions.Task#toStateJson +@aws-cdk/aws-stepfunctions.Task#whenBoundToGraph +@aws-cdk/aws-stepfunctions.TaskInput#fromContextAt +@aws-cdk/aws-stepfunctions.TaskInput#fromDataAt +@aws-cdk/aws-stepfunctions.TaskProps +@aws-cdk/aws-stepfunctions.TaskProps#task +@aws-cdk/aws-stepfunctions.TaskProps#comment +@aws-cdk/aws-stepfunctions.TaskProps#inputPath +@aws-cdk/aws-stepfunctions.TaskProps#outputPath +@aws-cdk/aws-stepfunctions.TaskProps#parameters +@aws-cdk/aws-stepfunctions.TaskProps#resultPath +@aws-cdk/aws-stepfunctions.TaskProps#timeout +@aws-cdk/aws-ecs-patterns.ApplicationLoadBalancedServiceBase#desiredCount +@aws-cdk/aws-ecs-patterns.ApplicationMultipleTargetGroupsServiceBase#desiredCount +@aws-cdk/aws-ecs-patterns.NetworkLoadBalancedServiceBase#desiredCount +@aws-cdk/aws-ecs-patterns.NetworkMultipleTargetGroupsServiceBase#desiredCount +@aws-cdk/aws-ecs-patterns.QueueProcessingServiceBase#desiredCount +@aws-cdk/aws-ecs-patterns.QueueProcessingServiceBaseProps#desiredTaskCount +@aws-cdk/aws-eks.NodegroupOptions#instanceType +@aws-cdk/aws-eks.ServiceAccount#addToPolicy +@aws-cdk/aws-s3-deployment.Expires +@aws-cdk/aws-s3-deployment.Expires#value +@aws-cdk/aws-s3-deployment.Expires#after +@aws-cdk/aws-s3-deployment.Expires#atDate +@aws-cdk/aws-s3-deployment.Expires#atTimestamp +@aws-cdk/aws-s3-deployment.Expires#fromString +@aws-cdk/aws-ses.WhiteListReceiptFilter +@aws-cdk/aws-ses.WhiteListReceiptFilterProps +@aws-cdk/aws-stepfunctions-tasks.EcsRunTaskBase +@aws-cdk/aws-stepfunctions-tasks.EcsRunTaskBase#connections +@aws-cdk/aws-stepfunctions-tasks.EcsRunTaskBase#bind +@aws-cdk/aws-stepfunctions-tasks.EcsRunTaskBase#configureAwsVpcNetworking +@aws-cdk/aws-stepfunctions-tasks.EcsRunTaskBaseProps +@aws-cdk/aws-stepfunctions-tasks.EcsRunTaskBaseProps#parameters +@aws-cdk/aws-stepfunctions-tasks.InvocationType +@aws-cdk/aws-stepfunctions-tasks.InvocationType#REQUEST_RESPONSE +@aws-cdk/aws-stepfunctions-tasks.InvocationType#EVENT +@aws-cdk/aws-stepfunctions-tasks.InvocationType#DRY_RUN +@aws-cdk/aws-stepfunctions-tasks.InvokeActivity +@aws-cdk/aws-stepfunctions-tasks.InvokeActivity#bind +@aws-cdk/aws-stepfunctions-tasks.InvokeActivityProps +@aws-cdk/aws-stepfunctions-tasks.InvokeActivityProps#heartbeat +@aws-cdk/aws-stepfunctions-tasks.InvokeFunction +@aws-cdk/aws-stepfunctions-tasks.InvokeFunction#bind +@aws-cdk/aws-stepfunctions-tasks.InvokeFunctionProps +@aws-cdk/aws-stepfunctions-tasks.InvokeFunctionProps#payload +@aws-cdk/aws-stepfunctions-tasks.PublishToTopic +@aws-cdk/aws-stepfunctions-tasks.PublishToTopic#bind +@aws-cdk/aws-stepfunctions-tasks.PublishToTopicProps +@aws-cdk/aws-stepfunctions-tasks.PublishToTopicProps#message +@aws-cdk/aws-stepfunctions-tasks.PublishToTopicProps#integrationPattern +@aws-cdk/aws-stepfunctions-tasks.PublishToTopicProps#messagePerSubscriptionType +@aws-cdk/aws-stepfunctions-tasks.PublishToTopicProps#subject +@aws-cdk/aws-stepfunctions-tasks.RunBatchJob +@aws-cdk/aws-stepfunctions-tasks.RunBatchJob#bind +@aws-cdk/aws-stepfunctions-tasks.RunBatchJobProps +@aws-cdk/aws-stepfunctions-tasks.RunBatchJobProps#jobDefinitionArn +@aws-cdk/aws-stepfunctions-tasks.RunBatchJobProps#jobName +@aws-cdk/aws-stepfunctions-tasks.RunBatchJobProps#jobQueueArn +@aws-cdk/aws-stepfunctions-tasks.RunBatchJobProps#arraySize +@aws-cdk/aws-stepfunctions-tasks.RunBatchJobProps#attempts +@aws-cdk/aws-stepfunctions-tasks.RunBatchJobProps#containerOverrides +@aws-cdk/aws-stepfunctions-tasks.RunBatchJobProps#dependsOn +@aws-cdk/aws-stepfunctions-tasks.RunBatchJobProps#integrationPattern +@aws-cdk/aws-stepfunctions-tasks.RunBatchJobProps#payload +@aws-cdk/aws-stepfunctions-tasks.RunBatchJobProps#timeout +@aws-cdk/aws-stepfunctions-tasks.RunEcsEc2Task +@aws-cdk/aws-stepfunctions-tasks.RunEcsEc2TaskProps +@aws-cdk/aws-stepfunctions-tasks.RunEcsEc2TaskProps#placementConstraints +@aws-cdk/aws-stepfunctions-tasks.RunEcsEc2TaskProps#placementStrategies +@aws-cdk/aws-stepfunctions-tasks.RunEcsEc2TaskProps#securityGroup +@aws-cdk/aws-stepfunctions-tasks.RunEcsEc2TaskProps#subnets +@aws-cdk/aws-stepfunctions-tasks.RunEcsFargateTask +@aws-cdk/aws-stepfunctions-tasks.RunEcsFargateTaskProps +@aws-cdk/aws-stepfunctions-tasks.RunEcsFargateTaskProps#assignPublicIp +@aws-cdk/aws-stepfunctions-tasks.RunEcsFargateTaskProps#platformVersion +@aws-cdk/aws-stepfunctions-tasks.RunEcsFargateTaskProps#securityGroup +@aws-cdk/aws-stepfunctions-tasks.RunEcsFargateTaskProps#subnets +@aws-cdk/aws-stepfunctions-tasks.RunGlueJobTask +@aws-cdk/aws-stepfunctions-tasks.RunGlueJobTask#bind +@aws-cdk/aws-stepfunctions-tasks.RunGlueJobTaskProps +@aws-cdk/aws-stepfunctions-tasks.RunGlueJobTaskProps#arguments +@aws-cdk/aws-stepfunctions-tasks.RunGlueJobTaskProps#integrationPattern +@aws-cdk/aws-stepfunctions-tasks.RunGlueJobTaskProps#notifyDelayAfter +@aws-cdk/aws-stepfunctions-tasks.RunGlueJobTaskProps#securityConfiguration +@aws-cdk/aws-stepfunctions-tasks.RunGlueJobTaskProps#timeout +@aws-cdk/aws-stepfunctions-tasks.RunLambdaTask +@aws-cdk/aws-stepfunctions-tasks.RunLambdaTask#bind +@aws-cdk/aws-stepfunctions-tasks.RunLambdaTaskProps +@aws-cdk/aws-stepfunctions-tasks.RunLambdaTaskProps#clientContext +@aws-cdk/aws-stepfunctions-tasks.RunLambdaTaskProps#integrationPattern +@aws-cdk/aws-stepfunctions-tasks.RunLambdaTaskProps#invocationType +@aws-cdk/aws-stepfunctions-tasks.RunLambdaTaskProps#payload +@aws-cdk/aws-stepfunctions-tasks.RunLambdaTaskProps#qualifier +@aws-cdk/aws-stepfunctions-tasks.SendToQueue +@aws-cdk/aws-stepfunctions-tasks.SendToQueue#bind +@aws-cdk/aws-stepfunctions-tasks.SendToQueueProps +@aws-cdk/aws-stepfunctions-tasks.SendToQueueProps#messageBody +@aws-cdk/aws-stepfunctions-tasks.SendToQueueProps#delay +@aws-cdk/aws-stepfunctions-tasks.SendToQueueProps#integrationPattern +@aws-cdk/aws-stepfunctions-tasks.SendToQueueProps#messageDeduplicationId +@aws-cdk/aws-stepfunctions-tasks.SendToQueueProps#messageGroupId +@aws-cdk/aws-stepfunctions-tasks.StartExecution +@aws-cdk/aws-stepfunctions-tasks.StartExecution#bind +@aws-cdk/aws-stepfunctions-tasks.StartExecutionProps +@aws-cdk/aws-stepfunctions-tasks.StartExecutionProps#input +@aws-cdk/aws-stepfunctions-tasks.StartExecutionProps#integrationPattern +@aws-cdk/aws-stepfunctions-tasks.StartExecutionProps#name +@aws-cdk/pipelines.AddManualApprovalOptions +@aws-cdk/pipelines.AddManualApprovalOptions#actionName +@aws-cdk/pipelines.AddManualApprovalOptions#runOrder +@aws-cdk/pipelines.AddStackOptions +@aws-cdk/pipelines.AddStackOptions#executeRunOrder +@aws-cdk/pipelines.AddStackOptions#runOrder +@aws-cdk/pipelines.AddStageOptions +@aws-cdk/pipelines.AddStageOptions#extraRunOrderSpace +@aws-cdk/pipelines.AddStageOptions#manualApprovals +@aws-cdk/pipelines.AdditionalArtifact +@aws-cdk/pipelines.AdditionalArtifact#artifact +@aws-cdk/pipelines.AdditionalArtifact#directory +@aws-cdk/pipelines.AssetPublishingCommand +@aws-cdk/pipelines.AssetPublishingCommand#assetId +@aws-cdk/pipelines.AssetPublishingCommand#assetManifestPath +@aws-cdk/pipelines.AssetPublishingCommand#assetPublishingRoleArn +@aws-cdk/pipelines.AssetPublishingCommand#assetSelector +@aws-cdk/pipelines.AssetPublishingCommand#assetType +@aws-cdk/pipelines.BaseStageOptions +@aws-cdk/pipelines.BaseStageOptions#confirmBroadeningPermissions +@aws-cdk/pipelines.BaseStageOptions#securityNotificationTopic +@aws-cdk/pipelines.CdkPipeline +@aws-cdk/pipelines.CdkPipeline#codePipeline +@aws-cdk/pipelines.CdkPipeline#addApplicationStage +@aws-cdk/pipelines.CdkPipeline#addStage +@aws-cdk/pipelines.CdkPipeline#stackOutput +@aws-cdk/pipelines.CdkPipeline#stage +@aws-cdk/pipelines.CdkPipeline#validate +@aws-cdk/pipelines.CdkPipelineProps +@aws-cdk/pipelines.CdkPipelineProps#cloudAssemblyArtifact +@aws-cdk/pipelines.CdkPipelineProps#assetBuildSpec +@aws-cdk/pipelines.CdkPipelineProps#assetPreInstallCommands +@aws-cdk/pipelines.CdkPipelineProps#cdkCliVersion +@aws-cdk/pipelines.CdkPipelineProps#codePipeline +@aws-cdk/pipelines.CdkPipelineProps#crossAccountKeys +@aws-cdk/pipelines.CdkPipelineProps#dockerCredentials +@aws-cdk/pipelines.CdkPipelineProps#enableKeyRotation +@aws-cdk/pipelines.CdkPipelineProps#pipelineName +@aws-cdk/pipelines.CdkPipelineProps#selfMutating +@aws-cdk/pipelines.CdkPipelineProps#selfMutationBuildSpec +@aws-cdk/pipelines.CdkPipelineProps#singlePublisherPerType +@aws-cdk/pipelines.CdkPipelineProps#sourceAction +@aws-cdk/pipelines.CdkPipelineProps#subnetSelection +@aws-cdk/pipelines.CdkPipelineProps#supportDockerAssets +@aws-cdk/pipelines.CdkPipelineProps#synthAction +@aws-cdk/pipelines.CdkPipelineProps#vpc +@aws-cdk/pipelines.CdkStackActionFromArtifactOptions +@aws-cdk/pipelines.CdkStackActionFromArtifactOptions#stackName +@aws-cdk/pipelines.CdkStage +@aws-cdk/pipelines.CdkStage#addActions +@aws-cdk/pipelines.CdkStage#addApplication +@aws-cdk/pipelines.CdkStage#addManualApprovalAction +@aws-cdk/pipelines.CdkStage#addStackArtifactDeployment +@aws-cdk/pipelines.CdkStage#deploysStack +@aws-cdk/pipelines.CdkStage#nextSequentialRunOrder +@aws-cdk/pipelines.CdkStageProps +@aws-cdk/pipelines.CdkStageProps#cloudAssemblyArtifact +@aws-cdk/pipelines.CdkStageProps#host +@aws-cdk/pipelines.CdkStageProps#pipelineStage +@aws-cdk/pipelines.CdkStageProps#stageName +@aws-cdk/pipelines.CdkStageProps#confirmBroadeningPermissions +@aws-cdk/pipelines.CdkStageProps#securityNotificationTopic +@aws-cdk/pipelines.DeployCdkStackAction +@aws-cdk/pipelines.DeployCdkStackAction#actionProperties +@aws-cdk/pipelines.DeployCdkStackAction#dependencyStackArtifactIds +@aws-cdk/pipelines.DeployCdkStackAction#executeRunOrder +@aws-cdk/pipelines.DeployCdkStackAction#prepareRunOrder +@aws-cdk/pipelines.DeployCdkStackAction#stackName +@aws-cdk/pipelines.DeployCdkStackAction#stackArtifactId +@aws-cdk/pipelines.DeployCdkStackAction#fromStackArtifact +@aws-cdk/pipelines.DeployCdkStackAction#bind +@aws-cdk/pipelines.DeployCdkStackAction#onStateChange +@aws-cdk/pipelines.DeployCdkStackActionOptions +@aws-cdk/pipelines.DeployCdkStackActionOptions#cloudAssemblyInput +@aws-cdk/pipelines.DeployCdkStackActionOptions#baseActionName +@aws-cdk/pipelines.DeployCdkStackActionOptions#changeSetName +@aws-cdk/pipelines.DeployCdkStackActionOptions#executeRunOrder +@aws-cdk/pipelines.DeployCdkStackActionOptions#output +@aws-cdk/pipelines.DeployCdkStackActionOptions#outputFileName +@aws-cdk/pipelines.DeployCdkStackActionOptions#prepareRunOrder +@aws-cdk/pipelines.DeployCdkStackActionProps +@aws-cdk/pipelines.DeployCdkStackActionProps#actionRole +@aws-cdk/pipelines.DeployCdkStackActionProps#stackName +@aws-cdk/pipelines.DeployCdkStackActionProps#templatePath +@aws-cdk/pipelines.DeployCdkStackActionProps#cloudFormationExecutionRole +@aws-cdk/pipelines.DeployCdkStackActionProps#dependencyStackArtifactIds +@aws-cdk/pipelines.DeployCdkStackActionProps#region +@aws-cdk/pipelines.DeployCdkStackActionProps#stackArtifactId +@aws-cdk/pipelines.DeployCdkStackActionProps#templateConfigurationPath +@aws-cdk/pipelines.FromStackArtifactOptions +@aws-cdk/pipelines.FromStackArtifactOptions#cloudAssemblyInput +@aws-cdk/pipelines.FromStackArtifactOptions#executeRunOrder +@aws-cdk/pipelines.FromStackArtifactOptions#output +@aws-cdk/pipelines.FromStackArtifactOptions#outputFileName +@aws-cdk/pipelines.FromStackArtifactOptions#prepareRunOrder +@aws-cdk/pipelines.IStageHost +@aws-cdk/pipelines.IStageHost#publishAsset +@aws-cdk/pipelines.IStageHost#stackOutputArtifact +@aws-cdk/pipelines.PublishAssetsAction +@aws-cdk/pipelines.PublishAssetsAction#actionProperties +@aws-cdk/pipelines.PublishAssetsAction#addPublishCommand +@aws-cdk/pipelines.PublishAssetsAction#bind +@aws-cdk/pipelines.PublishAssetsAction#onStateChange +@aws-cdk/pipelines.PublishAssetsActionProps +@aws-cdk/pipelines.PublishAssetsActionProps#actionName +@aws-cdk/pipelines.PublishAssetsActionProps#assetType +@aws-cdk/pipelines.PublishAssetsActionProps#cloudAssemblyInput +@aws-cdk/pipelines.PublishAssetsActionProps#buildSpec +@aws-cdk/pipelines.PublishAssetsActionProps#cdkCliVersion +@aws-cdk/pipelines.PublishAssetsActionProps#createBuildspecFile +@aws-cdk/pipelines.PublishAssetsActionProps#dependable +@aws-cdk/pipelines.PublishAssetsActionProps#preInstallCommands +@aws-cdk/pipelines.PublishAssetsActionProps#projectName +@aws-cdk/pipelines.PublishAssetsActionProps#role +@aws-cdk/pipelines.PublishAssetsActionProps#subnetSelection +@aws-cdk/pipelines.PublishAssetsActionProps#vpc +@aws-cdk/pipelines.ShellScriptAction +@aws-cdk/pipelines.ShellScriptAction#actionProperties +@aws-cdk/pipelines.ShellScriptAction#grantPrincipal +@aws-cdk/pipelines.ShellScriptAction#project +@aws-cdk/pipelines.ShellScriptAction#bind +@aws-cdk/pipelines.ShellScriptAction#onStateChange +@aws-cdk/pipelines.ShellScriptActionProps +@aws-cdk/pipelines.ShellScriptActionProps#actionName +@aws-cdk/pipelines.ShellScriptActionProps#commands +@aws-cdk/pipelines.ShellScriptActionProps#additionalArtifacts +@aws-cdk/pipelines.ShellScriptActionProps#bashOptions +@aws-cdk/pipelines.ShellScriptActionProps#environment +@aws-cdk/pipelines.ShellScriptActionProps#environmentVariables +@aws-cdk/pipelines.ShellScriptActionProps#rolePolicyStatements +@aws-cdk/pipelines.ShellScriptActionProps#runOrder +@aws-cdk/pipelines.ShellScriptActionProps#securityGroups +@aws-cdk/pipelines.ShellScriptActionProps#subnetSelection +@aws-cdk/pipelines.ShellScriptActionProps#useOutputs +@aws-cdk/pipelines.ShellScriptActionProps#vpc +@aws-cdk/pipelines.SimpleSynthAction +@aws-cdk/pipelines.SimpleSynthAction#actionProperties +@aws-cdk/pipelines.SimpleSynthAction#grantPrincipal +@aws-cdk/pipelines.SimpleSynthAction#project +@aws-cdk/pipelines.SimpleSynthAction#standardNpmSynth +@aws-cdk/pipelines.SimpleSynthAction#standardYarnSynth +@aws-cdk/pipelines.SimpleSynthAction#bind +@aws-cdk/pipelines.SimpleSynthAction#onStateChange +@aws-cdk/pipelines.SimpleSynthActionProps +@aws-cdk/pipelines.SimpleSynthActionProps#synthCommand +@aws-cdk/pipelines.SimpleSynthActionProps#buildCommand +@aws-cdk/pipelines.SimpleSynthActionProps#buildCommands +@aws-cdk/pipelines.SimpleSynthActionProps#installCommand +@aws-cdk/pipelines.SimpleSynthActionProps#installCommands +@aws-cdk/pipelines.SimpleSynthActionProps#testCommands +@aws-cdk/pipelines.SimpleSynthOptions +@aws-cdk/pipelines.SimpleSynthOptions#cloudAssemblyArtifact +@aws-cdk/pipelines.SimpleSynthOptions#sourceArtifact +@aws-cdk/pipelines.SimpleSynthOptions#actionName +@aws-cdk/pipelines.SimpleSynthOptions#additionalArtifacts +@aws-cdk/pipelines.SimpleSynthOptions#buildSpec +@aws-cdk/pipelines.SimpleSynthOptions#copyEnvironmentVariables +@aws-cdk/pipelines.SimpleSynthOptions#environment +@aws-cdk/pipelines.SimpleSynthOptions#environmentVariables +@aws-cdk/pipelines.SimpleSynthOptions#projectName +@aws-cdk/pipelines.SimpleSynthOptions#rolePolicyStatements +@aws-cdk/pipelines.SimpleSynthOptions#subdirectory +@aws-cdk/pipelines.SimpleSynthOptions#subnetSelection +@aws-cdk/pipelines.SimpleSynthOptions#vpc +@aws-cdk/pipelines.StackOutput +@aws-cdk/pipelines.StackOutput#artifactFile +@aws-cdk/pipelines.StackOutput#outputName +@aws-cdk/pipelines.StandardNpmSynthOptions +@aws-cdk/pipelines.StandardNpmSynthOptions#buildCommand +@aws-cdk/pipelines.StandardNpmSynthOptions#installCommand +@aws-cdk/pipelines.StandardNpmSynthOptions#synthCommand +@aws-cdk/pipelines.StandardNpmSynthOptions#testCommands +@aws-cdk/pipelines.StandardYarnSynthOptions +@aws-cdk/pipelines.StandardYarnSynthOptions#buildCommand +@aws-cdk/pipelines.StandardYarnSynthOptions#installCommand +@aws-cdk/pipelines.StandardYarnSynthOptions#synthCommand +@aws-cdk/pipelines.StandardYarnSynthOptions#testCommands +@aws-cdk/pipelines.UpdatePipelineAction +@aws-cdk/pipelines.UpdatePipelineAction#actionProperties +@aws-cdk/pipelines.UpdatePipelineAction#bind +@aws-cdk/pipelines.UpdatePipelineAction#onStateChange +@aws-cdk/pipelines.UpdatePipelineActionProps +@aws-cdk/pipelines.UpdatePipelineActionProps#cloudAssemblyInput +@aws-cdk/pipelines.UpdatePipelineActionProps#pipelineStackHierarchicalId +@aws-cdk/pipelines.UpdatePipelineActionProps#buildSpec +@aws-cdk/pipelines.UpdatePipelineActionProps#cdkCliVersion +@aws-cdk/pipelines.UpdatePipelineActionProps#dockerCredentials +@aws-cdk/pipelines.UpdatePipelineActionProps#pipelineStackName +@aws-cdk/pipelines.UpdatePipelineActionProps#privileged +@aws-cdk/pipelines.UpdatePipelineActionProps#projectName diff --git a/scripts/list-deprecated-apis.js b/scripts/list-deprecated-apis.js index 284022b4825e1..a4596ebdf1a69 100755 --- a/scripts/list-deprecated-apis.js +++ b/scripts/list-deprecated-apis.js @@ -3,51 +3,78 @@ const path = require('path'); const jsiiReflect = require('jsii-reflect'); -async function main() { +class MarkdownPrinter { + printHeader() { + process.stdout.write(`# List of deprecated APIs in v1\n`); + process.stdout.write('\n'); + process.stdout.write(`| Module | API Element | Message |\n`); + process.stdout.write(`|--------|-------------|---------|\n`); + } + + printIfDeprecated(mod, name, el) { + try { + if (el.docs.deprecated) { + // Add zero-width spaces after . and _ to allow for line breaking long identifiers + // (WindowsVersion.WINDOWS_SERVER_2012_RTM_CHINESE_TRADITIONAL_HONG_KONG_SAR_64BIT_BASE is a fun one...) + // For consistency with the original format, replace the '#' separators with '.' + const apiName = name.replace('#', '.').replace(/(\.|_)/g, '$1\u200B'); + + // Some deprecation reasons start with '- ' for misguided reasons. Get rid of it, and also get rid of newlines. + const reason = el.docs.deprecationReason.replace(/^-/, '').replace(/\n/g, ' ').trim(); + + process.stdout.write(`| ${mod} | ${apiName} | ${reason} |\n`); + } + } catch (e) { + console.error(`While processing ${mod}.${name}:`, e); + } + } +} + +/** For use as input to the --strip-deprecated argument in jsii */ +class StripDeprecatedPrinter { + printHeader() { } + + printIfDeprecated(mod, name, el) { + try { + if (el.docs.deprecated) { + // Remove the method parens + process.stdout.write(`${mod}.${name.replace(/\(\)$/, '')}\n`); + } + } catch (e) { + console.error(`While processing ${mod}.${name}:`, e); + } + } +} + +async function main(printer) { const typesystem = new jsiiReflect.TypeSystem(); // Decdk depends on everything, so that's a perfect directory to load as closure await typesystem.loadNpmDependencies(path.resolve(__dirname, '..', 'packages', 'decdk'), { validate: false }); - process.stdout.write(`# List of deprecated APIs in v1\n`); - process.stdout.write('\n'); - process.stdout.write(`| Module | API Element | Message |\n`); - process.stdout.write(`|--------|-------------|---------|\n`); + printer.printHeader(); for (const assembly of typesystem.assemblies) { for (const type of assembly.types) { - printIfDeprecated(assembly.fqn, type.name, type); + printer.printIfDeprecated(assembly.fqn, type.name, type); if (type.isEnumType()) { - type.members.forEach(e => printIfDeprecated(assembly.fqn, `${type.name}.${e.name}`, e)); + type.members.forEach(e => printer.printIfDeprecated(assembly.fqn, `${type.name}#${e.name}`, e)); } if (type.isInterfaceType() || type.isClassType() || type.isDataType()) { - type.ownProperties.forEach(p => printIfDeprecated(assembly.fqn, `${type.name}.${p.name}`, p)); + type.ownProperties.forEach(p => printer.printIfDeprecated(assembly.fqn, `${type.name}#${p.name}`, p)); type.ownMethods.forEach(method => { - printIfDeprecated(assembly.fqn, `${type.name}.${method.name}()`, method); - method.parameters.forEach(p => printIfDeprecated(assembly.fqn, `${type.name}.${method.name}(): ${p.name}`, p)); + printer.printIfDeprecated(assembly.fqn, `${type.name}#${method.name}()`, method); + method.parameters.forEach(p => printer.printIfDeprecated(assembly.fqn, `${type.name}#${method.name}(): ${p.name}`, p)); }); } } } } -function printIfDeprecated(mod, name, el) { - try { - if (el.docs.deprecated) { - // Add zero-width spaces after . and _ to allow for line breaking long identifiers - // (WindowsVersion.WINDOWS_SERVER_2012_RTM_CHINESE_TRADITIONAL_HONG_KONG_SAR_64BIT_BASE is a fun one...) - const apiName = name.replace(/(\.|_)/g, '$1\u200B'); - - // Some deprecation reasons start with '- ' for misguided reasons. Get rid of it, and also get rid of newlines. - const reason = el.docs.deprecationReason.replace(/^-/, '').replace(/\n/g, ' ').trim(); - - process.stdout.write(`| ${mod} | ${apiName} | ${reason} |\n`); - } - } catch (e) { - console.error(`While processing ${mod}.${name}:`, e); - } -} +const printer = (process.argv.length > 2 && process.argv[2] === '--plain') + ? new StripDeprecatedPrinter() + : new MarkdownPrinter(); -main().catch(e => console.error(e)); +main(printer).catch(e => console.error(e)); From 7640130b9f033ea950941ef8de46343869e523f5 Mon Sep 17 00:00:00 2001 From: Niranjan Jayakar Date: Wed, 27 Oct 2021 13:42:20 +0100 Subject: [PATCH 51/87] chore(assertions): minor documentation tweaks (#17138) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/@aws-cdk/assertions/README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/@aws-cdk/assertions/README.md b/packages/@aws-cdk/assertions/README.md index 47a27cbbd2513..3c97f387d8398 100644 --- a/packages/@aws-cdk/assertions/README.md +++ b/packages/@aws-cdk/assertions/README.md @@ -45,9 +45,11 @@ template. ```ts const expected = { Resources: { - Type: 'Foo::Bar', - Properties: { - Baz: 'Qux', + BarLogicalId: { + Type: 'Foo::Bar', + Properties: { + Baz: 'Qux', + }, }, }, }; @@ -62,7 +64,7 @@ to change this. Snapshot testing is a common technique to store a snapshot of the output and compare it during future changes. Since CloudFormation templates are human readable, -they are a good target for รฅรŸsnapshot testing. +they are a good target for snapshot testing. The `toJSON()` method on the `Template` can be used to produce a well formatted JSON of the CloudFormation template that can be used as a snapshot. From ca02187cba79e04d84b097bfb6838ac746a1a065 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Wed, 27 Oct 2021 15:36:00 +0200 Subject: [PATCH 52/87] chore(events): make examples compile (#17157) ---- *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-events/README.md | 45 +++++++++++++------ .../aws-events/rosetta/basic.ts-fixture | 12 +++++ .../aws-events/rosetta/default.ts-fixture | 20 +++++++++ 3 files changed, 64 insertions(+), 13 deletions(-) create mode 100644 packages/@aws-cdk/aws-events/rosetta/basic.ts-fixture create mode 100644 packages/@aws-cdk/aws-events/rosetta/default.ts-fixture diff --git a/packages/@aws-cdk/aws-events/README.md b/packages/@aws-cdk/aws-events/README.md index 0288407ee094f..13bd483ca54cb 100644 --- a/packages/@aws-cdk/aws-events/README.md +++ b/packages/@aws-cdk/aws-events/README.md @@ -59,6 +59,9 @@ For example, to define an rule that triggers a CodeBuild project build when a commit is pushed to the "master" branch of a CodeCommit repository: ```ts +declare const repo: codecommit.Repository; +declare const project: codebuild.Project; + const onCommitRule = repo.onCommit('OnCommit', { target: new targets.CodeBuildProject(project), branches: ['master'] @@ -73,6 +76,9 @@ topic target which formats a human-readable message for the commit. For example, this adds an SNS topic as a target: ```ts +declare const onCommitRule: events.Rule; +declare const topic: sns.Topic; + onCommitRule.addTarget(new targets.SnsTopic(topic, { message: events.RuleTargetInput.fromText( `A commit was pushed to the repository ${codecommit.ReferenceEvent.repositoryName} on branch ${codecommit.ReferenceEvent.referenceName}` @@ -83,6 +89,9 @@ onCommitRule.addTarget(new targets.SnsTopic(topic, { Or using an Object: ```ts +declare const onCommitRule: events.Rule; +declare const topic: sns.Topic; + onCommitRule.addTarget(new targets.SnsTopic(topic, { message: events.RuleTargetInput.fromObject( { @@ -99,10 +108,15 @@ Rate must be specified in minutes, hours or days. The following example runs a task every day at 4am: -```ts +```ts fixture=basic import { Rule, Schedule } from '@aws-cdk/aws-events'; import { EcsTask } from '@aws-cdk/aws-events-targets'; -... +import { Cluster, TaskDefinition } from '@aws-cdk/aws-ecs'; +import { Role } from '@aws-cdk/aws-iam'; + +declare const cluster: Cluster; +declare const taskDefinition: TaskDefinition; +declare const role: Role; const ecsTaskTarget = new EcsTask({ cluster, taskDefinition, role }); @@ -115,8 +129,12 @@ new Rule(this, 'ScheduleRule', { If you want to specify Fargate platform version, set `platformVersion` in EcsTask's props like the following example: ```ts +declare const cluster: ecs.Cluster; +declare const taskDefinition: ecs.TaskDefinition; +declare const role: iam.Role; + const platformVersion = ecs.FargatePlatformVersion.VERSION1_4; -const ecsTaskTarget = new EcsTask({ cluster, taskDefinition, role, platformVersion }); +const ecsTaskTarget = new targets.EcsTask({ cluster, taskDefinition, role, platformVersion }); ``` ## Event Targets @@ -140,7 +158,7 @@ The following targets are supported: It's possible to have the source of the event and a target in separate AWS accounts and regions: -```ts +```ts nofixture import { App, Stack } from '@aws-cdk/core'; import * as codebuild from '@aws-cdk/aws-codebuild'; import * as codecommit from '@aws-cdk/aws-codecommit'; @@ -148,9 +166,12 @@ import * as targets from '@aws-cdk/aws-events-targets'; const app = new App(); +const account1 = '11111111111'; +const account2 = '22222222222'; + const stack1 = new Stack(app, 'Stack1', { env: { account: account1, region: 'us-west-1' } }); const repo = new codecommit.Repository(stack1, 'Repository', { - // ... + repositoryName: 'myrepository', }); const stack2 = new Stack(app, 'Stack2', { env: { account: account2, region: 'us-east-1' } }); @@ -179,11 +200,7 @@ For more information, see the It is possible to archive all or some events sent to an event bus. It is then possible to [replay these events](https://aws.amazon.com/blogs/aws/new-archive-and-replay-events-with-amazon-eventbridge/). ```ts -import * as cdk from '@aws-cdk/core'; - -const stack = new stack(); - -const bus = new EventBus(stack, 'bus', { +const bus = new events.EventBus(this, 'bus', { eventBusName: 'MyCustomEventBus' }); @@ -191,9 +208,9 @@ bus.archive('MyArchive', { archiveName: 'MyCustomEventBusArchive', description: 'MyCustomerEventBus Archive', eventPattern: { - account: [stack.account], + account: [Stack.of(this).account], }, - retention: cdk.Duration.days(365), + retention: Duration.days(365), }); ``` @@ -205,7 +222,9 @@ or `EventBus.fromEventBusName` factory method. Then, you can use the `grantPutEventsTo` method to grant `event:PutEvents` to the eventBus. ```ts -const eventBus = EventBus.fromEventBusArn(this, 'ImportedEventBus', 'arn:aws:events:us-east-1:111111111:event-bus/my-event-bus'); +declare const lambdaFunction: lambda.Function; + +const eventBus = events.EventBus.fromEventBusArn(this, 'ImportedEventBus', 'arn:aws:events:us-east-1:111111111:event-bus/my-event-bus'); // now you can just call methods on the eventbus eventBus.grantPutEventsTo(lambdaFunction); diff --git a/packages/@aws-cdk/aws-events/rosetta/basic.ts-fixture b/packages/@aws-cdk/aws-events/rosetta/basic.ts-fixture new file mode 100644 index 0000000000000..0cc6d1104d521 --- /dev/null +++ b/packages/@aws-cdk/aws-events/rosetta/basic.ts-fixture @@ -0,0 +1,12 @@ +// Fixture with packages imported, but nothing else +import { Construct } from 'constructs'; +import { Stack, Duration } from '@aws-cdk/core'; + +class Fixture extends Stack { + constructor(scope: Construct, id: string) { + super(scope, id); + + /// here + } +} + diff --git a/packages/@aws-cdk/aws-events/rosetta/default.ts-fixture b/packages/@aws-cdk/aws-events/rosetta/default.ts-fixture new file mode 100644 index 0000000000000..7cb7c6f81aec6 --- /dev/null +++ b/packages/@aws-cdk/aws-events/rosetta/default.ts-fixture @@ -0,0 +1,20 @@ +// Fixture with packages imported, but nothing else +import { Construct } from 'constructs'; +import { Stack, Duration } from '@aws-cdk/core'; +import * as events from '@aws-cdk/aws-events'; +import * as targets from '@aws-cdk/aws-events-targets'; +import * as codecommit from '@aws-cdk/aws-codecommit'; +import * as codebuild from '@aws-cdk/aws-codebuild'; +import * as sns from '@aws-cdk/aws-sns'; +import * as ecs from '@aws-cdk/aws-ecs'; +import * as iam from '@aws-cdk/aws-iam'; +import * as lambda from '@aws-cdk/aws-lambda'; + +class Fixture extends Stack { + constructor(scope: Construct, id: string) { + super(scope, id); + + /// here + } +} + From 80369ff69e34a457cd7b27caf71d243d6579c727 Mon Sep 17 00:00:00 2001 From: kaizen3031593 <36202692+kaizen3031593@users.noreply.github.com> Date: Wed, 27 Oct 2021 10:27:07 -0400 Subject: [PATCH 53/87] docs(logs): make examples compile (#17168) ---- *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-logs/README.md | 54 ++++++++++--------- .../aws-logs/rosetta/default.ts-fixture | 15 ++++++ 2 files changed, 44 insertions(+), 25 deletions(-) create mode 100644 packages/@aws-cdk/aws-logs/rosetta/default.ts-fixture diff --git a/packages/@aws-cdk/aws-logs/README.md b/packages/@aws-cdk/aws-logs/README.md index 497526ca6ec60..1fcd323ca621c 100644 --- a/packages/@aws-cdk/aws-logs/README.md +++ b/packages/@aws-cdk/aws-logs/README.md @@ -61,7 +61,7 @@ Here's a simple example of creating an encrypted Log Group using a KMS CMK. ```ts import * as kms from '@aws-cdk/aws-kms'; -new LogGroup(this, 'LogGroup', { +new logs.LogGroup(this, 'LogGroup', { encryptionKey: new kms.Key(this, 'Key'), }); ``` @@ -83,13 +83,14 @@ Create a `SubscriptionFilter`, initialize it with an appropriate `Pattern` (see below) and supply the intended destination: ```ts -const fn = new lambda.Function(this, 'Lambda', { ... }); -const logGroup = new LogGroup(this, 'LogGroup', { ... }); +import * as destinations from '@aws-cdk/aws-logs-destinations'; +declare const fn: lambda.Function; +declare const logGroup: logs.LogGroup; -new SubscriptionFilter(this, 'Subscription', { - logGroup, - destination: new LogsDestinations.LambdaDestination(fn), - filterPattern: FilterPattern.allTerms("ERROR", "MainThread") +new logs.SubscriptionFilter(this, 'Subscription', { + logGroup, + destination: new destinations.LambdaDestination(fn), + filterPattern: logs.FilterPattern.allTerms("ERROR", "MainThread"), }); ``` @@ -114,6 +115,7 @@ A very simple MetricFilter can be created by using the `logGroup.extractMetric() helper function: ```ts +declare const logGroup: logs.LogGroup; logGroup.extractMetric('$.jsonField', 'Namespace', 'MetricName'); ``` @@ -127,11 +129,12 @@ You can expose a metric on a metric filter by calling the `MetricFilter.metric() This has a default of `statistic = 'avg'` if the statistic is not set in the `props`. ```ts -const mf = new MetricFilter(this, 'MetricFilter', { +declare const logGroup: logs.LogGroup; +const mf = new logs.MetricFilter(this, 'MetricFilter', { logGroup, metricNamespace: 'MyApp', metricName: 'Latency', - filterPattern: FilterPattern.exists('$.latency'), + filterPattern: logs.FilterPattern.exists('$.latency'), metricValue: '$.latency', }); @@ -139,7 +142,7 @@ const mf = new MetricFilter(this, 'MetricFilter', { const metric = mf.metric(); //you can use the metric to create a new alarm -new Alarm(this, 'alarm from metric filter', { +new cloudwatch.Alarm(this, 'alarm from metric filter', { metric, threshold: 100, evaluationPeriods: 2, @@ -175,7 +178,7 @@ line. (substrings) appear in the log event. * `FilterPattern.anyTerm(term, term, ...)`: matches if all of the given terms (substrings) appear in the log event. -* `FilterPattern.anyGroup([term, term, ...], [term, term, ...], ...)`: matches if +* `FilterPattern.anyTermGroup([term, term, ...], [term, term, ...], ...)`: matches if all of the terms in any of the groups (specified as arrays) matches. This is an OR match. @@ -184,14 +187,14 @@ Examples: ```ts // Search for lines that contain both "ERROR" and "MainThread" -const pattern1 = FilterPattern.allTerms('ERROR', 'MainThread'); +const pattern1 = logs.FilterPattern.allTerms('ERROR', 'MainThread'); // Search for lines that either contain both "ERROR" and "MainThread", or // both "WARN" and "Deadlock". -const pattern2 = FilterPattern.anyGroup( - ['ERROR', 'MainThread'], - ['WARN', 'Deadlock'], - ); +const pattern2 = logs.FilterPattern.anyTermGroup( + ['ERROR', 'MainThread'], + ['WARN', 'Deadlock'], +); ``` ## JSON Patterns @@ -235,12 +238,13 @@ Example: // Search for all events where the component field is equal to // "HttpServer" and either error is true or the latency is higher // than 1000. -const pattern = FilterPattern.all( - FilterPattern.stringValue('$.component', '=', 'HttpServer'), - FilterPattern.any( - FilterPattern.booleanValue('$.error', true), - FilterPattern.numberValue('$.latency', '>', 1000) - )); +const pattern = logs.FilterPattern.all( + logs.FilterPattern.stringValue('$.component', '=', 'HttpServer'), + logs.FilterPattern.any( + logs.FilterPattern.booleanValue('$.error', true), + logs.FilterPattern.numberValue('$.latency', '>', 1000), + ), +); ``` ## Space-delimited table patterns @@ -274,9 +278,9 @@ Example: ```ts // Search for all events where the component is "HttpServer" and the // result code is not equal to 200. -const pattern = FilterPattern.spaceDelimited('time', 'component', '...', 'result_code', 'latency') - .whereString('component', '=', 'HttpServer') - .whereNumber('result_code', '!=', 200); +const pattern = logs.FilterPattern.spaceDelimited('time', 'component', '...', 'result_code', 'latency') + .whereString('component', '=', 'HttpServer') + .whereNumber('result_code', '!=', 200); ``` ## Notes diff --git a/packages/@aws-cdk/aws-logs/rosetta/default.ts-fixture b/packages/@aws-cdk/aws-logs/rosetta/default.ts-fixture new file mode 100644 index 0000000000000..27c338ce30a32 --- /dev/null +++ b/packages/@aws-cdk/aws-logs/rosetta/default.ts-fixture @@ -0,0 +1,15 @@ +// Fixture with packages imported, but nothing else +import { Construct } from 'constructs'; +import { Stack } from '@aws-cdk/core'; +import * as logs from '@aws-cdk/aws-logs'; +import * as cloudwatch from '@aws-cdk/aws-cloudwatch'; +import * as lambda from '@aws-cdk/aws-lambda'; + +class Fixture extends Stack { + constructor(scope: Construct, id: string) { + super(scope, id); + + /// here + } +} + From 312c2b614a73ea3176564a1de43a15f0992972d6 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Wed, 27 Oct 2021 17:19:55 +0200 Subject: [PATCH 54/87] docs: note that `App`s `outdir` property should not be used (#16670) If this property is passed it has to agree with the CLI's `--output` flag. If this property is not passed, it will default to the CLI's `--output` flag. In either case, it's better to just use `--output` and not pass this property at all; the property only has value inside tests. I tried to add validation (by using `Annotations.of(app).addWarning()` but they are useless anyway: in the CX protocol, metadata can only be attached to `StackArtifacts`, so metadata attached to the `App` will not be rendered. Adding a full framework feature to move metadata to a different place feels like too much risk and work for this small note, so turned it into a documentation fix. Fixes #3717. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/@aws-cdk/core/lib/app.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/@aws-cdk/core/lib/app.ts b/packages/@aws-cdk/core/lib/app.ts index 6719995d2b837..09ad1a3f81b79 100644 --- a/packages/@aws-cdk/core/lib/app.ts +++ b/packages/@aws-cdk/core/lib/app.ts @@ -25,6 +25,12 @@ export interface AppProps { /** * The output directory into which to emit synthesized artifacts. * + * You should never need to set this value. By default, the value you pass to + * the CLI's `--output` flag will be used, and if you change it to a different + * directory the CLI will fail to pick up the generated Cloud Assembly. + * + * This property is intended for internal and testing use. + * * @default - If this value is _not_ set, considers the environment variable `CDK_OUTDIR`. * If `CDK_OUTDIR` is not defined, uses a temp directory. */ From deccdebc43b4ff79c53ffa5a4171ef5a78f944c4 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Wed, 27 Oct 2021 18:12:33 +0200 Subject: [PATCH 55/87] chore(ec2): make examples (mostly) compile (#17183) There is one error left, jsii-rosetta doesn't support array indexing yet (`array[5]`). That's easy enough to add, so we're going to add that to Rosetta. ---- *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-ec2/README.md | 245 ++++++++++++------ .../@aws-cdk/aws-ec2/lib/security-group.ts | 2 +- packages/@aws-cdk/aws-ec2/lib/user-data.ts | 6 +- packages/@aws-cdk/aws-ec2/lib/volume.ts | 5 +- packages/@aws-cdk/aws-ec2/lib/vpc-endpoint.ts | 2 + .../aws-ec2/rosetta/client-vpn.ts-fixture | 2 +- .../@aws-cdk/aws-ec2/rosetta/conns.ts-fixture | 26 -- .../aws-ec2/rosetta/default.ts-fixture | 8 +- 8 files changed, 177 insertions(+), 119 deletions(-) delete mode 100644 packages/@aws-cdk/aws-ec2/rosetta/conns.ts-fixture diff --git a/packages/@aws-cdk/aws-ec2/README.md b/packages/@aws-cdk/aws-ec2/README.md index f450e29dfcf20..ca30cc28fe9bd 100644 --- a/packages/@aws-cdk/aws-ec2/README.md +++ b/packages/@aws-cdk/aws-ec2/README.md @@ -93,17 +93,21 @@ must specify the environment where the stack will be deployed. You can gain full control over the availability zones selection strategy by overriding the Stack's [`get availabilityZones()`](https://github.com/aws/aws-cdk/blob/master/packages/@aws-cdk/core/lib/stack.ts) method: -```ts +```text +// This example is only available in TypeScript + class MyStack extends Stack { + constructor(scope: Construct, id: string, props?: StackProps) { + super(scope, id, props); + + // ... + } + get availabilityZones(): string[] { return ['us-west-2a', 'us-west-2b']; } - constructor(scope: Construct, id: string, props?: StackProps) { - super(scope, id, props); - ... - } } ``` @@ -121,11 +125,13 @@ The example below will place the endpoint into two AZs (`us-east-1a` and `us-eas in Isolated subnets: ```ts -new InterfaceVpcEndpoint(stack, 'VPC Endpoint', { +declare const vpc: ec2.Vpc; + +new ec2.InterfaceVpcEndpoint(this, 'VPC Endpoint', { vpc, - service: new InterfaceVpcEndpointService('com.amazonaws.vpce.us-east-1.vpce-svc-uuddlrlrbastrtsvc', 443), + service: new ec2.InterfaceVpcEndpointService('com.amazonaws.vpce.us-east-1.vpce-svc-uuddlrlrbastrtsvc', 443), subnets: { - subnetType: SubnetType.ISOLATED, + subnetType: ec2.SubnetType.ISOLATED, availabilityZones: ['us-east-1a', 'us-east-1c'] } }); @@ -134,9 +140,13 @@ new InterfaceVpcEndpoint(stack, 'VPC Endpoint', { You can also specify specific subnet objects for granular control: ```ts -new InterfaceVpcEndpoint(stack, 'VPC Endpoint', { +declare const vpc: ec2.Vpc; +declare const subnet1: ec2.Subnet; +declare const subnet2: ec2.Subnet; + +new ec2.InterfaceVpcEndpoint(this, 'VPC Endpoint', { vpc, - service: new InterfaceVpcEndpointService('com.amazonaws.vpce.us-east-1.vpce-svc-uuddlrlrbastrtsvc', 443), + service: new ec2.InterfaceVpcEndpointService('com.amazonaws.vpce.us-east-1.vpce-svc-uuddlrlrbastrtsvc', 443), subnets: { subnets: [subnet1, subnet2] } @@ -193,14 +203,16 @@ gets routed, pass `allowAllTraffic: false` and access the `NatInstanceProvider.connections` member after having passed it to the VPC: ```ts -const provider = NatProvider.instance({ - instanceType: /* ... */, +declare const instanceType: ec2.InstanceType; + +const provider = ec2.NatProvider.instance({ + instanceType, allowAllTraffic: false, }); -new Vpc(stack, 'TheVPC', { +new ec2.Vpc(this, 'TheVPC', { natGatewayProvider: provider, }); -provider.connections.allowFrom(Peer.ipv4('1.2.3.4/8'), Port.tcp(80)); +provider.connections.allowFrom(ec2.Peer.ipv4('1.2.3.4/8'), ec2.Port.tcp(80)); ``` ### Advanced Subnet Configuration @@ -284,6 +296,8 @@ DatabaseSubnet3 |`ISOLATED`|`10.0.6.32/28`|#3|Only routes within the VPC If you need access to the internet gateway, you can get its ID like so: ```ts +declare const vpc: ec2.Vpc; + const igwId = vpc.internetGatewayId; ``` @@ -305,18 +319,19 @@ Internet Gateway created for the public subnet - perhaps for routing a VPN connection - you can do so like this: ```ts -const vpc = ec2.Vpc(this, "VPC", { +const vpc = new ec2.Vpc(this, "VPC", { subnetConfiguration: [{ - subnetType: SubnetType.PUBLIC, + subnetType: ec2.SubnetType.PUBLIC, name: 'Public', },{ - subnetType: SubnetType.ISOLATED, + subnetType: ec2.SubnetType.ISOLATED, name: 'Isolated', }] -}) -(vpc.isolatedSubnets[0] as Subnet).addRoute("StaticRoute", { - routerId: vpc.internetGatewayId, - routerType: RouterType.GATEWAY, +}); + +(vpc.isolatedSubnets[0] as ec2.Subnet).addRoute("StaticRoute", { + routerId: vpc.internetGatewayId!, + routerType: ec2.RouterType.GATEWAY, destinationCidrBlock: "8.8.8.8/32", }) ``` @@ -412,7 +427,7 @@ following limitations: Using `Vpc.fromVpcAttributes()` looks like this: ```ts -const vpc = ec2.Vpc.fromVpcAttributes(stack, 'VPC', { +const vpc = ec2.Vpc.fromVpcAttributes(this, 'VPC', { vpcId: 'vpc-1234', availabilityZones: ['us-east-1a', 'us-east-1b'], @@ -423,7 +438,7 @@ const vpc = ec2.Vpc.fromVpcAttributes(stack, 'VPC', { privateSubnetIds: Fn.importListValue('PrivateSubnetIds', 2), // OR: split an imported string to a list of known length - isolatedSubnetIds: Fn.split(',', ssm.StringParameter.valueForStringParameter(stack, `MyParameter`), 2), + isolatedSubnetIds: Fn.split(',', ssm.StringParameter.valueForStringParameter(this, `MyParameter`), 2), }); ``` @@ -457,7 +472,11 @@ have security groups, you have to add an **Egress** rule to one Security Group, and an **Ingress** rule to the other. The connections object will automatically take care of this for you: -```ts fixture=conns +```ts +declare const loadBalancer: elbv2.ApplicationLoadBalancer; +declare const appFleet: autoscaling.AutoScalingGroup; +declare const dbFleet: autoscaling.AutoScalingGroup; + // Allow connections from anywhere loadBalancer.connections.allowFromAnyIpv4(ec2.Port.tcp(443), 'Allow inbound HTTPS'); @@ -472,7 +491,10 @@ appFleet.connections.allowTo(dbFleet, ec2.Port.tcp(443), 'App can call database' There are various classes that implement the connection peer part: -```ts fixture=conns +```ts +declare const appFleet: autoscaling.AutoScalingGroup; +declare const dbFleet: autoscaling.AutoScalingGroup; + // Simple connection peers let peer = ec2.Peer.ipv4('10.0.0.0/16'); peer = ec2.Peer.anyIpv4(); @@ -484,7 +506,11 @@ appFleet.connections.allowTo(peer, ec2.Port.tcp(443), 'Allow outbound HTTPS'); Any object that has a security group can itself be used as a connection peer: -```ts fixture=conns +```ts +declare const fleet1: autoscaling.AutoScalingGroup; +declare const fleet2: autoscaling.AutoScalingGroup; +declare const appFleet: autoscaling.AutoScalingGroup; + // These automatically create appropriate ingress and egress rules in both security groups fleet1.connections.allowTo(fleet2, ec2.Port.tcp(80), 'Allow between fleets'); @@ -518,7 +544,11 @@ If the object you're calling the peering method on has a default port associated For example: -```ts fixture=conns +```ts +declare const listener: elbv2.ApplicationListener; +declare const appFleet: autoscaling.AutoScalingGroup; +declare const rdsDatabase: rds.DatabaseCluster; + // Port implicit in listener listener.connections.allowDefaultPortFromAnyIpv4('Allow public'); @@ -637,9 +667,11 @@ By default, CDK will place a VPC endpoint in one subnet per AZ. If you wish to o use the `subnets` parameter as follows: ```ts -new InterfaceVpcEndpoint(stack, 'VPC Endpoint', { +declare const vpc: ec2.Vpc; + +new ec2.InterfaceVpcEndpoint(this, 'VPC Endpoint', { vpc, - service: new InterfaceVpcEndpointService('com.amazonaws.vpce.us-east-1.vpce-svc-uuddlrlrbastrtsvc', 443), + service: new ec2.InterfaceVpcEndpointService('com.amazonaws.vpce.us-east-1.vpce-svc-uuddlrlrbastrtsvc', 443), // Choose which availability zones to place the VPC endpoint in, based on // available AZs subnets: { @@ -654,9 +686,11 @@ AZs an endpoint service is available in, and will ensure the VPC endpoint is not These AZs will be stored in cdk.context.json. ```ts -new InterfaceVpcEndpoint(stack, 'VPC Endpoint', { +declare const vpc: ec2.Vpc; + +new ec2.InterfaceVpcEndpoint(this, 'VPC Endpoint', { vpc, - service: new InterfaceVpcEndpointService('com.amazonaws.vpce.us-east-1.vpce-svc-uuddlrlrbastrtsvc', 443), + service: new ec2.InterfaceVpcEndpointService('com.amazonaws.vpce.us-east-1.vpce-svc-uuddlrlrbastrtsvc', 443), // Choose which availability zones to place the VPC endpoint in, based on // available AZs lookupSupportedAzs: true @@ -668,7 +702,12 @@ create VPC endpoints without having to configure name, ports, etc. For example, use in your VPC: ``` ts -new InterfaceVpcEndpoint(stack, 'VPC Endpoint', { vpc, service: InterfaceVpcEndpointAwsService.KEYSPACES }); +declare const vpc: ec2.Vpc; + +new ec2.InterfaceVpcEndpoint(this, 'VPC Endpoint', { + vpc, + service: ec2.InterfaceVpcEndpointAwsService.KEYSPACES, +}); ``` #### Security groups for interface VPC endpoints @@ -678,7 +717,9 @@ automatically allowed from the VPC CIDR. Use the `connections` object to allow traffic to flow to the endpoint: -```ts fixture=conns +```ts +declare const myEndpoint: ec2.InterfaceVpcEndpoint; + myEndpoint.connections.allowDefaultPortFromAnyIpv4(); ``` @@ -689,10 +730,13 @@ Alternatively, existing security groups can be used by specifying the `securityG A VPC endpoint service enables you to expose a Network Load Balancer(s) as a provider service to consumers, who connect to your service over a VPC endpoint. You can restrict access to your service via allowed principals (anything that extends ArnPrincipal), and require that new connections be manually accepted. ```ts -new VpcEndpointService(this, 'EndpointService', { +declare const networkLoadBalancer1: elbv2.NetworkLoadBalancer; +declare const networkLoadBalancer2: elbv2.NetworkLoadBalancer; + +new ec2.VpcEndpointService(this, 'EndpointService', { vpcEndpointServiceLoadBalancers: [networkLoadBalancer1, networkLoadBalancer2], acceptanceRequired: true, - allowedPrincipals: [new ArnPrincipal('arn:aws:iam::123456789012:root')] + allowedPrincipals: [new iam.ArnPrincipal('arn:aws:iam::123456789012:root')] }); ``` @@ -700,9 +744,11 @@ Endpoint services support private DNS, which makes it easier for clients to conn You can enable private DNS on an endpoint service like so: ```ts -import { VpcEndpointServiceDomainName } from '@aws-cdk/aws-route53'; +import { HostedZone, VpcEndpointServiceDomainName } from '@aws-cdk/aws-route53'; +declare const zone: HostedZone; +declare const vpces: ec2.VpcEndpointService; -new VpcEndpointServiceDomainName(stack, 'EndpointDomain', { +new VpcEndpointServiceDomainName(this, 'EndpointDomain', { endpointService: vpces, domainName: 'my-stuff.aws-cdk.dev', publicHostedZone: zone, @@ -796,7 +842,15 @@ For the full set of capabilities of this system, see the documentation for Here is an example of applying some configuration to an instance: ```ts +declare const vpc: ec2.Vpc; +declare const instanceType: ec2.InstanceType; +declare const machineImage: ec2.IMachineImage; + new ec2.Instance(this, 'Instance', { + vpc, + instanceType, + machineImage, + // Showing the most complex setup, if you have simpler requirements // you can use `CloudFormationInit.fromElements()`. init: ec2.CloudFormationInit.fromConfigSets({ @@ -812,9 +866,9 @@ new ec2.Instance(this, 'Instance', { config: new ec2.InitConfig([ // Create a JSON file from tokens (can also create other files) ec2.InitFile.fromObject('/etc/stack.json', { - stackId: stack.stackId, - stackName: stack.stackName, - region: stack.region, + stackId: Stack.of(this).stackId, + stackName: Stack.of(this).stackName, + region: Stack.of(this).region, }), // Create a group and user @@ -834,10 +888,10 @@ new ec2.Instance(this, 'Instance', { timeout: Duration.minutes(30), // Optional, whether to include the --url argument when running cfn-init and cfn-signal commands (false by default) - includeUrl: true + includeUrl: true, // Optional, whether to include the --role argument when running cfn-init and cfn-signal commands (false by default) - includeRole: true + includeRole: true, }, }); ``` @@ -849,11 +903,13 @@ config writes a config file for nginx, extracts an archive to the root directory restarts nginx so that it picks up the new config and files: ```ts +declare const myBucket: s3.Bucket; + const handle = new ec2.InitServiceRestartHandle(); ec2.CloudFormationInit.fromElements( ec2.InitFile.fromString('/etc/nginx/nginx.conf', '...', { serviceRestartHandles: [handle] }), - ec2.InitSource.fromBucket('/var/www/html', myBucket, 'html.zip', { serviceRestartHandles: [handle] }), + ec2.InitSource.fromS3Object('/var/www/html', myBucket, 'html.zip', { serviceRestartHandles: [handle] }), ec2.InitService.enable('nginx', { serviceRestartHandle: handle, }) @@ -887,16 +943,16 @@ with the command `aws ec2-instance-connect send-ssh-public-key` to provide your EBS volume for the bastion host can be encrypted like: -```ts - const host = new ec2.BastionHostLinux(stack, 'BastionHost', { - vpc, - blockDevices: [{ - deviceName: 'EBSBastionHost', - volume: BlockDeviceVolume.ebs(10, { - encrypted: true, - }), - }], - }); +```ts fixture=with-vpc +const host = new ec2.BastionHostLinux(this, 'BastionHost', { + vpc, + blockDevices: [{ + deviceName: 'EBSBastionHost', + volume: ec2.BlockDeviceVolume.ebs(10, { + encrypted: true, + }), + }], +}); ``` ### Block Devices @@ -906,8 +962,17 @@ root device (`/dev/sda1`) size to 50 GiB, and adds another EBS-backed device map size: ```ts +declare const vpc: ec2.Vpc; +declare const instanceType: ec2.InstanceType; +declare const machineImage: ec2.IMachineImage; + new ec2.Instance(this, 'Instance', { + vpc, + instanceType, + machineImage, + // ... + blockDevices: [ { deviceName: '/dev/sda1', @@ -931,15 +996,12 @@ A notable restriction is that a Volume can only be attached to instances in the The following demonstrates how to create a 500 GiB encrypted Volume in the `us-west-2a` availability zone, and give a role the ability to attach that Volume to a specific instance: ```ts -const instance = new ec2.Instance(this, 'Instance', { - // ... -}); -const role = new iam.Role(stack, 'SomeRole', { - assumedBy: new iam.AccountRootPrincipal(), -}); +declare const instance: ec2.Instance; +declare const role: iam.Role; + const volume = new ec2.Volume(this, 'Volume', { availabilityZone: 'us-west-2a', - size: cdk.Size.gibibytes(500), + size: Size.gibibytes(500), encrypted: true, }); @@ -952,12 +1014,8 @@ If you need to grant an instance the ability to attach/detach an EBS volume to/f will lead to an unresolvable circular reference between the instance role and the instance. In this case, use `grantAttachVolumeByResourceTag` and `grantDetachVolumeByResourceTag` as follows: ```ts -const instance = new ec2.Instance(this, 'Instance', { - // ... -}); -const volume = new ec2.Volume(this, 'Volume', { - // ... -}); +declare const instance: ec2.Instance; +declare const volume: ec2.Volume; const attachGrant = volume.grantAttachVolumeByResourceTag(instance.grantPrincipal, [instance]); const detachGrant = volume.grantDetachVolumeByResourceTag(instance.grantPrincipal, [instance]); @@ -973,12 +1031,9 @@ to attach and detach your Volumes to/from instances, and how to format them for The following is a sample skeleton of EC2 UserData that can be used to attach a Volume to the Linux instance that it is running on: ```ts -const volume = new ec2.Volume(this, 'Volume', { - // ... -}); -const instance = new ec2.Instance(this, 'Instance', { - // ... -}); +declare const instance: ec2.Instance; +declare const volume: ec2.Volume; + volume.grantAttachVolumeByResourceTag(instance.grantPrincipal, [instance]); const targetDevice = '/dev/xvdz'; instance.userData.addCommands( @@ -1005,9 +1060,18 @@ To do this for a single `Instance`, you can use the `requireImdsv2` property. The example below demonstrates IMDSv2 being required on a single `Instance`: ```ts +declare const vpc: ec2.Vpc; +declare const instanceType: ec2.InstanceType; +declare const machineImage: ec2.IMachineImage; + new ec2.Instance(this, 'Instance', { - requireImdsv2: true, + vpc, + instanceType, + machineImage, + // ... + + requireImdsv2: true, }); ``` @@ -1018,7 +1082,7 @@ The following example demonstrates how to use the `InstanceRequireImdsv2Aspect` ```ts const aspect = new ec2.InstanceRequireImdsv2Aspect(); -Aspects.of(stack).add(aspect); +Aspects.of(this).add(aspect); ``` ## VPC Flow Logs @@ -1030,6 +1094,8 @@ By default a flow log will be created with CloudWatch Logs as the destination. You can create a flow log like this: ```ts +declare const vpc: ec2.Vpc; + new ec2.FlowLog(this, 'FlowLog', { resourceType: ec2.FlowLogResourceType.fromVpc(vpc) }) @@ -1066,6 +1132,8 @@ If you want to customize any of the destination resources you can provide your o *CloudWatch Logs* ```ts +declare const vpc: ec2.Vpc; + const logGroup = new logs.LogGroup(this, 'MyCustomLogGroup'); const role = new iam.Role(this, 'MyCustomRole', { @@ -1081,6 +1149,7 @@ new ec2.FlowLog(this, 'FlowLog', { *S3* ```ts +declare const vpc: ec2.Vpc; const bucket = new s3.Bucket(this, 'MyCustomBucket'); @@ -1103,10 +1172,14 @@ User data enables you to run a script when your instances start up. In order to A user data could be configured to run a script found in an asset through the following: ```ts -const asset = new Asset(this, 'Asset', {path: path.join(__dirname, 'configure.sh')}); -const instance = new ec2.Instance(this, 'Instance', { - // ... - }); +import { Asset } from '@aws-cdk/aws-s3-assets'; + +declare const instance: ec2.Instance; + +const asset = new Asset(this, 'Asset', { + path: './configure.sh' +}); + const localPath = instance.userData.addS3DownloadCommand({ bucket:asset.bucket, bucketKey:asset.s3ObjectKey, @@ -1116,7 +1189,7 @@ instance.userData.addExecuteFileCommand({ filePath:localPath, arguments: '--verbose -y' }); -asset.grantRead( instance.role ); +asset.grantRead(instance.role); ``` ### Multipart user data @@ -1152,7 +1225,7 @@ multipartUserData.addPart(ec2.MultipartBody.fromUserData(bootHookConf, 'text/clo // Execute the rest of setup multipartUserData.addPart(ec2.MultipartBody.fromUserData(setupCommands)); -new ec2.LaunchTemplate(stack, '', { +new ec2.LaunchTemplate(this, '', { userData: multipartUserData, blockDevices: [ // Block device configuration rest @@ -1172,7 +1245,7 @@ method on `MultipartUserData` with the `makeDefault` argument set to `true`: ```ts const multipartUserData = new ec2.MultipartUserData(); const commandsUserData = ec2.UserData.forLinux(); -multipartUserData.addUserDataPart(commandsUserData, MultipartBody.SHELL_SCRIPT, true); +multipartUserData.addUserDataPart(commandsUserData, ec2.MultipartBody.SHELL_SCRIPT, true); // Adding commands to the multipartUserData adds them to commandsUserData, and vice-versa. multipartUserData.addCommands('touch /root/multi.txt'); @@ -1193,14 +1266,14 @@ Importing an existing subnet looks like this: ```ts // Supply all properties -const subnet = Subnet.fromSubnetAttributes(this, 'SubnetFromAttributes', { +const subnet1 = ec2.Subnet.fromSubnetAttributes(this, 'SubnetFromAttributes', { subnetId: 's-1234', availabilityZone: 'pub-az-4465', routeTableId: 'rt-145' }); // Supply only subnet id -const subnet = Subnet.fromSubnetId(this, 'SubnetFromId', 's-1234'); +const subnet2 = ec2.Subnet.fromSubnetId(this, 'SubnetFromId', 's-1234'); ``` ## Launch Templates @@ -1214,10 +1287,10 @@ an instance. For information on Launch Templates please see the The following demonstrates how to create a launch template with an Amazon Machine Image, and security group. ```ts -const vpc = new ec2.Vpc(...); -// ... +declare const vpc: ec2.Vpc; + const template = new ec2.LaunchTemplate(this, 'LaunchTemplate', { - machineImage: new ec2.AmazonMachineImage(), + machineImage: ec2.MachineImage.latestAmazonLinux(), securityGroup: new ec2.SecurityGroup(this, 'LaunchTemplateSG', { vpc: vpc, }), diff --git a/packages/@aws-cdk/aws-ec2/lib/security-group.ts b/packages/@aws-cdk/aws-ec2/lib/security-group.ts index 2c01da7aef943..54695f2d17b71 100644 --- a/packages/@aws-cdk/aws-ec2/lib/security-group.ts +++ b/packages/@aws-cdk/aws-ec2/lib/security-group.ts @@ -308,7 +308,7 @@ export interface SecurityGroupImportOptions { * you would import it like this: * * ```ts - * const securityGroup = SecurityGroup.fromSecurityGroupId(this, 'SG', 'sg-12345', { + * const securityGroup = ec2.SecurityGroup.fromSecurityGroupId(this, 'SG', 'sg-12345', { * mutable: false * }); * ``` diff --git a/packages/@aws-cdk/aws-ec2/lib/user-data.ts b/packages/@aws-cdk/aws-ec2/lib/user-data.ts index 14b94d2d2ad4a..1e92eb888e6f8 100644 --- a/packages/@aws-cdk/aws-ec2/lib/user-data.ts +++ b/packages/@aws-cdk/aws-ec2/lib/user-data.ts @@ -489,7 +489,11 @@ export class MultipartUserData extends UserData { * If `makeDefault` is false, then this is the same as calling: * * ```ts - * multiPart.addPart(MultipartBody.fromUserData(userData, contentType)); + * declare const multiPart: ec2.MultipartUserData; + * declare const userData: ec2.UserData; + * declare const contentType: string; + * + * multiPart.addPart(ec2.MultipartBody.fromUserData(userData, contentType)); * ``` * * An undefined `makeDefault` defaults to either: diff --git a/packages/@aws-cdk/aws-ec2/lib/volume.ts b/packages/@aws-cdk/aws-ec2/lib/volume.ts index a25ca459b7c63..87e92b3f5006a 100644 --- a/packages/@aws-cdk/aws-ec2/lib/volume.ts +++ b/packages/@aws-cdk/aws-ec2/lib/volume.ts @@ -19,7 +19,7 @@ export interface BlockDevice { /** * The device name exposed to the EC2 instance * - * @example '/dev/sdh', 'xvdh' + * For example, a value like `/dev/sdh`, `xvdh`. * * @see https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/device_naming.html */ @@ -28,8 +28,7 @@ export interface BlockDevice { /** * Defines the block device volume, to be either an Amazon EBS volume or an ephemeral instance store volume * - * @example BlockDeviceVolume.ebs(15), BlockDeviceVolume.ephemeral(0) - * + * For example, a value like `BlockDeviceVolume.ebs(15)`, `BlockDeviceVolume.ephemeral(0)`. */ readonly volume: BlockDeviceVolume; diff --git a/packages/@aws-cdk/aws-ec2/lib/vpc-endpoint.ts b/packages/@aws-cdk/aws-ec2/lib/vpc-endpoint.ts index de64072868391..3282da410d09a 100644 --- a/packages/@aws-cdk/aws-ec2/lib/vpc-endpoint.ts +++ b/packages/@aws-cdk/aws-ec2/lib/vpc-endpoint.ts @@ -121,6 +121,8 @@ export interface GatewayVpcEndpointOptions { * @default - All subnets in the VPC * @example * + * declare const vpc: ec2.Vpc; + * * vpc.addGatewayEndpoint('DynamoDbEndpoint', { * service: ec2.GatewayVpcEndpointAwsService.DYNAMODB, * // Add only to ISOLATED subnets diff --git a/packages/@aws-cdk/aws-ec2/rosetta/client-vpn.ts-fixture b/packages/@aws-cdk/aws-ec2/rosetta/client-vpn.ts-fixture index 4886d590211df..34c83a31ced35 100644 --- a/packages/@aws-cdk/aws-ec2/rosetta/client-vpn.ts-fixture +++ b/packages/@aws-cdk/aws-ec2/rosetta/client-vpn.ts-fixture @@ -9,7 +9,7 @@ class Fixture extends Stack { const vpc = new ec2.Vpc(this, 'VPC'); const samlProvider = new iam.SamlProvider(this, 'Provider', { - metadataDocument: SamlMetadataDocument.fromXml('xml'), + metadataDocument: iam.SamlMetadataDocument.fromXml('xml'), }) /// here diff --git a/packages/@aws-cdk/aws-ec2/rosetta/conns.ts-fixture b/packages/@aws-cdk/aws-ec2/rosetta/conns.ts-fixture deleted file mode 100644 index f29d9a1816a6e..0000000000000 --- a/packages/@aws-cdk/aws-ec2/rosetta/conns.ts-fixture +++ /dev/null @@ -1,26 +0,0 @@ -// Fixture with fake connectables -import { Construct, Stack } from '@aws-cdk/core'; -import ec2 = require('@aws-cdk/aws-ec2'); - -class Fixture extends Stack { - constructor(scope: Construct, id: string) { - super(scope, id); - - const vpc = new ec2.Vpc(this, 'VPC'); - - const loadBalancer = new FakeConnectable(); - const appFleet = new FakeConnectable(); - const dbFleet = new FakeConnectable(); - const rdsDatabase = new FakeConnectable(); - const fleet1 = new FakeConnectable(); - const fleet2 = new FakeConnectable(); - const listener = new FakeConnectable(); - const myEndpoint = new FakeConnectable(); - - /// here - } -} - -class FakeConnectable implements ec2.IConnectable { - public readonly connections = new ec2.Connections({ securityGroups: [] }); -} diff --git a/packages/@aws-cdk/aws-ec2/rosetta/default.ts-fixture b/packages/@aws-cdk/aws-ec2/rosetta/default.ts-fixture index d4ecd7e92a6f1..df2d29f125b46 100644 --- a/packages/@aws-cdk/aws-ec2/rosetta/default.ts-fixture +++ b/packages/@aws-cdk/aws-ec2/rosetta/default.ts-fixture @@ -1,7 +1,13 @@ // Fixture with packages imported, but nothing else -import { Construct, Stack } from '@aws-cdk/core'; +import { Aspects, Construct, Duration, Fn, Size, Stack, StackProps } from '@aws-cdk/core'; import ec2 = require('@aws-cdk/aws-ec2'); +import s3 = require('@aws-cdk/aws-s3'); import iam = require('@aws-cdk/aws-iam'); +import logs = require('@aws-cdk/aws-logs'); +import ssm = require('@aws-cdk/aws-ssm'); +import autoscaling = require('@aws-cdk/aws-autoscaling'); +import elbv2 = require('@aws-cdk/aws-elasticloadbalancingv2'); +import rds = require('@aws-cdk/aws-rds'); class Fixture extends Stack { constructor(scope: Construct, id: string) { From 6aa86d590d5e06c64677161d970eb39a77f8fd99 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Wed, 27 Oct 2021 19:04:44 +0200 Subject: [PATCH 56/87] chore(elbv2): make examples compile (#17162) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../aws-elasticloadbalancingv2/README.md | 131 +++++++++++------- .../rosetta/default.ts-fixture | 17 +++ 2 files changed, 100 insertions(+), 48 deletions(-) create mode 100644 packages/@aws-cdk/aws-elasticloadbalancingv2/rosetta/default.ts-fixture diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/README.md b/packages/@aws-cdk/aws-elasticloadbalancingv2/README.md index f3d23b5e827cf..34755353fb202 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/README.md +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/README.md @@ -26,13 +26,10 @@ You define an application load balancer by creating an instance of and adding Targets to the Listener: ```ts -import * as ec2 from '@aws-cdk/aws-ec2'; -import * as elbv2 from '@aws-cdk/aws-elasticloadbalancingv2'; import { AutoScalingGroup } from '@aws-cdk/aws-autoscaling'; +declare const asg: AutoScalingGroup; -// ... - -const vpc = new ec2.Vpc(...); +declare const vpc: ec2.Vpc; // Create the load balancer in a VPC. 'internetFacing' is 'false' // by default, which creates an internal load balancer. @@ -54,7 +51,6 @@ const listener = lb.addListener('Listener', { // Create an AutoScaling group and add it as a load balancing // target to the listener. -const asg = new AutoScalingGroup(...); listener.addTargets('ApplicationFleet', { port: 8080, targets: [asg] @@ -68,14 +64,16 @@ One (or more) security groups can be associated with the load balancer; if a security group isn't provided, one will be automatically created. ```ts -const securityGroup1 = new ec2.SecurityGroup(stack, 'SecurityGroup1', { vpc }); +declare const vpc: ec2.Vpc; + +const securityGroup1 = new ec2.SecurityGroup(this, 'SecurityGroup1', { vpc }); const lb = new elbv2.ApplicationLoadBalancer(this, 'LB', { vpc, internetFacing: true, securityGroup: securityGroup1, // Optional - will be automatically created otherwise }); -const securityGroup2 = new ec2.SecurityGroup(stack, 'SecurityGroup2', { vpc }); +const securityGroup2 = new ec2.SecurityGroup(this, 'SecurityGroup2', { vpc }); lb.addSecurityGroup(securityGroup2); ``` @@ -87,11 +85,14 @@ AutoScalingGroup only if the requested host in the request is either for `example.com/ok` or `example.com/path`: ```ts +declare const listener: elbv2.ApplicationListener; +declare const asg: autoscaling.AutoScalingGroup; + listener.addTargets('Example.Com Fleet', { priority: 10, conditions: [ - ListenerCondition.hostHeaders(['example.com']), - ListenerCondition.pathPatterns(['/ok', '/path']), + elbv2.ListenerCondition.hostHeaders(['example.com']), + elbv2.ListenerCondition.pathPatterns(['/ok', '/path']), ], port: 8080, targets: [asg] @@ -149,12 +150,14 @@ Balancer that the other two convenience methods don't: Here's an example of serving a fixed response at the `/ok` URL: ```ts +declare const listener: elbv2.ApplicationListener; + listener.addAction('Fixed', { priority: 10, conditions: [ - ListenerCondition.pathPatterns(['/ok']), + elbv2.ListenerCondition.pathPatterns(['/ok']), ], - action: ListenerAction.fixedResponse(200, { + action: elbv2.ListenerAction.fixedResponse(200, { contentType: elbv2.ContentType.TEXT_PLAIN, messageBody: 'OK', }) @@ -164,12 +167,21 @@ listener.addAction('Fixed', { Here's an example of using OIDC authentication before forwarding to a TargetGroup: ```ts +declare const listener: elbv2.ApplicationListener; +declare const myTargetGroup: elbv2.ApplicationTargetGroup; + listener.addAction('DefaultAction', { - action: ListenerAction.authenticateOidc({ + action: elbv2.ListenerAction.authenticateOidc({ authorizationEndpoint: 'https://example.com/openid', // Other OIDC properties here - // ... - next: ListenerAction.forward([myTargetGroup]), + clientId: '...', + clientSecret: SecretValue.secretsManager('...'), + issuer: '...', + tokenEndpoint: '...', + userInfoEndpoint: '...', + + // Next + next: elbv2.ListenerAction.forward([myTargetGroup]), }), }); ``` @@ -177,6 +189,8 @@ listener.addAction('DefaultAction', { If you just want to redirect all incoming traffic on one port to another port, you can use the following code: ```ts +declare const lb: elbv2.ApplicationLoadBalancer; + lb.addRedirect({ sourceProtocol: elbv2.ApplicationProtocol.HTTPS, sourcePort: 8443, @@ -196,9 +210,8 @@ Network Load Balancers are defined in a similar way to Application Load Balancers: ```ts -import * as ec2 from '@aws-cdk/aws-ec2'; -import * as elbv2 from '@aws-cdk/aws-elasticloadbalancingv2'; -import * as autoscaling from '@aws-cdk/aws-autoscaling'; +declare const vpc: ec2.Vpc; +declare const asg: autoscaling.AutoScalingGroup; // Create the load balancer in a VPC. 'internetFacing' is 'false' // by default, which creates an internal load balancer. @@ -243,6 +256,10 @@ and add it to the listener by calling `addTargetGroups` instead of `addTargets`. `addTargets()` will always return the Target Group it just created for you: ```ts +declare const listener: elbv2.NetworkListener; +declare const asg1: autoscaling.AutoScalingGroup; +declare const asg2: autoscaling.AutoScalingGroup; + const group = listener.addTargets('AppFleet', { port: 443, targets: [asg1], @@ -258,19 +275,21 @@ By default, an Application Load Balancer routes each request independently to a Application Load Balancers support both duration-based cookies (`lb_cookie`) and application-based cookies (`app_cookie`). The key to managing sticky sessions is determining how long your load balancer should consistently route the user's request to the same target. Sticky sessions are enabled at the target group level. You can use a combination of duration-based stickiness, application-based stickiness, and no stickiness across all of your target groups. ```ts +declare const vpc: ec2.Vpc; + // Target group with duration-based stickiness with load-balancer generated cookie -const tg1 = new elbv2.ApplicationTargetGroup(stack, 'TG1', { +const tg1 = new elbv2.ApplicationTargetGroup(this, 'TG1', { targetType: elbv2.TargetType.INSTANCE, port: 80, - stickinessCookieDuration: cdk.Duration.minutes(5), + stickinessCookieDuration: Duration.minutes(5), vpc, }); // Target group with application-based stickiness -const tg2 = new elbv2.ApplicationTargetGroup(stack, 'TG2', { +const tg2 = new elbv2.ApplicationTargetGroup(this, 'TG2', { targetType: elbv2.TargetType.INSTANCE, port: 80, - stickinessCookieDuration: cdk.Duration.minutes(5), + stickinessCookieDuration: Duration.minutes(5), stickinessCookieName: 'MyDeliciousCookie', vpc, }); @@ -283,7 +302,9 @@ For more information see: https://docs.aws.amazon.com/elasticloadbalancing/lates By default, Application Load Balancers send requests to targets using HTTP/1.1. You can use the [protocol version](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-target-groups.html#target-group-protocol-version) to send requests to targets using HTTP/2 or gRPC. ```ts -const tg = new elbv2.ApplicationTargetGroup(stack, 'TG', { +declare const vpc: ec2.Vpc; + +const tg = new elbv2.ApplicationTargetGroup(this, 'TG', { targetType: elbv2.TargetType.IP, port: 50051, protocol: elbv2.ApplicationProtocol.HTTP, @@ -303,11 +324,10 @@ To use a Lambda Function as a target, use the integration class in the ```ts import * as lambda from '@aws-cdk/aws-lambda'; -import * as elbv2 from '@aws-cdk/aws-elasticloadbalancingv2'; import * as targets from '@aws-cdk/aws-elasticloadbalancingv2-targets'; -const lambdaFunction = new lambda.Function(...); -const lb = new elbv2.ApplicationLoadBalancer(...); +declare const lambdaFunction: lambda.Function; +declare const lb: elbv2.ApplicationLoadBalancer; const listener = lb.addListener('Listener', { port: 80 }); listener.addTargets('Targets', { @@ -329,11 +349,12 @@ To use a single application load balancer as a target for the network load balan `@aws-cdk/aws-elasticloadbalancingv2-targets` package: ```ts -import * as elbv2 from '@aws-cdk/aws-elasticloadbalancingv2'; import * as targets from '@aws-cdk/aws-elasticloadbalancingv2-targets'; import * as ecs from '@aws-cdk/aws-ecs'; import * as patterns from '@aws-cdk/aws-ecs-patterns'; +declare const vpc: ec2.Vpc; + const task = new ecs.FargateTaskDefinition(this, 'Task', { cpu: 256, memoryLimitMiB: 512 }); task.addContainer('nginx', { image: ecs.ContainerImage.fromRegistry('public.ecr.aws/nginx/nginx:latest'), @@ -369,12 +390,15 @@ Only the network load balancer is allowed to add the application load balancer a Health checks are configured upon creation of a target group: ```ts +declare const listener: elbv2.ApplicationListener; +declare const asg: autoscaling.AutoScalingGroup; + listener.addTargets('AppFleet', { port: 8080, targets: [asg], healthCheck: { path: '/ping', - interval: cdk.Duration.minutes(1), + interval: Duration.minutes(1), } }); ``` @@ -388,15 +412,19 @@ you're routing traffic to, the security group already allows the traffic. If not, you will have to configure the security groups appropriately: ```ts +declare const lb: elbv2.ApplicationLoadBalancer; +declare const listener: elbv2.ApplicationListener; +declare const asg: autoscaling.AutoScalingGroup; + listener.addTargets('AppFleet', { port: 8080, targets: [asg], healthCheck: { - port: 8088, + port: '8088', } }); -listener.connections.allowFrom(lb, ec2.Port.tcp(8088)); +asg.connections.allowFrom(lb, ec2.Port.tcp(8088)); ``` ## Using a Load Balancer from a different Stack @@ -424,12 +452,15 @@ call functions on the load balancer and should return metadata about the load balancing target: ```ts -public attachToApplicationTargetGroup(targetGroup: ApplicationTargetGroup): LoadBalancerTargetProps { - targetGroup.registerConnectable(...); - return { - targetType: TargetType.Instance | TargetType.Ip - targetJson: { id: ..., port: ... }, - }; +class MyTarget implements elbv2.IApplicationLoadBalancerTarget { + public attachToApplicationTargetGroup(targetGroup: elbv2.ApplicationTargetGroup): elbv2.LoadBalancerTargetProps { + // If we need to add security group rules + // targetGroup.registerConnectable(...); + return { + targetType: elbv2.TargetType.IP, + targetJson: { id: '1.2.3.4', port: 8080 }, + }; + } } ``` @@ -445,12 +476,16 @@ group rules. If your load balancer target requires that the TargetGroup has been associated with a LoadBalancer before registration can happen (such as is the case for ECS Services for example), take a resource dependency on -`targetGroup.loadBalancerDependency()` as follows: +`targetGroup.loadBalancerAttached` as follows: ```ts +declare const resource: Resource; +declare const targetGroup: elbv2.ApplicationTargetGroup; + // Make sure that the listener has been created, and so the TargetGroup // has been associated with the LoadBalancer, before 'resource' is created. -resourced.addDependency(targetGroup.loadBalancerDependency()); + +Node.of(resource).addDependency(targetGroup.loadBalancerAttached); ``` ## Looking up Load Balancers and Listeners @@ -478,15 +513,15 @@ provide more specific criteria. **Look up a Application Load Balancer by ARN** ```ts -const loadBalancer = ApplicationLoadBalancer.fromLookup(stack, 'ALB', { - loadBalancerArn: YOUR_ALB_ARN, +const loadBalancer = elbv2.ApplicationLoadBalancer.fromLookup(this, 'ALB', { + loadBalancerArn: 'arn:aws:elasticloadbalancing:us-east-2:123456789012:loadbalancer/app/my-load-balancer/1234567890123456', }); ``` **Look up an Application Load Balancer by tags** ```ts -const loadBalancer = ApplicationLoadBalancer.fromLookup(stack, 'ALB', { +const loadBalancer = elbv2.ApplicationLoadBalancer.fromLookup(this, 'ALB', { loadBalancerTags: { // Finds a load balancer matching all tags. some: 'tag', @@ -512,9 +547,9 @@ criteria. **Look up a Listener by associated Load Balancer, Port, and Protocol** ```ts -const listener = ApplicationListener.fromLookup(stack, 'ALBListener', { - loadBalancerArn: YOUR_ALB_ARN, - listenerProtocol: ApplicationProtocol.HTTPS, +const listener = elbv2.ApplicationListener.fromLookup(this, 'ALBListener', { + loadBalancerArn: 'arn:aws:elasticloadbalancing:us-east-2:123456789012:loadbalancer/app/my-load-balancer/1234567890123456', + listenerProtocol: elbv2.ApplicationProtocol.HTTPS, listenerPort: 443, }); ``` @@ -522,11 +557,11 @@ const listener = ApplicationListener.fromLookup(stack, 'ALBListener', { **Look up a Listener by associated Load Balancer Tag, Port, and Protocol** ```ts -const listener = ApplicationListener.fromLookup(stack, 'ALBListener', { +const listener = elbv2.ApplicationListener.fromLookup(this, 'ALBListener', { loadBalancerTags: { Cluster: 'MyClusterName', }, - listenerProtocol: ApplicationProtocol.HTTPS, + listenerProtocol: elbv2.ApplicationProtocol.HTTPS, listenerPort: 443, }); ``` @@ -534,11 +569,11 @@ const listener = ApplicationListener.fromLookup(stack, 'ALBListener', { **Look up a Network Listener by associated Load Balancer Tag, Port, and Protocol** ```ts -const listener = NetworkListener.fromLookup(stack, 'ALBListener', { +const listener = elbv2.NetworkListener.fromLookup(this, 'ALBListener', { loadBalancerTags: { Cluster: 'MyClusterName', }, - listenerProtocol: Protocol.TCP, + listenerProtocol: elbv2.Protocol.TCP, listenerPort: 12345, }); ``` diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/rosetta/default.ts-fixture b/packages/@aws-cdk/aws-elasticloadbalancingv2/rosetta/default.ts-fixture new file mode 100644 index 0000000000000..8a21c6ec4d9a6 --- /dev/null +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/rosetta/default.ts-fixture @@ -0,0 +1,17 @@ +// Fixture with packages imported, but nothing else +import { Construct, Node } from 'constructs'; +import { CfnOutput, Stack, Duration, Resource, SecretValue } from '@aws-cdk/core'; +import * as elbv2 from '@aws-cdk/aws-elasticloadbalancingv2'; +import * as ec2 from '@aws-cdk/aws-ec2'; +import * as autoscaling from '@aws-cdk/aws-autoscaling'; + +class Fixture extends Stack { + constructor(scope: Construct, id: string) { + super(scope, id); + + /// here + } +} + + + From d298696a7d8978296a34294484cea80f91ebe880 Mon Sep 17 00:00:00 2001 From: James Lakin Date: Wed, 27 Oct 2021 18:55:18 +0100 Subject: [PATCH 57/87] feat(core): Docker tags can be prefixed (#17028) This adds a container image equivalent of the `bucketPrefix` option for file assets. CDK assets works very well to make deploying applications easy, but I often find the contents of the S3 bucket and ECR repo to be a mess of alphabetti spaghetti over time. These options should help to provide some context in future cleanup operations. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../stack-synthesizers/default-synthesizer.ts | 19 +++++++++++++-- .../new-style-synthesis.test.ts | 24 +++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/core/lib/stack-synthesizers/default-synthesizer.ts b/packages/@aws-cdk/core/lib/stack-synthesizers/default-synthesizer.ts index aae69e36ef24e..d8e1f8818abc4 100644 --- a/packages/@aws-cdk/core/lib/stack-synthesizers/default-synthesizer.ts +++ b/packages/@aws-cdk/core/lib/stack-synthesizers/default-synthesizer.ts @@ -168,11 +168,20 @@ export interface DefaultStackSynthesizerProps { /** * bucketPrefix to use while storing S3 Assets * - * * @default - DefaultStackSynthesizer.DEFAULT_FILE_ASSET_PREFIX */ readonly bucketPrefix?: string; + /** + * A prefix to use while tagging and uploading Docker images to ECR. + * + * This does not add any separators - the source hash will be appended to + * this string directly. + * + * @default - DefaultStackSynthesizer.DEFAULT_DOCKER_ASSET_PREFIX + */ + readonly dockerTagPrefix?: string; + /** * Bootstrap stack version SSM parameter. * @@ -242,6 +251,10 @@ export class DefaultStackSynthesizer extends StackSynthesizer { * Default file asset prefix */ public static readonly DEFAULT_FILE_ASSET_PREFIX = ''; + /** + * Default Docker asset prefix + */ + public static readonly DEFAULT_DOCKER_ASSET_PREFIX = ''; /** * Default bootstrap stack version SSM parameter. @@ -258,6 +271,7 @@ export class DefaultStackSynthesizer extends StackSynthesizer { private lookupRoleArn?: string; private qualifier?: string; private bucketPrefix?: string; + private dockerTagPrefix?: string; private bootstrapStackVersionSsmParameter?: string; private readonly files: NonNullable = {}; @@ -319,6 +333,7 @@ export class DefaultStackSynthesizer extends StackSynthesizer { this.imageAssetPublishingRoleArn = specialize(this.props.imageAssetPublishingRoleArn ?? DefaultStackSynthesizer.DEFAULT_IMAGE_ASSET_PUBLISHING_ROLE_ARN); this.lookupRoleArn = specialize(this.props.lookupRoleArn ?? DefaultStackSynthesizer.DEFAULT_LOOKUP_ROLE_ARN); this.bucketPrefix = specialize(this.props.bucketPrefix ?? DefaultStackSynthesizer.DEFAULT_FILE_ASSET_PREFIX); + this.dockerTagPrefix = specialize(this.props.dockerTagPrefix ?? DefaultStackSynthesizer.DEFAULT_DOCKER_ASSET_PREFIX); this.bootstrapStackVersionSsmParameter = replaceAll( this.props.bootstrapStackVersionSsmParameter ?? DefaultStackSynthesizer.DEFAULT_BOOTSTRAP_STACK_VERSION_SSM_PARAMETER, '${Qualifier}', @@ -372,7 +387,7 @@ export class DefaultStackSynthesizer extends StackSynthesizer { assertBound(this.repositoryName); validateDockerImageAssetSource(asset); - const imageTag = asset.sourceHash; + const imageTag = this.dockerTagPrefix + asset.sourceHash; // Add to manifest this.dockerImages[asset.sourceHash] = { diff --git a/packages/@aws-cdk/core/test/stack-synthesis/new-style-synthesis.test.ts b/packages/@aws-cdk/core/test/stack-synthesis/new-style-synthesis.test.ts index 3a8d8c1e60b31..80303a4bbcf22 100644 --- a/packages/@aws-cdk/core/test/stack-synthesis/new-style-synthesis.test.ts +++ b/packages/@aws-cdk/core/test/stack-synthesis/new-style-synthesis.test.ts @@ -337,6 +337,30 @@ describe('new style synthesis', () => { }); + test('synthesis with dockerPrefix', () => { + // GIVEN + const myapp = new App(); + + // WHEN + const mystack = new Stack(myapp, 'mystack-dockerPrefix', { + synthesizer: new DefaultStackSynthesizer({ + dockerTagPrefix: 'test-prefix-', + }), + }); + + mystack.synthesizer.addDockerImageAsset({ + directoryName: 'some-folder', + sourceHash: 'docker-asset-hash', + }); + + const asm = myapp.synth(); + + // THEN + const manifest = readAssetManifest(getAssetManifest(asm)); + const imageTag = manifest.dockerImages?.['docker-asset-hash']?.destinations?.['current_account-current_region'].imageTag; + expect(imageTag).toEqual('test-prefix-docker-asset-hash'); + }); + test('cannot use same synthesizer for multiple stacks', () => { // GIVEN const synthesizer = new DefaultStackSynthesizer(); From e5095b2cbda7422bd6e67aab6ad949294b0b8ef2 Mon Sep 17 00:00:00 2001 From: niku <10890+niku@users.noreply.github.com> Date: Thu, 28 Oct 2021 03:48:30 +0900 Subject: [PATCH 58/87] chore(cx-api): return type of futureFlagDefault is incorrect (#17026) If invalid flag were given to futureFlagDefault, it returns `undefined`. As you see in changed files, I don't modify production codes. I only fix return type of the `futureFlagDefault` and add a test to describe when it runs into. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/@aws-cdk/cx-api/lib/features.ts | 2 +- packages/@aws-cdk/cx-api/test/features.test.ts | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/@aws-cdk/cx-api/lib/features.ts b/packages/@aws-cdk/cx-api/lib/features.ts index 986be7f4e136b..37c9aace0ce86 100644 --- a/packages/@aws-cdk/cx-api/lib/features.ts +++ b/packages/@aws-cdk/cx-api/lib/features.ts @@ -220,6 +220,6 @@ const FUTURE_FLAGS_DEFAULTS: { [key: string]: boolean } = { [CLOUDFRONT_DEFAULT_SECURITY_POLICY_TLS_V1_2_2021]: false, }; -export function futureFlagDefault(flag: string): boolean { +export function futureFlagDefault(flag: string): boolean | undefined { return FUTURE_FLAGS_DEFAULTS[flag]; } diff --git a/packages/@aws-cdk/cx-api/test/features.test.ts b/packages/@aws-cdk/cx-api/test/features.test.ts index 2aaa774b7b1c5..afc9c0838d7da 100644 --- a/packages/@aws-cdk/cx-api/test/features.test.ts +++ b/packages/@aws-cdk/cx-api/test/features.test.ts @@ -7,6 +7,10 @@ test('all future flags have defaults configured', () => { }); }); +test('futureFlagDefault returns undefined if non existent flag was given', () => { + expect(feats.futureFlagDefault('non-existent-flag')).toEqual(undefined); +}); + testLegacyBehavior('FUTURE_FLAGS_EXPIRED must be empty in CDKv1', Object, () => { expect(feats.FUTURE_FLAGS_EXPIRED.length).toEqual(0); }); From 354686b189377dd1daae7ba616e8fb62488d9855 Mon Sep 17 00:00:00 2001 From: "Michael R. Torres" <6692889+micrictor@users.noreply.github.com> Date: Wed, 27 Oct 2021 12:40:55 -0700 Subject: [PATCH 59/87] fix(custom-resources): invalid service name leads to unhelpful error message (#16718) fix(custom-resources): improve AwsSdkCall service error Makes the error that occurs when an invalid service name is supplied more explicit. Closes #7312 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../lib/aws-custom-resource/runtime/index.ts | 3 ++ .../aws-custom-resource-provider.test.ts | 33 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/packages/@aws-cdk/custom-resources/lib/aws-custom-resource/runtime/index.ts b/packages/@aws-cdk/custom-resources/lib/aws-custom-resource/runtime/index.ts index a805fc8c2bf4d..e88b441637cfc 100644 --- a/packages/@aws-cdk/custom-resources/lib/aws-custom-resource/runtime/index.ts +++ b/packages/@aws-cdk/custom-resources/lib/aws-custom-resource/runtime/index.ts @@ -176,6 +176,9 @@ export async function handler(event: AWSLambda.CloudFormationCustomResourceEvent } + if (!Object.prototype.hasOwnProperty.call(AWS, call.service)) { + throw Error(`Service ${call.service} does not exist in AWS SDK version ${AWS.VERSION}.`); + } const awsService = new (AWS as any)[call.service]({ apiVersion: call.apiVersion, region: call.region, diff --git a/packages/@aws-cdk/custom-resources/test/aws-custom-resource/aws-custom-resource-provider.test.ts b/packages/@aws-cdk/custom-resources/test/aws-custom-resource/aws-custom-resource-provider.test.ts index 8a4786a138468..aa8a9589d1fdb 100644 --- a/packages/@aws-cdk/custom-resources/test/aws-custom-resource/aws-custom-resource-provider.test.ts +++ b/packages/@aws-cdk/custom-resources/test/aws-custom-resource/aws-custom-resource-provider.test.ts @@ -467,3 +467,36 @@ test('installs the latest SDK', async () => { // clean up aws-sdk install await fs.remove(tmpPath); }); + +test('invalid service name throws explicit error', async () => { + const publishFake = sinon.fake.resolves({}); + + AWS.mock('SNS', 'publish', publishFake); + + const event: AWSLambda.CloudFormationCustomResourceCreateEvent = { + ...eventCommon, + RequestType: 'Create', + ResourceProperties: { + ServiceToken: 'token', + Create: JSON.stringify({ + service: 'thisisnotarealservice', + action: 'publish', + parameters: { + Message: 'message', + TopicArn: 'topic', + }, + physicalResourceId: PhysicalResourceId.of('id'), + } as AwsSdkCall), + }, + }; + + const request = createRequest(body => + body.Status === 'FAILED' && + body.Reason!.startsWith('Service thisisnotarealservice does not exist'), + ); + + await handler(event, {} as AWSLambda.Context); + + expect(request.isDone()).toBeTruthy(); +}); + From 322cf10ef3257b9d20d898882a14de91110a0033 Mon Sep 17 00:00:00 2001 From: Jonathan Goldwasser Date: Wed, 27 Oct 2021 22:32:54 +0200 Subject: [PATCH 60/87] feat(cli): deployment progress shows stack name (#16604) Allows to filter logs based on stack name, gives more context when looking at a log line in a log file. Useful in CI when multiple stacks are deployed in a run. (similar to lerna adding the package name) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../cloudformation/stack-activity-monitor.ts | 5 ++- .../test/api/stack-activity-monitor.test.ts | 42 +++++++++---------- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/packages/aws-cdk/lib/api/util/cloudformation/stack-activity-monitor.ts b/packages/aws-cdk/lib/api/util/cloudformation/stack-activity-monitor.ts index 73075a41fee27..e956e63e3704c 100644 --- a/packages/aws-cdk/lib/api/util/cloudformation/stack-activity-monitor.ts +++ b/packages/aws-cdk/lib/api/util/cloudformation/stack-activity-monitor.ts @@ -523,8 +523,9 @@ export class HistoryActivityPrinter extends ActivityPrinterBase { this.stream.write( util.format( - ' %s%s | %s | %s | %s %s%s%s\n', - (progress !== false ? ` ${this.progress()} | ` : ''), + '%s | %s%s | %s | %s | %s %s%s%s\n', + e.StackName, + (progress !== false ? `${this.progress()} | ` : ''), new Date(e.Timestamp).toLocaleTimeString(), color(padRight(STATUS_WIDTH, (e.ResourceStatus || '').substr(0, STATUS_WIDTH))), // pad left and trim padRight(this.props.resourceTypeColumnWidth, e.ResourceType || ''), diff --git a/packages/aws-cdk/test/api/stack-activity-monitor.test.ts b/packages/aws-cdk/test/api/stack-activity-monitor.test.ts index c76ddda1ceb00..b793acda8b68b 100644 --- a/packages/aws-cdk/test/api/stack-activity-monitor.test.ts +++ b/packages/aws-cdk/test/api/stack-activity-monitor.test.ts @@ -27,12 +27,12 @@ test('prints 0/4 progress report, when addActivity is called with an "IN_PROGRES ResourceType: 'AWS::CloudFormation::Stack', StackId: '', EventId: '', - StackName: '', + StackName: 'stack-name', }, }); }); - expect(output[0].trim()).toStrictEqual(`0/4 | ${HUMAN_TIME} | ${reset('IN_PROGRESS ')} | AWS::CloudFormation::Stack | ${reset(bold('stack1'))}`); + expect(output[0].trim()).toStrictEqual(`stack-name | 0/4 | ${HUMAN_TIME} | ${reset('IN_PROGRESS ')} | AWS::CloudFormation::Stack | ${reset(bold('stack1'))}`); }); test('prints 1/4 progress report, when addActivity is called with an "UPDATE_COMPLETE" ResourceStatus', () => { @@ -51,12 +51,12 @@ test('prints 1/4 progress report, when addActivity is called with an "UPDATE_COM ResourceType: 'AWS::CloudFormation::Stack', StackId: '', EventId: '', - StackName: '', + StackName: 'stack-name', }, }); }); - expect(output[0].trim()).toStrictEqual(`1/4 | ${HUMAN_TIME} | ${green('UPDATE_COMPLETE ')} | AWS::CloudFormation::Stack | ${green(bold('stack1'))}`); + expect(output[0].trim()).toStrictEqual(`stack-name | 1/4 | ${HUMAN_TIME} | ${green('UPDATE_COMPLETE ')} | AWS::CloudFormation::Stack | ${green(bold('stack1'))}`); }); test('prints 1/4 progress report, when addActivity is called with an "UPDATE_COMPLETE_CLEAN_IN_PROGRESS" ResourceStatus', () => { @@ -75,12 +75,12 @@ test('prints 1/4 progress report, when addActivity is called with an "UPDATE_COM ResourceType: 'AWS::CloudFormation::Stack', StackId: '', EventId: '', - StackName: '', + StackName: 'stack-name', }, }); }); - expect(output[0].trim()).toStrictEqual(`1/4 | ${HUMAN_TIME} | ${green('UPDATE_COMPLETE_CLEA')} | AWS::CloudFormation::Stack | ${green(bold('stack1'))}`); + expect(output[0].trim()).toStrictEqual(`stack-name | 1/4 | ${HUMAN_TIME} | ${green('UPDATE_COMPLETE_CLEA')} | AWS::CloudFormation::Stack | ${green(bold('stack1'))}`); }); @@ -100,12 +100,12 @@ test('prints 1/4 progress report, when addActivity is called with an "ROLLBACK_C ResourceType: 'AWS::CloudFormation::Stack', StackId: '', EventId: '', - StackName: '', + StackName: 'stack-name', }, }); }); - expect(output[0].trim()).toStrictEqual(`1/4 | ${HUMAN_TIME} | ${yellow('ROLLBACK_COMPLETE_CL')} | AWS::CloudFormation::Stack | ${yellow(bold('stack1'))}`); + expect(output[0].trim()).toStrictEqual(`stack-name | 1/4 | ${HUMAN_TIME} | ${yellow('ROLLBACK_COMPLETE_CL')} | AWS::CloudFormation::Stack | ${yellow(bold('stack1'))}`); }); test('prints 0/4 progress report, when addActivity is called with an "UPDATE_FAILED" ResourceStatus', () => { @@ -124,12 +124,12 @@ test('prints 0/4 progress report, when addActivity is called with an "UPDATE_FAI ResourceType: 'AWS::CloudFormation::Stack', StackId: '', EventId: '', - StackName: '', + StackName: 'stack-name', }, }); }); - expect(output[0].trim()).toStrictEqual(`0/4 | ${HUMAN_TIME} | ${red('UPDATE_FAILED ')} | AWS::CloudFormation::Stack | ${red(bold('stack1'))}`); + expect(output[0].trim()).toStrictEqual(`stack-name | 0/4 | ${HUMAN_TIME} | ${red('UPDATE_FAILED ')} | AWS::CloudFormation::Stack | ${red(bold('stack1'))}`); }); @@ -149,7 +149,7 @@ test('does not print "Failed Resources:" list, when all deployments are successf ResourceType: 'AWS::CloudFormation::Stack', StackId: '', EventId: '', - StackName: '', + StackName: 'stack-name', }, }); historyActivityPrinter.addActivity({ @@ -160,7 +160,7 @@ test('does not print "Failed Resources:" list, when all deployments are successf ResourceType: 'AWS::CloudFormation::Stack', StackId: '', EventId: '', - StackName: '', + StackName: 'stack-name', }, }); historyActivityPrinter.addActivity({ @@ -171,16 +171,16 @@ test('does not print "Failed Resources:" list, when all deployments are successf ResourceType: 'AWS::CloudFormation::Stack', StackId: '', EventId: '', - StackName: '', + StackName: 'stack-name', }, }); historyActivityPrinter.stop(); }); expect(output.length).toStrictEqual(3); - expect(output[0].trim()).toStrictEqual(`0/2 | ${HUMAN_TIME} | ${reset('IN_PROGRESS ')} | AWS::CloudFormation::Stack | ${reset(bold('stack1'))}`); - expect(output[1].trim()).toStrictEqual(`1/2 | ${HUMAN_TIME} | ${green('UPDATE_COMPLETE ')} | AWS::CloudFormation::Stack | ${green(bold('stack1'))}`); - expect(output[2].trim()).toStrictEqual(`2/2 | ${HUMAN_TIME} | ${green('UPDATE_COMPLETE ')} | AWS::CloudFormation::Stack | ${green(bold('stack2'))}`); + expect(output[0].trim()).toStrictEqual(`stack-name | 0/2 | ${HUMAN_TIME} | ${reset('IN_PROGRESS ')} | AWS::CloudFormation::Stack | ${reset(bold('stack1'))}`); + expect(output[1].trim()).toStrictEqual(`stack-name | 1/2 | ${HUMAN_TIME} | ${green('UPDATE_COMPLETE ')} | AWS::CloudFormation::Stack | ${green(bold('stack1'))}`); + expect(output[2].trim()).toStrictEqual(`stack-name | 2/2 | ${HUMAN_TIME} | ${green('UPDATE_COMPLETE ')} | AWS::CloudFormation::Stack | ${green(bold('stack2'))}`); }); test('prints "Failed Resources:" list, when at least one deployment fails', () => { @@ -199,7 +199,7 @@ test('prints "Failed Resources:" list, when at least one deployment fails', () = ResourceType: 'AWS::CloudFormation::Stack', StackId: '', EventId: '', - StackName: '', + StackName: 'stack-name', }, }); historyActivityPrinter.addActivity({ @@ -210,15 +210,15 @@ test('prints "Failed Resources:" list, when at least one deployment fails', () = ResourceType: 'AWS::CloudFormation::Stack', StackId: '', EventId: '', - StackName: '', + StackName: 'stack-name', }, }); historyActivityPrinter.stop(); }); expect(output.length).toStrictEqual(4); - expect(output[0].trim()).toStrictEqual(`0/2 | ${HUMAN_TIME} | ${reset('IN_PROGRESS ')} | AWS::CloudFormation::Stack | ${reset(bold('stack1'))}`); - expect(output[1].trim()).toStrictEqual(`0/2 | ${HUMAN_TIME} | ${red('UPDATE_FAILED ')} | AWS::CloudFormation::Stack | ${red(bold('stack1'))}`); + expect(output[0].trim()).toStrictEqual(`stack-name | 0/2 | ${HUMAN_TIME} | ${reset('IN_PROGRESS ')} | AWS::CloudFormation::Stack | ${reset(bold('stack1'))}`); + expect(output[1].trim()).toStrictEqual(`stack-name | 0/2 | ${HUMAN_TIME} | ${red('UPDATE_FAILED ')} | AWS::CloudFormation::Stack | ${red(bold('stack1'))}`); expect(output[2].trim()).toStrictEqual('Failed resources:'); - expect(output[3].trim()).toStrictEqual(`${HUMAN_TIME} | ${red('UPDATE_FAILED ')} | AWS::CloudFormation::Stack | ${red(bold('stack1'))}`); + expect(output[3].trim()).toStrictEqual(`stack-name | ${HUMAN_TIME} | ${red('UPDATE_FAILED ')} | AWS::CloudFormation::Stack | ${red(bold('stack1'))}`); }); From 3cfe8a2df9edfb3133e470eb8f2274efcc2adda1 Mon Sep 17 00:00:00 2001 From: vincent-turato <39069200+vincent-turato@users.noreply.github.com> Date: Wed, 27 Oct 2021 14:24:25 -0700 Subject: [PATCH 61/87] feat(cloudtrail): selector for management event exclusions (#16546) Closes: #16273 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../@aws-cdk/aws-cloudtrail/lib/cloudtrail.ts | 24 ++++++++ .../aws-cloudtrail/test/cloudtrail.test.ts | 55 ++++++++++++++++++- 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-cloudtrail/lib/cloudtrail.ts b/packages/@aws-cdk/aws-cloudtrail/lib/cloudtrail.ts index 245c60600c08e..12cf079c5279e 100644 --- a/packages/@aws-cdk/aws-cloudtrail/lib/cloudtrail.ts +++ b/packages/@aws-cdk/aws-cloudtrail/lib/cloudtrail.ts @@ -334,6 +334,7 @@ export class Trail extends Resource { values: dataResourceValues, }], includeManagementEvents: options.includeManagementEvents, + excludeManagementEventSources: options.excludeManagementEventSources, readWriteType: options.readWriteType, }); } @@ -424,6 +425,28 @@ export interface AddEventSelectorOptions { * @default true */ readonly includeManagementEvents?: boolean; + + /** + * An optional list of service event sources from which you do not want management events to be logged on your trail. + * + * @default [] + */ + readonly excludeManagementEventSources?: ManagementEventSources[]; +} + +/** + * Types of management event sources that can be excluded + */ +export enum ManagementEventSources { + /** + * AWS Key Management Service (AWS KMS) events + */ + KMS = 'kms.amazonaws.com', + + /** + * Data API events + */ + RDS_DATA_API = 'rdsdata.amazonaws.com', } /** @@ -457,6 +480,7 @@ export enum DataResourceType { interface EventSelector { readonly includeManagementEvents?: boolean; + readonly excludeManagementEventSources?: string[]; readonly readWriteType?: ReadWriteType; readonly dataResources?: EventSelectorData[]; } diff --git a/packages/@aws-cdk/aws-cloudtrail/test/cloudtrail.test.ts b/packages/@aws-cdk/aws-cloudtrail/test/cloudtrail.test.ts index 9e17345368785..c00f01d43acc4 100644 --- a/packages/@aws-cdk/aws-cloudtrail/test/cloudtrail.test.ts +++ b/packages/@aws-cdk/aws-cloudtrail/test/cloudtrail.test.ts @@ -7,7 +7,7 @@ import { LogGroup, RetentionDays } from '@aws-cdk/aws-logs'; import * as s3 from '@aws-cdk/aws-s3'; import * as sns from '@aws-cdk/aws-sns'; import { Stack } from '@aws-cdk/core'; -import { ReadWriteType, Trail } from '../lib'; +import { ManagementEventSources, ReadWriteType, Trail } from '../lib'; const ExpectedBucketPolicyProperties = { PolicyDocument: { @@ -446,6 +446,59 @@ describe('cloudtrail', () => { }); }); + test('exclude management events', () => { + const stack = getTestStack(); + const bucket = new s3.Bucket(stack, 'testBucket', { bucketName: 'test-bucket' }); + const cloudTrail = new Trail(stack, 'MyAmazingCloudTrail'); + cloudTrail.addS3EventSelector([{ bucket }], { + excludeManagementEventSources: [ + ManagementEventSources.KMS, + ManagementEventSources.RDS_DATA_API, + ], + }); + cloudTrail.addS3EventSelector([{ bucket }], { + excludeManagementEventSources: [], + }); + + expect(stack).toHaveResourceLike('AWS::CloudTrail::Trail', { + EventSelectors: [ + { + DataResources: [{ + Type: 'AWS::S3::Object', + Values: [{ + 'Fn::Join': [ + '', + [ + { 'Fn::GetAtt': ['testBucketDF4D7D1A', 'Arn'] }, + '/', + ], + ], + }], + }], + ExcludeManagementEventSources: [ + 'kms.amazonaws.com', + 'rdsdata.amazonaws.com', + ], + }, + { + DataResources: [{ + Type: 'AWS::S3::Object', + Values: [{ + 'Fn::Join': [ + '', + [ + { 'Fn::GetAtt': ['testBucketDF4D7D1A', 'Arn'] }, + '/', + ], + ], + }], + }], + ExcludeManagementEventSources: [], + }, + ], + }); + }); + test('for Lambda function data event', () => { const stack = getTestStack(); const lambdaFunction = new lambda.Function(stack, 'LambdaFunction', { From dbb3f25904403bfc020a081e94270f5c16a7606f Mon Sep 17 00:00:00 2001 From: Alban Esc Date: Wed, 27 Oct 2021 15:16:33 -0700 Subject: [PATCH 62/87] feat(events): DLQ support for EventBus target (#16383) Closes #15954. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../@aws-cdk/aws-events-targets/README.md | 22 +++++- .../aws-events-targets/lib/event-bus.ts | 35 ++++++--- .../test/event-bus/event-rule-target.test.ts | 78 ++++++++++++++++++- .../event-bus/integ.event-bus.expected.json | 54 ++++++++++++- .../test/event-bus/integ.event-bus.ts | 7 ++ 5 files changed, 184 insertions(+), 12 deletions(-) diff --git a/packages/@aws-cdk/aws-events-targets/README.md b/packages/@aws-cdk/aws-events-targets/README.md index 76d25eab83dd3..1282cee012c5e 100644 --- a/packages/@aws-cdk/aws-events-targets/README.md +++ b/packages/@aws-cdk/aws-events-targets/README.md @@ -28,7 +28,7 @@ Currently supported are: * Put a record to a Kinesis stream * [Log an event into a LogGroup](#log-an-event-into-a-loggroup) * Put a record to a Kinesis Data Firehose stream -* Put an event on an EventBridge bus +* [Put an event on an EventBridge bus](#put-an-event-on-an-eventbridge-bus) See the README of the `@aws-cdk/aws-events` library for more information on EventBridge. @@ -266,3 +266,23 @@ rule.addTarget( } ), ) ``` + +## Put an event on an EventBridge bus + +Use the `EventBus` target to route event to a different EventBus. + +The code snippet below creates the scheduled event rule that route events to an imported event bus. + +```ts +const rule = new events.Rule(this, 'Rule', { + schedule: events.Schedule.expression('rate(1 minute)'), +}); + +rule.addTarget(new targets.EventBus( + events.EventBus.fromEventBusArn( + this, + 'External', + `arn:aws:events:eu-west-1:999999999999:event-bus/test-bus`, + ), +)); +``` diff --git a/packages/@aws-cdk/aws-events-targets/lib/event-bus.ts b/packages/@aws-cdk/aws-events-targets/lib/event-bus.ts index 8237b8cdd7993..7026273ef5330 100644 --- a/packages/@aws-cdk/aws-events-targets/lib/event-bus.ts +++ b/packages/@aws-cdk/aws-events-targets/lib/event-bus.ts @@ -1,9 +1,12 @@ import * as events from '@aws-cdk/aws-events'; import * as iam from '@aws-cdk/aws-iam'; -import { singletonEventRole } from './util'; +import * as sqs from '@aws-cdk/aws-sqs'; +import { singletonEventRole, addToDeadLetterQueueResourcePolicy } from './util'; /** * Configuration properties of an Event Bus event + * + * Cannot extend TargetBaseProps. Retry policy is not supported for Event bus targets. */ export interface EventBusProps { /** @@ -12,25 +15,39 @@ export interface EventBusProps { * @default a new role is created. */ readonly role?: iam.IRole; + + /** + * The SQS queue to be used as deadLetterQueue. + * Check out the [considerations for using a dead-letter queue](https://docs.aws.amazon.com/eventbridge/latest/userguide/rule-dlq.html#dlq-considerations). + * + * The events not successfully delivered are automatically retried for a specified period of time, + * depending on the retry policy of the target. + * If an event is not delivered before all retry attempts are exhausted, it will be sent to the dead letter queue. + * + * @default - no dead-letter queue + */ + readonly deadLetterQueue?: sqs.IQueue; } /** * Notify an existing Event Bus of an event */ export class EventBus implements events.IRuleTarget { - private readonly role?: iam.IRole; - - constructor(private readonly eventBus: events.IEventBus, props: EventBusProps = {}) { - this.role = props.role; - } + constructor(private readonly eventBus: events.IEventBus, private readonly props: EventBusProps = {}) { } bind(rule: events.IRule, _id?: string): events.RuleTargetConfig { - if (this.role) { - this.role.addToPrincipalPolicy(this.putEventStatement()); + if (this.props.role) { + this.props.role.addToPrincipalPolicy(this.putEventStatement()); } - const role = this.role ?? singletonEventRole(rule, [this.putEventStatement()]); + const role = this.props.role ?? singletonEventRole(rule, [this.putEventStatement()]); + + if (this.props.deadLetterQueue) { + addToDeadLetterQueueResourcePolicy(rule, this.props.deadLetterQueue); + } + return { arn: this.eventBus.eventBusArn, + deadLetterConfig: this.props.deadLetterQueue ? { arn: this.props.deadLetterQueue?.queueArn } : undefined, role, }; } diff --git a/packages/@aws-cdk/aws-events-targets/test/event-bus/event-rule-target.test.ts b/packages/@aws-cdk/aws-events-targets/test/event-bus/event-rule-target.test.ts index 8d188f1550e8b..a6552a10d7a57 100644 --- a/packages/@aws-cdk/aws-events-targets/test/event-bus/event-rule-target.test.ts +++ b/packages/@aws-cdk/aws-events-targets/test/event-bus/event-rule-target.test.ts @@ -1,6 +1,7 @@ import '@aws-cdk/assert-internal/jest'; import * as events from '@aws-cdk/aws-events'; import * as iam from '@aws-cdk/aws-iam'; +import * as sqs from '@aws-cdk/aws-sqs'; import { Stack } from '@aws-cdk/core'; import * as targets from '../../lib'; @@ -90,4 +91,79 @@ test('with supplied role', () => { Ref: 'Role1ABCC5F0', }], }); -}); \ No newline at end of file +}); + +test('with a Dead Letter Queue specified', () => { + const stack = new Stack(); + const rule = new events.Rule(stack, 'Rule', { + schedule: events.Schedule.expression('rate(1 min)'), + }); + const queue = new sqs.Queue(stack, 'Queue'); + + rule.addTarget(new targets.EventBus( + events.EventBus.fromEventBusArn( + stack, + 'External', + 'arn:aws:events:us-east-1:123456789012:default', + ), + { deadLetterQueue: queue }, + )); + + expect(stack).toHaveResource('AWS::Events::Rule', { + Targets: [{ + Arn: 'arn:aws:events:us-east-1:123456789012:default', + Id: 'Target0', + RoleArn: { + 'Fn::GetAtt': [ + 'RuleEventsRoleC51A4248', + 'Arn', + ], + }, + DeadLetterConfig: { + Arn: { + 'Fn::GetAtt': [ + 'Queue4A7E3555', + 'Arn', + ], + }, + }, + }], + }); + + expect(stack).toHaveResource('AWS::SQS::QueuePolicy', { + PolicyDocument: { + Statement: [ + { + Action: 'sqs:SendMessage', + Condition: { + ArnEquals: { + 'aws:SourceArn': { + 'Fn::GetAtt': [ + 'Rule4C995B7F', + 'Arn', + ], + }, + }, + }, + Effect: 'Allow', + Principal: { + Service: 'events.amazonaws.com', + }, + Resource: { + 'Fn::GetAtt': [ + 'Queue4A7E3555', + 'Arn', + ], + }, + Sid: 'AllowEventRuleRule', + }, + ], + Version: '2012-10-17', + }, + Queues: [ + { + Ref: 'Queue4A7E3555', + }, + ], + }); +}); diff --git a/packages/@aws-cdk/aws-events-targets/test/event-bus/integ.event-bus.expected.json b/packages/@aws-cdk/aws-events-targets/test/event-bus/integ.event-bus.expected.json index 632ddf1767598..a10603f0b03b5 100644 --- a/packages/@aws-cdk/aws-events-targets/test/event-bus/integ.event-bus.expected.json +++ b/packages/@aws-cdk/aws-events-targets/test/event-bus/integ.event-bus.expected.json @@ -19,6 +19,14 @@ ] ] }, + "DeadLetterConfig": { + "Arn": { + "Fn::GetAtt": [ + "Queue4A7E3555", + "Arn" + ] + } + }, "Id": "Target0", "RoleArn": { "Fn::GetAtt": [ @@ -78,6 +86,50 @@ } ] } + }, + "Queue4A7E3555": { + "Type": "AWS::SQS::Queue", + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "QueuePolicy25439813": { + "Type": "AWS::SQS::QueuePolicy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "sqs:SendMessage", + "Condition": { + "ArnEquals": { + "aws:SourceArn": { + "Fn::GetAtt": [ + "Rule4C995B7F", + "Arn" + ] + } + } + }, + "Effect": "Allow", + "Principal": { + "Service": "events.amazonaws.com" + }, + "Resource": { + "Fn::GetAtt": [ + "Queue4A7E3555", + "Arn" + ] + }, + "Sid": "AllowEventRuleeventsourcestackRuleFCA41174" + } + ], + "Version": "2012-10-17" + }, + "Queues": [ + { + "Ref": "Queue4A7E3555" + } + ] + } } } -} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-events-targets/test/event-bus/integ.event-bus.ts b/packages/@aws-cdk/aws-events-targets/test/event-bus/integ.event-bus.ts index c0ec2ea421b85..5a102ea3cba6c 100644 --- a/packages/@aws-cdk/aws-events-targets/test/event-bus/integ.event-bus.ts +++ b/packages/@aws-cdk/aws-events-targets/test/event-bus/integ.event-bus.ts @@ -1,5 +1,6 @@ /// !cdk-integ pragma:ignore-assets import * as events from '@aws-cdk/aws-events'; +import * as sqs from '@aws-cdk/aws-sqs'; import * as cdk from '@aws-cdk/core'; import * as targets from '../../lib'; @@ -12,12 +13,18 @@ class EventSourceStack extends cdk.Stack { const rule = new events.Rule(this, 'Rule', { schedule: events.Schedule.expression('rate(1 minute)'), }); + + const queue = new sqs.Queue(this, 'Queue'); + rule.addTarget(new targets.EventBus( events.EventBus.fromEventBusArn( this, 'External', `arn:aws:events:${this.region}:999999999999:event-bus/test-bus`, ), + { + deadLetterQueue: queue, + }, )); } } From 5831456465fa44af96a268de56db0e3a8d3c2ea6 Mon Sep 17 00:00:00 2001 From: Julian Michel Date: Thu, 28 Oct 2021 01:09:43 +0200 Subject: [PATCH 63/87] fix(core): SecretValue.secretsManager fails for tokenized secret-id (#16230) `SecretValue.secretsManager` fails if a token is used for `secret-id`. This is caused by a validation which should be skipped for tokenized values. Solved by skipping the validation if token is unresolved. Fixes #16166. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/@aws-cdk/core/lib/secret-value.ts | 3 +- .../@aws-cdk/core/test/secret-value.test.ts | 47 ++++++++++++++++++- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/core/lib/secret-value.ts b/packages/@aws-cdk/core/lib/secret-value.ts index 2cd1b772f3207..b57b704bd9ed6 100644 --- a/packages/@aws-cdk/core/lib/secret-value.ts +++ b/packages/@aws-cdk/core/lib/secret-value.ts @@ -1,6 +1,7 @@ import { CfnDynamicReference, CfnDynamicReferenceService } from './cfn-dynamic-reference'; import { CfnParameter } from './cfn-parameter'; import { Intrinsic } from './private/intrinsic'; +import { Token } from './token'; /** * Work with secret values in the CDK @@ -39,7 +40,7 @@ export class SecretValue extends Intrinsic { throw new Error('secretId cannot be empty'); } - if (!secretId.startsWith('arn:') && secretId.includes(':')) { + if (!Token.isUnresolved(secretId) && !secretId.startsWith('arn:') && secretId.includes(':')) { throw new Error(`secret id "${secretId}" is not an ARN but contains ":"`); } diff --git a/packages/@aws-cdk/core/test/secret-value.test.ts b/packages/@aws-cdk/core/test/secret-value.test.ts index a32702b98771d..2efcdffbe808d 100644 --- a/packages/@aws-cdk/core/test/secret-value.test.ts +++ b/packages/@aws-cdk/core/test/secret-value.test.ts @@ -1,4 +1,4 @@ -import { CfnDynamicReference, CfnDynamicReferenceService, CfnParameter, SecretValue, Stack } from '../lib'; +import { CfnDynamicReference, CfnDynamicReferenceService, CfnParameter, SecretValue, Stack, Token } from '../lib'; describe('secret value', () => { test('plainText', () => { @@ -28,6 +28,30 @@ describe('secret value', () => { }); + test('secretsManager with secret-id from token', () => { + // GIVEN + const stack = new Stack(); + + // WHEN + const v = SecretValue.secretsManager(Token.asString({ Ref: 'secret-id' }), { + jsonField: 'json-key', + versionStage: 'version-stage', + }); + + // THEN + expect(stack.resolve(v)).toEqual({ + 'Fn::Join': [ + '', + [ + '{{resolve:secretsmanager:', + { Ref: 'secret-id' }, + ':SecretString:json-key:version-stage:}}', + ], + ], + }); + + }); + test('secretsManager with defaults', () => { // GIVEN const stack = new Stack(); @@ -40,6 +64,27 @@ describe('secret value', () => { }); + test('secretsManager with defaults, secret-id from token', () => { + // GIVEN + const stack = new Stack(); + + // WHEN + const v = SecretValue.secretsManager(Token.asString({ Ref: 'secret-id' })); + + // THEN + expect(stack.resolve(v)).toEqual({ + 'Fn::Join': [ + '', + [ + '{{resolve:secretsmanager:', + { Ref: 'secret-id' }, + ':SecretString:::}}', + ], + ], + }); + + }); + test('secretsManager with an empty ID', () => { expect(() => SecretValue.secretsManager('')).toThrow(/secretId cannot be empty/); From e55301b635374a87822f78870981a9e06e13d99e Mon Sep 17 00:00:00 2001 From: Anurag Mohapatra Date: Thu, 28 Oct 2021 11:03:33 +1100 Subject: [PATCH 64/87] fix(cli): downgrade bootstrap stack error message needs a hint for new-style synthesis (#16237) Fix to the bootstrap error message on the version comparison to provide to peek at solution so as to warn users about new style stack synthesis not being enabled automatically in the cdk.json as the potential root cause Fixes https://github.com/aws/aws-cdk/issues/16009 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/aws-cdk/lib/api/bootstrap/deploy-bootstrap.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/aws-cdk/lib/api/bootstrap/deploy-bootstrap.ts b/packages/aws-cdk/lib/api/bootstrap/deploy-bootstrap.ts index 4d66e59268dcc..49f97e71332c3 100644 --- a/packages/aws-cdk/lib/api/bootstrap/deploy-bootstrap.ts +++ b/packages/aws-cdk/lib/api/bootstrap/deploy-bootstrap.ts @@ -65,7 +65,7 @@ export class BootstrapStack { const newVersion = bootstrapVersionFromTemplate(template); if (this.currentToolkitInfo.found && newVersion < this.currentToolkitInfo.version && !options.force) { - throw new Error(`Not downgrading existing bootstrap stack from version '${this.currentToolkitInfo.version}' to version '${newVersion}'. Use --force to force.`); + throw new Error(`Not downgrading existing bootstrap stack from version '${this.currentToolkitInfo.version}' to version '${newVersion}'. Use --force to force or set the '@aws-cdk/core:newStyleStackSynthesis' feature flag in cdk.json to use the latest bootstrap version.`); } const outdir = await fs.mkdtemp(path.join(os.tmpdir(), 'cdk-bootstrap')); @@ -114,4 +114,4 @@ export function bootstrapVersionFromTemplate(template: any): number { } } return 0; -} \ No newline at end of file +} From a6aaa64bf9779b984f20d18881b4f6e510ac091a Mon Sep 17 00:00:00 2001 From: James Lakin Date: Thu, 28 Oct 2021 01:56:20 +0100 Subject: [PATCH 65/87] fix(logs): Apply tags to log retention Lambda (#17029) This hopefully fixes #15032 by implementing the `ITaggable` interface on the custom construct and then applying discovered tags to the underlying `CfnResource`. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../@aws-cdk/aws-logs/lib/log-retention.ts | 5 +- .../aws-logs/test/log-retention.test.ts | 19 ++++++++ packages/@aws-cdk/core/lib/tag-manager.ts | 46 ++++++++++++++++++- 3 files changed, 67 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk/aws-logs/lib/log-retention.ts b/packages/@aws-cdk/aws-logs/lib/log-retention.ts index f3054cf910f1c..fe4e3e3cff7af 100644 --- a/packages/@aws-cdk/aws-logs/lib/log-retention.ts +++ b/packages/@aws-cdk/aws-logs/lib/log-retention.ts @@ -128,9 +128,11 @@ export class LogRetention extends CoreConstruct { /** * Private provider Lambda function to support the log retention custom resource. */ -class LogRetentionFunction extends CoreConstruct { +class LogRetentionFunction extends CoreConstruct implements cdk.ITaggable { public readonly functionArn: cdk.Reference; + public readonly tags: cdk.TagManager = new cdk.TagManager(cdk.TagType.KEY_VALUE, 'AWS::Lambda::Function'); + constructor(scope: Construct, id: string, props: LogRetentionProps) { super(scope, id); @@ -164,6 +166,7 @@ class LogRetentionFunction extends CoreConstruct { S3Key: asset.s3ObjectKey, }, Role: role.roleArn, + Tags: this.tags.renderedTags, }, }); this.functionArn = resource.getAtt('Arn'); diff --git a/packages/@aws-cdk/aws-logs/test/log-retention.test.ts b/packages/@aws-cdk/aws-logs/test/log-retention.test.ts index 8f8ed85bb4d47..208031bc1744b 100644 --- a/packages/@aws-cdk/aws-logs/test/log-retention.test.ts +++ b/packages/@aws-cdk/aws-logs/test/log-retention.test.ts @@ -156,4 +156,23 @@ describe('log retention', () => { expect(logGroupArn.endsWith(':*')).toEqual(true); }); + + test('retention Lambda CfnResource receives propagated tags', () => { + const stack = new cdk.Stack(); + cdk.Tags.of(stack).add('test-key', 'test-value'); + new LogRetention(stack, 'MyLambda', { + logGroupName: 'group', + retention: RetentionDays.ONE_MONTH, + }); + + expect(stack).toHaveResourceLike('AWS::Lambda::Function', { + Tags: [ + { + Key: 'test-key', + Value: 'test-value', + }, + ], + }); + + }); }); diff --git a/packages/@aws-cdk/core/lib/tag-manager.ts b/packages/@aws-cdk/core/lib/tag-manager.ts index cdc224500ef1b..8f4893d5036f0 100644 --- a/packages/@aws-cdk/core/lib/tag-manager.ts +++ b/packages/@aws-cdk/core/lib/tag-manager.ts @@ -1,5 +1,7 @@ import { TagType } from './cfn-resource'; import { CfnTag } from './cfn-tag'; +import { Lazy } from './lazy'; +import { IResolvable } from './resolvable'; interface Tag { key: string; @@ -172,7 +174,7 @@ class KeyValueFormatter implements ITagFormatter { Value: tag.value, }); }); - return tags; + return tags.length > 0 ? tags : undefined; } } @@ -228,7 +230,32 @@ export interface TagManagerOptions { } /** - * TagManager facilitates a common implementation of tagging for Constructs. + * TagManager facilitates a common implementation of tagging for Constructs + * + * Normally, you do not need to use this class, as the CloudFormation specification + * will indicate which resources are taggable. However, sometimes you will need this + * to make custom resources taggable. Used `tagManager.renderedTags` to obtain a + * value that will resolve to the tags at synthesis time. + * + * @example + * import * as cdk from '@aws-cdk/core'; + * + * class MyConstruct extends cdk.Resource implements cdk.ITaggable { + * public readonly tags = new cdk.TagManager(cdk.TagType.KEY_VALUE, 'Whatever::The::Type'); + * + * constructor(scope: cdk.Construct, id: string) { + * super(scope, id); + * + * new cdk.CfnResource(this, 'Resource', { + * type: 'Whatever::The::Type', + * properties: { + * // ... + * Tags: this.tags.renderedTags, + * }, + * }); + * } + * } + * */ export class TagManager { @@ -247,6 +274,14 @@ export class TagManager { */ public readonly tagPropertyName: string; + /** + * A lazy value that represents the rendered tags at synthesis time + * + * If you need to make a custom construct taggable, use the value of this + * property to pass to the `tags` property of the underlying construct. + */ + public readonly renderedTags: IResolvable; + private readonly tags = new Map(); private readonly priorities = new Map(); private readonly tagFormatter: ITagFormatter; @@ -260,6 +295,8 @@ export class TagManager { this._setTag(...this.tagFormatter.parseTags(tagStructure, this.initialTagPriority)); } this.tagPropertyName = options.tagPropertyName || 'tags'; + + this.renderedTags = Lazy.any({ produce: () => this.renderTags() }); } /** @@ -287,6 +324,11 @@ export class TagManager { /** * Renders tags into the proper format based on TagType + * + * This method will eagerly render the tags currently applied. In + * most cases, you should be using `tagManager.renderedTags` instead, + * which will return a `Lazy` value that will resolve to the correct + * tags at synthesis time. */ public renderTags(): any { return this.tagFormatter.formatTags(this.sortedTags); From 823c4d6700fdbba7f0defb2cf4daa1543738284b Mon Sep 17 00:00:00 2001 From: kaizen3031593 <36202692+kaizen3031593@users.noreply.github.com> Date: Wed, 27 Oct 2021 21:49:12 -0400 Subject: [PATCH 66/87] chore(lambda): make examples compile (#17188) ---- *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-lambda/README.md | 218 +++++++++--------- .../aws-lambda/rosetta/default.ts-fixture | 6 +- .../aws-lambda/rosetta/function.ts-fixture | 18 -- 3 files changed, 118 insertions(+), 124 deletions(-) delete mode 100644 packages/@aws-cdk/aws-lambda/rosetta/function.ts-fixture diff --git a/packages/@aws-cdk/aws-lambda/README.md b/packages/@aws-cdk/aws-lambda/README.md index dc97826d51135..bb42d0811994d 100644 --- a/packages/@aws-cdk/aws-lambda/README.md +++ b/packages/@aws-cdk/aws-lambda/README.md @@ -14,10 +14,10 @@ This construct library allows you to define AWS Lambda Functions. ```ts -const fn = new Function(this, 'MyFunction', { - runtime: Runtime.NODEJS_12_X, +const fn = new lambda.Function(this, 'MyFunction', { + runtime: lambda.Runtime.NODEJS_12_X, handler: 'index.handler', - code: Code.fromAsset(path.join(__dirname, 'lambda-handler')), + code: lambda.Code.fromAsset(path.join(__dirname, 'lambda-handler')), }); ``` @@ -62,8 +62,8 @@ The following `DockerImageFunction` construct uses a local folder with a Dockerfile as the asset that will be used as the function handler. ```ts -new DockerImageFunction(this, 'AssetFunction', { - code: DockerImageCode.fromImageAsset(path.join(__dirname, 'docker-handler')), +new lambda.DockerImageFunction(this, 'AssetFunction', { + code: lambda.DockerImageCode.fromImageAsset(path.join(__dirname, 'docker-handler')), }); ``` @@ -73,8 +73,8 @@ You can also specify an image that already exists in ECR as the function handler import * as ecr from '@aws-cdk/aws-ecr'; const repo = new ecr.Repository(this, 'Repository'); -new DockerImageFunction(this, 'ECRFunction', { - code: DockerImageCode.fromEcr(repo), +new lambda.DockerImageFunction(this, 'ECRFunction', { + code: lambda.DockerImageCode.fromEcr(repo), }); ``` @@ -90,13 +90,13 @@ The autogenerated Role is automatically given permissions to execute the Lambda function. To reference the autogenerated Role: ```ts -const fn = new Function(this, 'MyFunction', { - runtime: Runtime.NODEJS_12_X, +const fn = new lambda.Function(this, 'MyFunction', { + runtime: lambda.Runtime.NODEJS_12_X, handler: 'index.handler', - code: Code.fromAsset(path.join(__dirname, 'lambda-handler')), + code: lambda.Code.fromAsset(path.join(__dirname, 'lambda-handler')), }); -fn.role // the Role +const role = fn.role; // the Role ``` You can also provide your own IAM role. Provided IAM roles will not automatically @@ -104,15 +104,15 @@ be given permissions to execute the Lambda function. To provide a role and grant it appropriate permissions: ```ts -import * as iam from '@aws-cdk/aws-iam'; const myRole = new iam.Role(this, 'My Role', { assumedBy: new iam.ServicePrincipal('sns.amazonaws.com'), }); -const fn = new Function(this, 'MyFunction', { - runtime: Runtime.NODEJS_12_X, + +const fn = new lambda.Function(this, 'MyFunction', { + runtime: lambda.Runtime.NODEJS_12_X, handler: 'index.handler', - code: Code.fromAsset(path.join(__dirname, 'lambda-handler')), - role: myRole // user-provided role + code: lambda.Code.fromAsset(path.join(__dirname, 'lambda-handler')), + role: myRole, // user-provided role }); myRole.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName("service-role/AWSLambdaBasicExecutionRole")); @@ -128,8 +128,8 @@ functions. You can also restrict permissions given to AWS services by providing a source account or ARN (representing the account and identifier of the resource that accesses the function or layer). -```ts fixture=function -import * as iam from '@aws-cdk/aws-iam'; +```ts +declare const fn: lambda.Function; const principal = new iam.ServicePrincipal('my-service'); fn.grantInvoke(principal); @@ -151,8 +151,8 @@ principal in question has conditions limiting the source account or ARN of the operation (see above), these conditions will be automatically added to the resource policy. -```ts fixture=function -import * as iam from '@aws-cdk/aws-iam'; +```ts +declare const fn: lambda.Function; const servicePrincipal = new iam.ServicePrincipal('my-service'); const sourceArn = 'arn:aws:s3:::my-bucket'; const sourceAccount = '111122223333'; @@ -193,8 +193,8 @@ The function version includes the following information: You could create a version to your lambda function using the `Version` construct. ```ts -const fn = new Function(this, 'MyFunction', ...); -const version = new Version(this, 'MyVersion', { +declare const fn: lambda.Function; +const version = new lambda.Version(this, 'MyVersion', { lambda: fn, }); ``` @@ -211,9 +211,12 @@ latest code. For instance - ```ts const codeVersion = "stringOrMethodToGetCodeVersion"; const fn = new lambda.Function(this, 'MyFunction', { - environment: { - 'CodeVersionString': codeVersion - } + runtime: lambda.Runtime.NODEJS_12_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(path.join(__dirname, 'lambda-handler')), + environment: { + 'CodeVersionString': codeVersion, + }, }); ``` @@ -291,16 +294,14 @@ specify options for the current version through the `currentVersionOptions` property. ```ts -import * as cdk from '@aws-cdk/core'; - -const fn = new Function(this, 'MyFunction', { +const fn = new lambda.Function(this, 'MyFunction', { currentVersionOptions: { - removalPolicy: cdk.RemovalPolicy.RETAIN, // retain old versions - retryAttempts: 1 // async retry attempts + removalPolicy: RemovalPolicy.RETAIN, // retain old versions + retryAttempts: 1, // async retry attempts }, - runtime: Runtime.NODEJS_12_X, + runtime: lambda.Runtime.NODEJS_12_X, handler: 'index.handler', - code: Code.fromAsset(path.join(__dirname, 'lambda-handler')), + code: lambda.Code.fromAsset(path.join(__dirname, 'lambda-handler')), }); fn.currentVersion.addAlias('live'); @@ -318,11 +319,9 @@ By default, updating a layer creates a new layer version, and CloudFormation wil Alternatively, a removal policy can be used to retain the old version: ```ts -import * as cdk from '@aws-cdk/core'; - -new LayerVersion(this, 'MyLayer', { - removalPolicy: cdk.RemovalPolicy.RETAIN, - code: Code.fromAsset(path.join(__dirname, 'lambda-handler')), +new lambda.LayerVersion(this, 'MyLayer', { + removalPolicy: RemovalPolicy.RETAIN, + code: lambda.Code.fromAsset(path.join(__dirname, 'lambda-handler')), }); ``` @@ -336,18 +335,21 @@ for some workloads. A lambda function can be configured to be run on one of these platforms: ```ts -new Function(this, 'MyFunction', { - ... - architecture: Architecture.ARM_64, +new lambda.Function(this, 'MyFunction', { + runtime: lambda.Runtime.NODEJS_12_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(path.join(__dirname, 'lambda-handler')), + architecture: lambda.Architecture.ARM_64, }); ``` Similarly, lambda layer versions can also be tagged with architectures it is compatible with. ```ts -new LayerVersion(this, 'MyLayer', { - ... - compatibleArchitectures: [Architecture.X86_64, Architecture.ARM_64], +new lambda.LayerVersion(this, 'MyLayer', { + removalPolicy: RemovalPolicy.RETAIN, + code: lambda.Code.fromAsset(path.join(__dirname, 'lambda-handler')), + compatibleArchitectures: [lambda.Architecture.X86_64, lambda.Architecture.ARM_64], }); ``` @@ -357,20 +359,24 @@ Lambda functions can be configured to use CloudWatch [Lambda Insights](https://d which provides low-level runtime metrics for a Lambda functions. ```ts -import * as lambda from '@aws-cdk/lambda'; - -new Function(this, 'MyFunction', { - insightsVersion: lambda.LambdaInsightsVersion.VERSION_1_0_98_0 -}) +new lambda.Function(this, 'MyFunction', { + runtime: lambda.Runtime.NODEJS_12_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(path.join(__dirname, 'lambda-handler')), + insightsVersion: lambda.LambdaInsightsVersion.VERSION_1_0_98_0, +}); ``` If the version of insights is not yet available in the CDK, you can also provide the ARN directly as so - ```ts const layerArn = 'arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:14'; -new Function(this, 'MyFunction', { - insightsVersion: lambda.LambdaInsightsVersion.fromInsightVersionArn(layerArn) -}) +new lambda.Function(this, 'MyFunction', { + runtime: lambda.Runtime.NODEJS_12_X, + handler: 'index.handler', + code: lambda.Code.fromAsset(path.join(__dirname, 'lambda-handler')), + insightsVersion: lambda.LambdaInsightsVersion.fromInsightVersionArn(layerArn), +}); ``` ## Event Rule Target @@ -378,9 +384,11 @@ new Function(this, 'MyFunction', { You can use an AWS Lambda function as a target for an Amazon CloudWatch event rule: -```ts fixture=function +```ts import * as events from '@aws-cdk/aws-events'; import * as targets from '@aws-cdk/aws-events-targets'; + +declare const fn: lambda.Function; const rule = new events.Rule(this, 'Schedule Rule', { schedule: events.Schedule.cron({ minute: '0', hour: '4' }), }); @@ -402,18 +410,22 @@ includes classes for the various event sources supported by AWS Lambda. For example, the following code adds an SQS queue as an event source for a function: -```ts fixture=function +```ts import * as eventsources from '@aws-cdk/aws-lambda-event-sources'; import * as sqs from '@aws-cdk/aws-sqs'; + +declare const fn: lambda.Function; const queue = new sqs.Queue(this, 'Queue'); fn.addEventSource(new eventsources.SqsEventSource(queue)); ``` The following code adds an S3 bucket notification as an event source: -```ts fixture=function +```ts import * as eventsources from '@aws-cdk/aws-lambda-event-sources'; import * as s3 from '@aws-cdk/aws-s3'; + +declare const fn: lambda.Function; const bucket = new s3.Bucket(this, 'Bucket'); fn.addEventSource(new eventsources.S3EventSource(bucket, { events: [ s3.EventType.OBJECT_CREATED, s3.EventType.OBJECT_REMOVED ], @@ -429,11 +441,11 @@ A dead-letter queue can be automatically created for a Lambda function by setting the `deadLetterQueueEnabled: true` configuration. ```ts -const fn = new Function(this, 'MyFunction', { - runtime: Runtime.NODEJS_12_X, - handler: 'index.handler', - code: Code.fromInline('exports.handler = function(event, ctx, cb) { return cb(null, "hi"); }'), - deadLetterQueueEnabled: true +const fn = new lambda.Function(this, 'MyFunction', { + runtime: lambda.Runtime.NODEJS_12_X, + handler: 'index.handler', + code: lambda.Code.fromInline('exports.handler = function(event, ctx, cb) { return cb(null, "hi"); }'), + deadLetterQueueEnabled: true, }); ``` @@ -443,11 +455,11 @@ It is also possible to provide a dead-letter queue instead of getting a new queu import * as sqs from '@aws-cdk/aws-sqs'; const dlq = new sqs.Queue(this, 'DLQ'); -const fn = new Function(this, 'MyFunction', { - runtime: Runtime.NODEJS_12_X, - handler: 'index.handler', - code: Code.fromInline('exports.handler = function(event, ctx, cb) { return cb(null, "hi"); }'), - deadLetterQueue: dlq +const fn = new lambda.Function(this, 'MyFunction', { + runtime: lambda.Runtime.NODEJS_12_X, + handler: 'index.handler', + code: lambda.Code.fromInline('exports.handler = function(event, ctx, cb) { return cb(null, "hi"); }'), + deadLetterQueue: dlq, }); ``` @@ -457,11 +469,11 @@ to learn more about AWS Lambdas and DLQs. ## Lambda with X-Ray Tracing ```ts -const fn = new Function(this, 'MyFunction', { - runtime: Runtime.NODEJS_12_X, - handler: 'index.handler', - code: Code.fromInline('exports.handler = function(event, ctx, cb) { return cb(null, "hi"); }'), - tracing: Tracing.ACTIVE +const fn = new lambda.Function(this, 'MyFunction', { + runtime: lambda.Runtime.NODEJS_12_X, + handler: 'index.handler', + code: lambda.Code.fromInline('exports.handler = function(event, ctx, cb) { return cb(null, "hi"); }'), + tracing: lambda.Tracing.ACTIVE, }); ``` @@ -474,13 +486,11 @@ The following code configures the lambda function with CodeGuru profiling. By de profiling group - ```ts -import * as lambda from '@aws-cdk/aws-lambda'; - -const fn = new Function(this, 'MyFunction', { - runtime: Runtime.PYTHON_3_6, - handler: 'index.handler', - code: Code.fromAsset('lambda-handler'), - profiling: true +const fn = new lambda.Function(this, 'MyFunction', { + runtime: lambda.Runtime.PYTHON_3_6, + handler: 'index.handler', + code: lambda.Code.fromAsset('lambda-handler'), + profiling: true, }); ``` @@ -494,11 +504,11 @@ to learn more about AWS Lambda's Profiling support. ## Lambda with Reserved Concurrent Executions ```ts -const fn = new Function(this, 'MyFunction', { - runtime: Runtime.NODEJS_12_X, - handler: 'index.handler', - code: Code.fromInline('exports.handler = function(event, ctx, cb) { return cb(null, "hi"); }'), - reservedConcurrentExecutions: 100 +const fn = new lambda.Function(this, 'MyFunction', { + runtime: lambda.Runtime.NODEJS_12_X, + handler: 'index.handler', + code: lambda.Code.fromInline('exports.handler = function(event, ctx, cb) { return cb(null, "hi"); }'), + reservedConcurrentExecutions: 100, }); ``` @@ -509,15 +519,17 @@ managing concurrency. You can use Application AutoScaling to automatically configure the provisioned concurrency for your functions. AutoScaling can be set to track utilization or be based on a schedule. To configure AutoScaling on a function alias: -```ts fixture=function +```ts import * as autoscaling from '@aws-cdk/aws-autoscaling'; -const alias = new Alias(this, 'Alias', { + +declare const fn: lambda.Function; +const alias = new lambda.Alias(this, 'Alias', { aliasName: 'prod', version: fn.latestVersion, }); // Create AutoScaling target -const as = alias.addAutoScaling({ maxCapacity: 50 }) +const as = alias.addAutoScaling({ maxCapacity: 50 }); // Configure Target Tracking as.scaleOnUtilization({ @@ -591,12 +603,12 @@ const accessPoint = fileSystem.addAccessPoint('AccessPoint', { }, }); -const fn = new Function(this, 'MyLambda', { +const fn = new lambda.Function(this, 'MyLambda', { // mount the access point to /mnt/msg in the lambda runtime environment - filesystem: FileSystem.fromEfsAccessPoint(accessPoint, '/mnt/msg'), - runtime: Runtime.NODEJS_12_X, + filesystem: lambda.FileSystem.fromEfsAccessPoint(accessPoint, '/mnt/msg'), + runtime: lambda.Runtime.NODEJS_12_X, handler: 'index.handler', - code: Code.fromAsset(path.join(__dirname, 'lambda-handler')), + code: lambda.Code.fromAsset(path.join(__dirname, 'lambda-handler')), vpc, }); ``` @@ -626,17 +638,17 @@ Docker container is responsible for putting content at `/asset-output`. The cont Example with Python: ```ts -new Function(this, 'Function', { - code: Code.fromAsset(path.join(__dirname, 'my-python-handler'), { +new lambda.Function(this, 'Function', { + code: lambda.Code.fromAsset(path.join(__dirname, 'my-python-handler'), { bundling: { - image: Runtime.PYTHON_3_9.bundlingImage, + image: lambda.Runtime.PYTHON_3_9.bundlingImage, command: [ 'bash', '-c', 'pip install -r requirements.txt -t /asset-output && cp -au . /asset-output' ], }, }), - runtime: Runtime.PYTHON_3_9, + runtime: lambda.Runtime.PYTHON_3_9, handler: 'index.handler', }); ``` @@ -647,12 +659,10 @@ Use `cdk.DockerImage.fromRegistry(image)` to use an existing image or `cdk.DockerImage.fromBuild(path)` to build a specific image: ```ts -import * as cdk from '@aws-cdk/core'; - -new Function(this, 'Function', { - code: Code.fromAsset('/path/to/handler', { +new lambda.Function(this, 'Function', { + code: lambda.Code.fromAsset('/path/to/handler', { bundling: { - image: cdk.DockerImage.fromBuild('/path/to/dir/with/DockerFile', { + image: DockerImage.fromBuild('/path/to/dir/with/DockerFile', { buildArgs: { ARG1: 'value1', }, @@ -660,7 +670,7 @@ new Function(this, 'Function', { command: ['my', 'cool', 'command'], }, }), - runtime: Runtime.PYTHON_3_9, + runtime: lambda.Runtime.PYTHON_3_9, handler: 'index.handler', }); ``` @@ -679,21 +689,21 @@ When enabled, AWS Lambda checks every code deployment and verifies that the code For more information, see [Configuring code signing for AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/configuration-codesigning.html). The following code configures a function with code signing. -```typescript +```ts import * as signer from '@aws-cdk/aws-signer'; const signingProfile = new signer.SigningProfile(this, 'SigningProfile', { - platform: signer.Platform.AWS_LAMBDA_SHA384_ECDSA + platform: signer.Platform.AWS_LAMBDA_SHA384_ECDSA, }); -const codeSigningConfig = new CodeSigningConfig(this, 'CodeSigningConfig', { +const codeSigningConfig = new lambda.CodeSigningConfig(this, 'CodeSigningConfig', { signingProfiles: [signingProfile], }); -new Function(this, 'Function', { +new lambda.Function(this, 'Function', { codeSigningConfig, - runtime: Runtime.NODEJS_12_X, + runtime: lambda.Runtime.NODEJS_12_X, handler: 'index.handler', - code: Code.fromAsset(path.join(__dirname, 'lambda-handler')), + code: lambda.Code.fromAsset(path.join(__dirname, 'lambda-handler')), }); ``` diff --git a/packages/@aws-cdk/aws-lambda/rosetta/default.ts-fixture b/packages/@aws-cdk/aws-lambda/rosetta/default.ts-fixture index 417454806bb9d..f473db8d31bd5 100644 --- a/packages/@aws-cdk/aws-lambda/rosetta/default.ts-fixture +++ b/packages/@aws-cdk/aws-lambda/rosetta/default.ts-fixture @@ -1,7 +1,9 @@ // Fixture with packages imported, but nothing else import * as path from 'path'; -import { Construct, Stack } from '@aws-cdk/core'; -import { Alias, Code, CodeSigningConfig, DockerImageCode, DockerImageFunction, FileSystem, Function, LayerVersion, Runtime, Tracing } from '@aws-cdk/aws-lambda'; +import { Construct } from 'constructs'; +import { DockerImage, RemovalPolicy, Stack } from '@aws-cdk/core'; +import * as lambda from '@aws-cdk/aws-lambda'; +import * as iam from '@aws-cdk/aws-iam'; class Fixture extends Stack { constructor(scope: Construct, id: string) { diff --git a/packages/@aws-cdk/aws-lambda/rosetta/function.ts-fixture b/packages/@aws-cdk/aws-lambda/rosetta/function.ts-fixture deleted file mode 100644 index 91eafe0abfcc0..0000000000000 --- a/packages/@aws-cdk/aws-lambda/rosetta/function.ts-fixture +++ /dev/null @@ -1,18 +0,0 @@ -// Fixture with function (`fn`) already created -import * as path from 'path'; -import { Construct, Stack } from '@aws-cdk/core'; -import { Alias, Code, Function, Runtime } from '@aws-cdk/aws-lambda'; - -class Fixture extends Stack { - constructor(scope: Construct, id: string) { - super(scope, id); - - const fn = new Function(this, 'MyFunction', { - runtime: Runtime.NODEJS_12_X, - handler: 'index.handler', - code: Code.fromAsset(path.join(__dirname, 'lambda-handler')), - }); - - /// here - } -} From 029eed9c8341545e090ec48ee97b47d25f4c3c56 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Thu, 28 Oct 2021 04:44:23 +0200 Subject: [PATCH 67/87] chore: upgrade to jsii 1.41 (#17190) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- package.json | 8 +- packages/awslint/package.json | 4 +- packages/decdk/package.json | 4 +- tools/@aws-cdk/cdk-build-tools/package.json | 6 +- yarn.lock | 162 ++++++++------------ 5 files changed, 74 insertions(+), 110 deletions(-) diff --git a/package.json b/package.json index 6115ddc36950c..7a521b7db98e1 100644 --- a/package.json +++ b/package.json @@ -20,10 +20,10 @@ "fs-extra": "^9.1.0", "graceful-fs": "^4.2.8", "jest-junit": "^12.3.0", - "jsii-diff": "^1.40.0", - "jsii-pacmak": "^1.40.0", - "jsii-reflect": "^1.40.0", - "jsii-rosetta": "^1.40.0", + "jsii-diff": "^1.41.0", + "jsii-pacmak": "^1.41.0", + "jsii-reflect": "^1.41.0", + "jsii-rosetta": "^1.41.0", "lerna": "^4.0.0", "patch-package": "^6.4.7", "standard-version": "^9.3.1", diff --git a/packages/awslint/package.json b/packages/awslint/package.json index 1bae6a09ba6cb..df07c732685ef 100644 --- a/packages/awslint/package.json +++ b/packages/awslint/package.json @@ -18,11 +18,11 @@ "awslint": "bin/awslint" }, "dependencies": { - "@jsii/spec": "^1.40.0", + "@jsii/spec": "^1.41.0", "camelcase": "^6.2.0", "colors": "^1.4.0", "fs-extra": "^9.1.0", - "jsii-reflect": "^1.40.0", + "jsii-reflect": "^1.41.0", "yargs": "^16.2.0" }, "devDependencies": { diff --git a/packages/decdk/package.json b/packages/decdk/package.json index 6a0a0eb5c0baa..7ebd9cc3d632c 100644 --- a/packages/decdk/package.json +++ b/packages/decdk/package.json @@ -244,7 +244,7 @@ "@aws-cdk/region-info": "0.0.0", "constructs": "^3.3.69", "fs-extra": "^9.1.0", - "jsii-reflect": "^1.40.0", + "jsii-reflect": "^1.41.0", "jsonschema": "^1.4.0", "yaml": "1.10.2", "yargs": "^16.2.0" @@ -255,7 +255,7 @@ "@types/yaml": "1.9.7", "@types/yargs": "^15.0.14", "jest": "^26.6.3", - "jsii": "^1.40.0" + "jsii": "^1.41.0" }, "keywords": [ "aws", diff --git a/tools/@aws-cdk/cdk-build-tools/package.json b/tools/@aws-cdk/cdk-build-tools/package.json index c8dfb507afc46..a99a32059c006 100644 --- a/tools/@aws-cdk/cdk-build-tools/package.json +++ b/tools/@aws-cdk/cdk-build-tools/package.json @@ -56,9 +56,9 @@ "fs-extra": "^9.1.0", "jest": "^27.3.1", "jest-junit": "^11.1.0", - "jsii": "^1.40.0", - "jsii-pacmak": "^1.40.0", - "jsii-reflect": "^1.40.0", + "jsii": "^1.41.0", + "jsii-pacmak": "^1.41.0", + "jsii-reflect": "^1.41.0", "markdownlint-cli": "^0.29.0", "nyc": "^15.1.0", "semver": "^7.3.5", diff --git a/yarn.lock b/yarn.lock index c63b92155ae6a..48ecde5d6ee28 100644 --- a/yarn.lock +++ b/yarn.lock @@ -760,10 +760,18 @@ chalk "^4.1.2" semver "^7.3.5" -"@jsii/spec@^1.40.0": - version "1.40.0" - resolved "https://registry.npmjs.org/@jsii/spec/-/spec-1.40.0.tgz#027dd2a9c2c0b49e5974ad6445728dde91569fe3" - integrity sha512-SJ9Kwz0C53bomYWb5PlESt6v8JmfgqqFjc1annNK+foHxcaUzs3trhKbBXgxhcoApE2pMnUIBj3DG9gLNmKdWw== +"@jsii/check-node@1.41.0": + version "1.41.0" + resolved "https://registry.npmjs.org/@jsii/check-node/-/check-node-1.41.0.tgz#17b6895e1fcc0b8bbb8fa81b52b17c47c9c47674" + integrity sha512-lV/vMK1HZQcUye2vXPu6XsmnTk7fEui0GnQsPAX1eLWfRMkxkRblT4VZ9DQTYjMno2HuVP4IH51fiFoICMmnkA== + dependencies: + chalk "^4.1.2" + semver "^7.3.5" + +"@jsii/spec@^1.41.0": + version "1.41.0" + resolved "https://registry.npmjs.org/@jsii/spec/-/spec-1.41.0.tgz#d504c8536139a97986b1ec63201d3575972e1e9c" + integrity sha512-sN7x6C0DGLngiO6SkrM/7gVaHyeja59bDZODZtBXIq8kBIC+GgAFS8P0s1e5FpU9mHHvvHq4rvzvcIbxw0nkXw== dependencies: jsonschema "^1.4.0" @@ -2250,11 +2258,6 @@ ansi-regex@^2.0.0: resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= - ansi-regex@^4.1.0: version "4.1.0" resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" @@ -3078,11 +3081,6 @@ co@^4.6.0: resolved "https://registry.npmjs.org/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= - codemaker@^1.39.0: version "1.39.0" resolved "https://registry.npmjs.org/codemaker/-/codemaker-1.39.0.tgz#d8103f4b587210b1d6aa073d62ffb510ac20bc42" @@ -3092,10 +3090,10 @@ codemaker@^1.39.0: decamelize "^5.0.1" fs-extra "^9.1.0" -codemaker@^1.40.0: - version "1.40.0" - resolved "https://registry.npmjs.org/codemaker/-/codemaker-1.40.0.tgz#80ed75a433fb08976c602b9080dc7fffbb13dbb9" - integrity sha512-X0dMlXILO5r9/YhNAbiLl9kNIfhATfGS8nAT7xC09zREipANnCEbjZuF8jtFGzrD942/k5QNROmqRtqRaZJ1QQ== +codemaker@^1.41.0: + version "1.41.0" + resolved "https://registry.npmjs.org/codemaker/-/codemaker-1.41.0.tgz#814edff6ffd241727794e76f81c5f9e4df135162" + integrity sha512-Iow0udcpshcVmztwSSJDTRhJxTbH0nXU3pxf7iF0gv6+BWC5Nd2aWQ2W5rHECySQPIvmWn4KEpV/SvXgvfl0aA== dependencies: camelcase "^6.2.0" decamelize "^5.0.1" @@ -5536,18 +5534,6 @@ is-extglob@^2.1.1: resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= - dependencies: - number-is-nan "^1.0.0" - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= - is-fullwidth-code-point@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" @@ -6706,70 +6692,72 @@ jsesc@^2.5.1: resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== -jsii-diff@^1.40.0: - version "1.40.0" - resolved "https://registry.npmjs.org/jsii-diff/-/jsii-diff-1.40.0.tgz#97668273bc6c7f8ea6c6c27ebd8d70d433e1208d" - integrity sha512-Q0ctTmPE3wZ03CP++MxjPMBV3ynonDHq1gsd5mFUk9DW+cTyKb78KUkyjhgQnuiehXLRDQtoTlWJkH9C5xhEnQ== +jsii-diff@^1.41.0: + version "1.41.0" + resolved "https://registry.npmjs.org/jsii-diff/-/jsii-diff-1.41.0.tgz#ef88aa98081e4bb41f13d24074fce9bee1574d24" + integrity sha512-LTfqGh0f0fUuWu8DBkEUgl0fteIBfzyEiExcqLBXbztg/8JRbt3DYUr63hHULJj4O/rnRTaaYNH7oT1sg4gpSQ== dependencies: - "@jsii/check-node" "1.40.0" - "@jsii/spec" "^1.40.0" + "@jsii/check-node" "1.41.0" + "@jsii/spec" "^1.41.0" fs-extra "^9.1.0" - jsii-reflect "^1.40.0" + jsii-reflect "^1.41.0" log4js "^6.3.0" typescript "~3.9.10" yargs "^16.2.0" -jsii-pacmak@^1.40.0: - version "1.40.0" - resolved "https://registry.npmjs.org/jsii-pacmak/-/jsii-pacmak-1.40.0.tgz#5c0ecd5ff9c0917931bbe66773402dfe5517fbec" - integrity sha512-8IyvvWiD2eUpVhw0WXrYJILz+NSeNEwcWfQB+fUmn2gL8q27hlPZhHE7BVlr8+rb+EJVVLeHmpAMgA/SF9g/vQ== +jsii-pacmak@^1.41.0: + version "1.41.0" + resolved "https://registry.npmjs.org/jsii-pacmak/-/jsii-pacmak-1.41.0.tgz#b94575f4a7c658d3fbd1c5f30876ce53a22ed126" + integrity sha512-B3ohEObc2xSnWoawK0q4qVkxa9Dh4A+x1y9K31AAS5jGbhdjbdS/FfphlUbukIoSR0NBJLgJg9pT+h/PIlUqdA== dependencies: - "@jsii/check-node" "1.40.0" - "@jsii/spec" "^1.40.0" + "@jsii/check-node" "1.41.0" + "@jsii/spec" "^1.41.0" clone "^2.1.2" - codemaker "^1.40.0" + codemaker "^1.41.0" commonmark "^0.30.0" escape-string-regexp "^4.0.0" fs-extra "^9.1.0" - jsii-reflect "^1.40.0" - jsii-rosetta "^1.40.0" + jsii-reflect "^1.41.0" + jsii-rosetta "^1.41.0" semver "^7.3.5" spdx-license-list "^6.4.0" xmlbuilder "^15.1.1" yargs "^16.2.0" -jsii-reflect@^1.40.0: - version "1.40.0" - resolved "https://registry.npmjs.org/jsii-reflect/-/jsii-reflect-1.40.0.tgz#f8715f1506059d49294b32fe2c710753dd9545ba" - integrity sha512-/ccIjkRSfbHCl1MCfwWFaz2RjoAAiNH5teE95Qi11a4gbTu52WcOFIg3Y+8llzHmmLykr9jTDqBtgyzi9WI6dw== +jsii-reflect@^1.41.0: + version "1.41.0" + resolved "https://registry.npmjs.org/jsii-reflect/-/jsii-reflect-1.41.0.tgz#3c8fbcbbb7e2853b7c2a59384524ccbd2d9d832c" + integrity sha512-KQaAXQ38hyREs7IuBChZldSyvW1gezHRezGKGc6BZILwlIX330F3GIauJ2rJKJinh/Lo/DlMfd0k1mxdBz/W9A== dependencies: - "@jsii/check-node" "1.40.0" - "@jsii/spec" "^1.40.0" + "@jsii/check-node" "1.41.0" + "@jsii/spec" "^1.41.0" colors "^1.4.0" fs-extra "^9.1.0" - oo-ascii-tree "^1.40.0" + oo-ascii-tree "^1.41.0" yargs "^16.2.0" -jsii-rosetta@^1.40.0: - version "1.40.0" - resolved "https://registry.npmjs.org/jsii-rosetta/-/jsii-rosetta-1.40.0.tgz#eff34919ed9d4193ddb4a684f6108c82db3feb7c" - integrity sha512-Gb257CdUbHV8ZRFYflZy7F7alH5X49T+pX2133F7eaoMpRqc0V6jQsphaL4V+S/jK29XOfXtANmq55AvmwsWLQ== +jsii-rosetta@^1.41.0: + version "1.41.0" + resolved "https://registry.npmjs.org/jsii-rosetta/-/jsii-rosetta-1.41.0.tgz#ddf3f49738489d8330aa4eff96f0a9c8c811792d" + integrity sha512-wSjMqRBhjBKB8kx+gIXE7YXoiOlTFH/ugksHz2K4UwqriPmEHue8b7LkV3d/mD8xuhXWS6ekGAz67Gd1RSB7Sg== dependencies: - "@jsii/check-node" "1.40.0" - "@jsii/spec" "^1.40.0" + "@jsii/check-node" "1.41.0" + "@jsii/spec" "^1.41.0" "@xmldom/xmldom" "^0.7.5" commonmark "^0.30.0" fs-extra "^9.1.0" + sort-json "^2.0.0" typescript "~3.9.10" + workerpool "^6.1.5" yargs "^16.2.0" -jsii@^1.40.0: - version "1.40.0" - resolved "https://registry.npmjs.org/jsii/-/jsii-1.40.0.tgz#cc04f2bad5ae9495513af921cfcaca99dc8753d3" - integrity sha512-QUPmQzq7c/FREvtfw9+eIU16LB45hxRPtdLO2Ci2ZX1df4E4+vegtfvvjUJ21diVo2hwVp4UCftKqrXZ/cXEFg== +jsii@^1.41.0: + version "1.41.0" + resolved "https://registry.npmjs.org/jsii/-/jsii-1.41.0.tgz#926e033d7ba57c65d6d070dee1d4d19da0fa9508" + integrity sha512-5pjfWjSaMzE+mkpW//llBSGLcXJGNjE0KFSf73USPZTfJC09dBEJ4KJM85SogCNnWHwG5QecEpZStxNvt8GI7g== dependencies: - "@jsii/check-node" "1.40.0" - "@jsii/spec" "^1.40.0" + "@jsii/check-node" "1.41.0" + "@jsii/spec" "^1.41.0" case "^1.6.3" colors "^1.4.0" deep-equal "^2.0.5" @@ -7972,11 +7960,6 @@ null-check@^1.0.0: resolved "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz#977dffd7176012b9ec30d2a39db5cf72a0439edd" integrity sha1-l33/1xdgErnsMNKjnbXPcqBDnt0= -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= - nwsapi@^2.2.0: version "2.2.0" resolved "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" @@ -8113,10 +8096,10 @@ onetime@^5.1.0, onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" -oo-ascii-tree@^1.40.0: - version "1.40.0" - resolved "https://registry.npmjs.org/oo-ascii-tree/-/oo-ascii-tree-1.40.0.tgz#69005b8f5f140ed23a81e90b3659750dc3a62522" - integrity sha512-nkiEc8TJZwGxPdEB1jRxHWyc/qBTPQSf70KhO+WjuiWzVfLVEWF/dksWRjm8e510YmPrBjfYCJOn+BVlOUojSQ== +oo-ascii-tree@^1.41.0: + version "1.41.0" + resolved "https://registry.npmjs.org/oo-ascii-tree/-/oo-ascii-tree-1.41.0.tgz#88883d2b8446ded7082a96faf3294e1092aeeb46" + integrity sha512-WxQIFO+JMCIJBlIMUATsp+PW5kqDMy2CD7u5uC9qQk29XInUMO+RN7/QVZJsPHO3o73eJFN9CFc9XDWQJwVKBQ== open@^7.4.2: version "7.4.2" @@ -9599,7 +9582,7 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -string-width@*, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +string-width@*, string-width@^1.0.1, "string-width@^1.0.2 || 2", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -9608,23 +9591,6 @@ string-width@*, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string-width@^1.0.1: - version "1.0.2" - resolved "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - -"string-width@^1.0.2 || 2": - version "2.1.1" - resolved "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - string.prototype.repeat@^0.2.0: version "0.2.0" resolved "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-0.2.0.tgz#aba36de08dcee6a5a337d49b2ea1da1b28fc0ecf" @@ -9677,13 +9643,6 @@ strip-ansi@^3.0.0, strip-ansi@^3.0.1: dependencies: ansi-regex "^2.0.0" -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= - dependencies: - ansi-regex "^3.0.0" - strip-ansi@^5.2.0: version "5.2.0" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" @@ -10540,6 +10499,11 @@ wordwrap@>=0.0.2, wordwrap@^1.0.0: resolved "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= +workerpool@^6.1.5: + version "6.1.5" + resolved "https://registry.npmjs.org/workerpool/-/workerpool-6.1.5.tgz#0f7cf076b6215fd7e1da903ff6f22ddd1886b581" + integrity sha512-XdKkCK0Zqc6w3iTxLckiuJ81tiD/o5rBE/m+nXpRCB+/Sq4DqkfXZ/x0jW02DG1tGsfUGXbTJyZDP+eu67haSw== + wrap-ansi@^6.2.0: version "6.2.0" resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" From 5cee43e73a836addf5554d74c617f543a450249d Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Thu, 28 Oct 2021 05:41:35 +0200 Subject: [PATCH 68/87] chore: activate 'rosetta infuse' feature (#17191) `jsii-rosetta infuse` will modify all the assemblies in-place to add examples to types that don't have examples yet. This feature depends on jsii 1.41, and should not be merged before jsii has been upgraded to that version (either by #17187 or by #17190). Depends-On: #17190 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- pack.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pack.sh b/pack.sh index 168a17f972406..3c2d7dbce6c1a 100755 --- a/pack.sh +++ b/pack.sh @@ -39,12 +39,17 @@ function lerna_scopes() { # Compile examples with respect to "decdk" directory, as all packages will # be symlinked there so they can all be included. echo "Extracting code samples" >&2 -node --experimental-worker $(which $ROSETTA) \ +$ROSETTA extract \ --compile \ --output samples.tabl.json \ --directory packages/decdk \ $(cat $TMPDIR/jsii.txt) +echo "Infusing examples back into assemblies" >&2 +$ROSETTA infuse \ + samples.tabl.json \ + $(cat $TMPDIR/jsii.txt) + # Jsii packaging (all at once using jsii-pacmak) echo "Packaging jsii modules" >&2 $PACMAK \ From 758568007bf82a97ed6edba3ef4717735b224bf9 Mon Sep 17 00:00:00 2001 From: Kyle Roach Date: Thu, 28 Oct 2021 04:34:47 +0000 Subject: [PATCH 69/87] feat(codebuild): add fromEcrRepository to LinuxGpuBuildImage (#17170) Resolves #16500 ---- *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-codebuild/README.md | 2 + .../lib/linux-gpu-build-image.ts | 16 ++ .../test/linux-gpu-build-image.test.ts | 174 ++++++++++++++++++ packages/@aws-cdk/aws-ecr/lib/repository.ts | 4 +- 4 files changed, 195 insertions(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-codebuild/README.md b/packages/@aws-cdk/aws-codebuild/README.md index ff73599bca8e4..8a5fa30ac408b 100644 --- a/packages/@aws-cdk/aws-codebuild/README.md +++ b/packages/@aws-cdk/aws-codebuild/README.md @@ -320,6 +320,8 @@ new codebuild.Project(this, 'Project', { }) ``` +Alternatively, you can reference an image available in an ECR repository using the `LinuxGpuBuildImage.fromEcrRepository(repo[, tag])` method. + ## Logs CodeBuild lets you specify an S3 Bucket, CloudWatch Log Group or both to receive logs from your projects. diff --git a/packages/@aws-cdk/aws-codebuild/lib/linux-gpu-build-image.ts b/packages/@aws-cdk/aws-codebuild/lib/linux-gpu-build-image.ts index 6cbf5bcfc2f7e..b26611745afbb 100644 --- a/packages/@aws-cdk/aws-codebuild/lib/linux-gpu-build-image.ts +++ b/packages/@aws-cdk/aws-codebuild/lib/linux-gpu-build-image.ts @@ -91,6 +91,22 @@ export class LinuxGpuBuildImage implements IBindableBuildImage { return new LinuxGpuBuildImage(repositoryName, tag, account); } + + /** + * Returns a GPU image running Linux from an ECR repository. + * + * NOTE: if the repository is external (i.e. imported), then we won't be able to add + * a resource policy statement for it so CodeBuild can pull the image. + * + * @see https://docs.aws.amazon.com/codebuild/latest/userguide/sample-ecr.html + * + * @param repository The ECR repository + * @param tag Image tag (default "latest") + */ + public static fromEcrRepository(repository: ecr.IRepository, tag: string = 'latest'): IBuildImage { + return new LinuxGpuBuildImage(repository.repositoryName, tag, repository.env.account); + } + public readonly type = 'LINUX_GPU_CONTAINER'; public readonly defaultComputeType = ComputeType.LARGE; public readonly imageId: string; diff --git a/packages/@aws-cdk/aws-codebuild/test/linux-gpu-build-image.test.ts b/packages/@aws-cdk/aws-codebuild/test/linux-gpu-build-image.test.ts index 7e32ab033c68c..d3b0d44dde984 100644 --- a/packages/@aws-cdk/aws-codebuild/test/linux-gpu-build-image.test.ts +++ b/packages/@aws-cdk/aws-codebuild/test/linux-gpu-build-image.test.ts @@ -1,5 +1,6 @@ import { arrayWith, objectLike } from '@aws-cdk/assert-internal'; import '@aws-cdk/assert-internal/jest'; +import * as ecr from '@aws-cdk/aws-ecr'; import * as cdk from '@aws-cdk/core'; import * as codebuild from '../lib'; @@ -58,4 +59,177 @@ describe('Linux GPU build image', () => { }); }); }); + + describe('ECR Repository', () => { + test('allows creating a build image from a new ECR repository', () => { + const stack = new cdk.Stack(); + + const repository = new ecr.Repository(stack, 'my-repo'); + + new codebuild.Project(stack, 'Project', { + buildSpec: codebuild.BuildSpec.fromObject({ + version: '0.2', + phases: { + build: { commands: ['ls'] }, + }, + }), + environment: { + buildImage: codebuild.LinuxGpuBuildImage.fromEcrRepository(repository, 'v1'), + }, + }); + + expect(stack).toHaveResourceLike('AWS::CodeBuild::Project', { + Environment: { + ComputeType: 'BUILD_GENERAL1_LARGE', + Image: { + 'Fn::Join': ['', [ + { Ref: 'AWS::AccountId' }, + '.dkr.ecr.', + { Ref: 'AWS::Region' }, + '.', + { Ref: 'AWS::URLSuffix' }, + '/', + { Ref: 'myrepo5DFA62E5' }, + ':v1', + ]], + }, + }, + }); + + expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + PolicyDocument: { + Statement: arrayWith(objectLike({ + Action: [ + 'ecr:BatchCheckLayerAvailability', + 'ecr:GetDownloadUrlForLayer', + 'ecr:BatchGetImage', + ], + Resource: { + 'Fn::Join': ['', [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':ecr:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':repository/', + { Ref: 'myrepo5DFA62E5' }, + ]], + }, + })), + }, + }); + }); + + test('allows creating a build image from an existing ECR repository', () => { + const stack = new cdk.Stack(); + + const repository = ecr.Repository.fromRepositoryName(stack, 'my-imported-repo', 'test-repo'); + + new codebuild.Project(stack, 'Project', { + buildSpec: codebuild.BuildSpec.fromObject({ + version: '0.2', + phases: { + build: { commands: ['ls'] }, + }, + }), + environment: { + buildImage: codebuild.LinuxGpuBuildImage.fromEcrRepository(repository), + }, + }); + + expect(stack).toHaveResourceLike('AWS::CodeBuild::Project', { + Environment: { + ComputeType: 'BUILD_GENERAL1_LARGE', + Image: { + 'Fn::Join': ['', [ + { Ref: 'AWS::AccountId' }, + '.dkr.ecr.', + { Ref: 'AWS::Region' }, + '.', + { Ref: 'AWS::URLSuffix' }, + '/test-repo:latest', + ]], + }, + }, + }); + + expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + PolicyDocument: { + Statement: arrayWith(objectLike({ + Action: [ + 'ecr:BatchCheckLayerAvailability', + 'ecr:GetDownloadUrlForLayer', + 'ecr:BatchGetImage', + ], + Resource: { + 'Fn::Join': ['', [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':ecr:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':repository/test-repo', + ]], + }, + })), + }, + }); + }); + + test('allows creating a build image from an existing cross-account ECR repository', () => { + const stack = new cdk.Stack(); + + const repository = ecr.Repository.fromRepositoryArn(stack, 'my-cross-acount-repo', 'arn:aws:ecr:us-east-1:585695036304:repository/foo/bar/foo/fooo'); + + new codebuild.Project(stack, 'Project', { + buildSpec: codebuild.BuildSpec.fromObject({ + version: '0.2', + phases: { + build: { commands: ['ls'] }, + }, + }), + environment: { + buildImage: codebuild.LinuxGpuBuildImage.fromEcrRepository(repository), + }, + }); + + expect(stack).toHaveResourceLike('AWS::CodeBuild::Project', { + Environment: { + ComputeType: 'BUILD_GENERAL1_LARGE', + Image: { + 'Fn::Join': ['', [ + '585695036304.dkr.ecr.', + { Ref: 'AWS::Region' }, + '.', + { Ref: 'AWS::URLSuffix' }, + '/foo/bar/foo/fooo:latest', + ]], + }, + }, + }); + + expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + PolicyDocument: { + Statement: arrayWith(objectLike({ + Action: [ + 'ecr:BatchCheckLayerAvailability', + 'ecr:GetDownloadUrlForLayer', + 'ecr:BatchGetImage', + ], + Resource: { + 'Fn::Join': ['', [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':ecr:', + { Ref: 'AWS::Region' }, + ':585695036304:repository/foo/bar/foo/fooo', + ]], + }, + })), + }, + }); + }); + }); }); diff --git a/packages/@aws-cdk/aws-ecr/lib/repository.ts b/packages/@aws-cdk/aws-ecr/lib/repository.ts index af8547ba5edaf..0511290e113a5 100644 --- a/packages/@aws-cdk/aws-ecr/lib/repository.ts +++ b/packages/@aws-cdk/aws-ecr/lib/repository.ts @@ -411,7 +411,9 @@ export class Repository extends RepositoryBase { } } - return new Import(scope, id); + return new Import(scope, id, { + environmentFromArn: repositoryArn, + }); } public static fromRepositoryName(scope: Construct, id: string, repositoryName: string): IRepository { From 1f570e84e48e157b36d84bfb8434e50484d7f3e2 Mon Sep 17 00:00:00 2001 From: Madeline Kusters <80541297+madeline-k@users.noreply.github.com> Date: Wed, 27 Oct 2021 22:28:55 -0700 Subject: [PATCH 70/87] chore(aws-applicationautoscaling): add unit tests to increase branch coverage (#17173) increasing branch coverage from 74/75% to 80% ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../test/scalable-target.test.ts | 107 +++++++++++++++--- .../test/{cron.test.ts => schedule.test.ts} | 15 +++ 2 files changed, 105 insertions(+), 17 deletions(-) rename packages/@aws-cdk/aws-applicationautoscaling/test/{cron.test.ts => schedule.test.ts} (79%) diff --git a/packages/@aws-cdk/aws-applicationautoscaling/test/scalable-target.test.ts b/packages/@aws-cdk/aws-applicationautoscaling/test/scalable-target.test.ts index 8628a8624468c..508ae3bb2c9e2 100644 --- a/packages/@aws-cdk/aws-applicationautoscaling/test/scalable-target.test.ts +++ b/packages/@aws-cdk/aws-applicationautoscaling/test/scalable-target.test.ts @@ -1,5 +1,6 @@ import '@aws-cdk/assert-internal/jest'; import * as cloudwatch from '@aws-cdk/aws-cloudwatch'; +import * as iam from '@aws-cdk/aws-iam'; import * as cdk from '@aws-cdk/core'; import * as appscaling from '../lib'; import { createScalableTarget } from './util'; @@ -26,8 +27,6 @@ describe('scalable target', () => { MinCapacity: 1, MaxCapacity: 20, }); - - }); test('validation does not fail when using Tokens', () => { @@ -51,8 +50,6 @@ describe('scalable target', () => { MinCapacity: 10, MaxCapacity: 1, }); - - }); test('add scheduled scaling', () => { @@ -80,8 +77,6 @@ describe('scalable target', () => { }, ], }); - - }); test('step scaling on MathExpression', () => { @@ -136,21 +131,99 @@ describe('scalable target', () => { ], Threshold: 49, }); + }); + test('test service namespace enum', () => { + expect(appscaling.ServiceNamespace.APPSTREAM).toEqual('appstream'); + expect(appscaling.ServiceNamespace.COMPREHEND).toEqual('comprehend'); + expect(appscaling.ServiceNamespace.CUSTOM_RESOURCE).toEqual('custom-resource'); + expect(appscaling.ServiceNamespace.DYNAMODB).toEqual('dynamodb'); + expect(appscaling.ServiceNamespace.EC2).toEqual('ec2'); + expect(appscaling.ServiceNamespace.ECS).toEqual('ecs'); + expect(appscaling.ServiceNamespace.ELASTIC_MAP_REDUCE).toEqual('elasticmapreduce'); + expect(appscaling.ServiceNamespace.LAMBDA).toEqual('lambda'); + expect(appscaling.ServiceNamespace.RDS).toEqual('rds'); + expect(appscaling.ServiceNamespace.SAGEMAKER).toEqual('sagemaker'); + }); + test('create scalable target with negative minCapacity throws error', () => { + const stack = new cdk.Stack(); + expect(() => { + new appscaling.ScalableTarget(stack, 'Target', { + serviceNamespace: appscaling.ServiceNamespace.DYNAMODB, + scalableDimension: 'test:TestCount', + resourceId: 'test:this/test', + minCapacity: -1, + maxCapacity: 20, + }); + }).toThrow('minCapacity cannot be negative, got: -1'); }); - test('test service namespace enum', () => { - expect(appscaling.ServiceNamespace.APPSTREAM).toEqual( 'appstream'); - expect(appscaling.ServiceNamespace.COMPREHEND).toEqual( 'comprehend'); - expect(appscaling.ServiceNamespace.CUSTOM_RESOURCE).toEqual( 'custom-resource'); - expect(appscaling.ServiceNamespace.DYNAMODB).toEqual( 'dynamodb'); - expect(appscaling.ServiceNamespace.EC2).toEqual( 'ec2'); - expect(appscaling.ServiceNamespace.ECS).toEqual( 'ecs'); - expect(appscaling.ServiceNamespace.ELASTIC_MAP_REDUCE).toEqual( 'elasticmapreduce'); - expect(appscaling.ServiceNamespace.LAMBDA).toEqual( 'lambda'); - expect(appscaling.ServiceNamespace.RDS).toEqual( 'rds'); - expect(appscaling.ServiceNamespace.SAGEMAKER).toEqual( 'sagemaker'); + test('create scalable target with negative maxCapacity throws error', () => { + const stack = new cdk.Stack(); + expect(() => { + new appscaling.ScalableTarget(stack, 'Target', { + serviceNamespace: appscaling.ServiceNamespace.DYNAMODB, + scalableDimension: 'test:TestCount', + resourceId: 'test:this/test', + minCapacity: 1, + maxCapacity: -1, + }); + }).toThrow('maxCapacity cannot be negative, got: -1'); + }); + + test('create scalable target with maxCapacity less than minCapacity throws error', () => { + const stack = new cdk.Stack(); + expect(() => { + new appscaling.ScalableTarget(stack, 'Target', { + serviceNamespace: appscaling.ServiceNamespace.DYNAMODB, + scalableDimension: 'test:TestCount', + resourceId: 'test:this/test', + minCapacity: 2, + maxCapacity: 1, + }); + }).toThrow('minCapacity (2) should be lower than maxCapacity (1)'); + }); + test('create scalable target with custom role', () => { + // GIVEN + const stack = new cdk.Stack(); + + // WHEN + new appscaling.ScalableTarget(stack, 'Target', { + serviceNamespace: appscaling.ServiceNamespace.DYNAMODB, + scalableDimension: 'test:TestCount', + resourceId: 'test:this/test', + minCapacity: 1, + maxCapacity: 20, + role: new iam.Role(stack, 'Role', { + assumedBy: new iam.ServicePrincipal('test.amazonaws.com'), + }), + }); + + // THEN + expect(stack).toHaveResource('AWS::ApplicationAutoScaling::ScalableTarget', { + ServiceNamespace: 'dynamodb', + ScalableDimension: 'test:TestCount', + ResourceId: 'test:this/test', + MinCapacity: 1, + MaxCapacity: 20, + RoleARN: { + 'Fn::GetAtt': [ + 'Role1ABCC5F0', + 'Arn', + ], + }, + }); + }); + + test('add scheduled scaling with neither of min/maxCapacity defined throws error', () => { + const stack = new cdk.Stack(); + const target = createScalableTarget(stack); + expect(() => { + target.scaleOnSchedule('ScaleUp', { + schedule: appscaling.Schedule.rate(cdk.Duration.minutes(1)), + }); + }).toThrow(/You must supply at least one of minCapacity or maxCapacity, got/); }); }); diff --git a/packages/@aws-cdk/aws-applicationautoscaling/test/cron.test.ts b/packages/@aws-cdk/aws-applicationautoscaling/test/schedule.test.ts similarity index 79% rename from packages/@aws-cdk/aws-applicationautoscaling/test/cron.test.ts rename to packages/@aws-cdk/aws-applicationautoscaling/test/schedule.test.ts index b3c337883146c..6583be41f97c5 100644 --- a/packages/@aws-cdk/aws-applicationautoscaling/test/cron.test.ts +++ b/packages/@aws-cdk/aws-applicationautoscaling/test/schedule.test.ts @@ -11,7 +11,9 @@ describe('cron', () => { expect(appscaling.Schedule.cron({ hour: '18', minute: '24' }).expressionString).toEqual('cron(24 18 * * ? *)'); }); +}); +describe('rate', () => { test('rate must be whole number of minutes', () => { expect(() => { appscaling.Schedule.rate(Duration.minutes(0.13456)); @@ -53,3 +55,16 @@ describe('cron', () => { }); }); + +describe('expression', () => { + test('test using a literal schedule expression', () => { + expect(appscaling.Schedule.expression('cron(0 18 * * ? *)').expressionString).toEqual('cron(0 18 * * ? *)'); + + }); +}); + +describe('at', () => { + test('test using at with a specific Date', () => { + expect(appscaling.Schedule.at(new Date(2021, 10, 26)).expressionString).toEqual('at(2021-11-26T00:00:00)'); + }); +}); From c4ba858278bffe1a987ea8200c313f17f7f1cbe9 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Thu, 28 Oct 2021 12:02:52 +0200 Subject: [PATCH 71/87] chore: revert activate 'rosetta infuse' feature (#17207) The examples we copy into docblocks may contain block comments themselves. However, the docblock renderer does not escape the docblock *closing* text, so the doc block gets terminated early and compiling fails: ```java /** * Initialization props for the `NestedStack` construct. *

* Example: *

*

{@code
 * // Example automatically generated. See https://github.com/aws/jsii/issues/826
 * import software.amazon.awscdk.core.App;
 * import software.amazon.awscdk.core.CfnOutput;
 * import software.amazon.awscdk.core.NestedStack;
 * import lib.RestApi;
 * import lib.Stage;
 * /**
 *  * This file showcases how to split up a RestApi's Resources and Methods across nested stacks.
 *  *
 *  * The root stack 'RootStack' first defines a RestApi.
 *  * Two nested stacks BooksStack and PetsStack, create corresponding Resources '/books' and '/pets'.
 *  * They are then deployed to a 'prod' Stage via a third nested stack - DeployStack.
 *  *
 *  * To verify this worked, go to the APIGateway
 *  */    <------------ OOOPS!
 * public class RootStack extends Stack {
 *     public RootStack(Construct scope) {
 *         super(scope, "integ-restapi-import-RootStack");
 *         RestApi restApi = RestApi.Builder.cre

```

Revert this until we can address the quoting issue.

Reverts aws/aws-cdk#17191
---
 pack.sh | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/pack.sh b/pack.sh
index 3c2d7dbce6c1a..168a17f972406 100755
--- a/pack.sh
+++ b/pack.sh
@@ -39,17 +39,12 @@ function lerna_scopes() {
 # Compile examples with respect to "decdk" directory, as all packages will
 # be symlinked there so they can all be included.
 echo "Extracting code samples" >&2
-$ROSETTA extract \
+node --experimental-worker $(which $ROSETTA) \
   --compile \
   --output samples.tabl.json \
   --directory packages/decdk \
   $(cat $TMPDIR/jsii.txt)
 
-echo "Infusing examples back into assemblies" >&2
-$ROSETTA infuse \
-  samples.tabl.json \
-  $(cat $TMPDIR/jsii.txt)
-
 # Jsii packaging (all at once using jsii-pacmak)
 echo "Packaging jsii modules" >&2
 $PACMAK \

From bc07cb0e383aa64280a9c7f8ac4870d296830cf7 Mon Sep 17 00:00:00 2001
From: Ryan Parker 
Date: Thu, 28 Oct 2021 04:10:15 -0700
Subject: [PATCH 72/87] feat(aws-route53-targets): Support for Elastic
 Beanstalk environment URLs (#16305)

## Summary

This PR adds a new Route53 target `ElasticBeanstalkEnvironmentTarget` for creating RecordSets that target Elastic Beanstalk environment URLs.

E.g.

```ts
const ebsEnvironmentUrl = 'mysampleenvironment.xyz.us-east-1.elasticbeanstalk.com';

new route53.ARecord(this, 'AliasRecord', {
	zone,
    target: route53.RecordTarget.fromAlias(new alias.ElasticBeanstalkEnvironmentTarget(ebsEnvironmentUrl)),
});
```

[How to find your Elastic Beanstalk environment URL](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-to-beanstalk-environment.html#routing-to-beanstalk-environment-get-domain-name)

Fixes: https://github.com/aws/aws-cdk/issues/3206


----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
---
 .../@aws-cdk/aws-route53-targets/README.md    | 11 +++++++
 .../elastic-beanstalk-environment-target.ts   | 33 +++++++++++++++++++
 .../@aws-cdk/aws-route53-targets/lib/index.ts |  1 +
 ...astic-beanstalk-environment-target.test.ts | 25 ++++++++++++++
 .../region-info/build-tools/fact-tables.ts    | 31 +++++++++++++++++
 .../build-tools/generate-static-data.ts       |  5 ++-
 packages/@aws-cdk/region-info/lib/fact.ts     |  5 +++
 .../@aws-cdk/region-info/lib/region-info.ts   |  7 ++++
 8 files changed, 117 insertions(+), 1 deletion(-)
 create mode 100644 packages/@aws-cdk/aws-route53-targets/lib/elastic-beanstalk-environment-target.ts
 create mode 100644 packages/@aws-cdk/aws-route53-targets/test/elastic-beanstalk-environment-target.test.ts

diff --git a/packages/@aws-cdk/aws-route53-targets/README.md b/packages/@aws-cdk/aws-route53-targets/README.md
index 07be5b2e363d0..6c703ad5adc8f 100644
--- a/packages/@aws-cdk/aws-route53-targets/README.md
+++ b/packages/@aws-cdk/aws-route53-targets/README.md
@@ -129,4 +129,15 @@ See [the Developer Guide](https://docs.aws.amazon.com/Route53/latest/DeveloperGu
   });
   ```
 
+* Elastic Beanstalk environment:
+
+**Important:** Only supports Elastic Beanstalk environments created after 2016 that have a regional endpoint.
+
+  ```ts
+  new route53.ARecord(this, 'AliasRecord', {
+    zone,
+    target: route53.RecordTarget.fromAlias(new alias.ElasticBeanstalkEnvironmentEndpointTarget(ebsEnvironmentUrl)),
+  });
+  ```
+
 See the documentation of `@aws-cdk/aws-route53` for more information.
diff --git a/packages/@aws-cdk/aws-route53-targets/lib/elastic-beanstalk-environment-target.ts b/packages/@aws-cdk/aws-route53-targets/lib/elastic-beanstalk-environment-target.ts
new file mode 100644
index 0000000000000..ef48c2845c233
--- /dev/null
+++ b/packages/@aws-cdk/aws-route53-targets/lib/elastic-beanstalk-environment-target.ts
@@ -0,0 +1,33 @@
+import * as route53 from '@aws-cdk/aws-route53';
+import * as cdk from '@aws-cdk/core';
+import { RegionInfo } from '@aws-cdk/region-info';
+
+/**
+ * Use an Elastic Beanstalk environment URL as an alias record target.
+ * E.g. mysampleenvironment.xyz.us-east-1.elasticbeanstalk.com
+ *
+ * Only supports Elastic Beanstalk environments created after 2016 that have a regional endpoint.
+ */
+export class ElasticBeanstalkEnvironmentEndpointTarget implements route53.IAliasRecordTarget {
+  constructor(private readonly environmentEndpoint: string) {
+  }
+
+  public bind(_record: route53.IRecordSet, _zone?: route53.IHostedZone): route53.AliasRecordTargetConfig {
+    if (cdk.Token.isUnresolved(this.environmentEndpoint)) {
+      throw new Error('Cannot use an EBS alias as `environmentEndpoint`. You must find your EBS environment endpoint via the AWS console. See the Elastic Beanstalk developer guide: https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/customdomains.html');
+    }
+
+    const dnsName = this.environmentEndpoint;
+    const region = cdk.Fn.select(2, cdk.Fn.split('.', dnsName));
+    const { ebsEnvEndpointHostedZoneId: hostedZoneId } = RegionInfo.get(region);
+
+    if (!hostedZoneId || !dnsName) {
+      throw new Error(`Elastic Beanstalk environment target is not supported for the "${region}" region.`);
+    }
+
+    return {
+      hostedZoneId,
+      dnsName,
+    };
+  }
+}
diff --git a/packages/@aws-cdk/aws-route53-targets/lib/index.ts b/packages/@aws-cdk/aws-route53-targets/lib/index.ts
index 92f1d9ee08d25..714719322b883 100644
--- a/packages/@aws-cdk/aws-route53-targets/lib/index.ts
+++ b/packages/@aws-cdk/aws-route53-targets/lib/index.ts
@@ -1,6 +1,7 @@
 export * from './api-gateway-domain-name';
 export * from './api-gatewayv2-domain-name';
 export * from './bucket-website-target';
+export * from './elastic-beanstalk-environment-target';
 export * from './classic-load-balancer-target';
 export * from './cloudfront-target';
 export * from './load-balancer-target';
diff --git a/packages/@aws-cdk/aws-route53-targets/test/elastic-beanstalk-environment-target.test.ts b/packages/@aws-cdk/aws-route53-targets/test/elastic-beanstalk-environment-target.test.ts
new file mode 100644
index 0000000000000..ed18f49362118
--- /dev/null
+++ b/packages/@aws-cdk/aws-route53-targets/test/elastic-beanstalk-environment-target.test.ts
@@ -0,0 +1,25 @@
+import '@aws-cdk/assert-internal/jest';
+import * as route53 from '@aws-cdk/aws-route53';
+import { Stack } from '@aws-cdk/core';
+import * as targets from '../lib';
+
+test('use EBS environment as record target', () => {
+  // GIVEN
+  const stack = new Stack();
+  const zone = new route53.PublicHostedZone(stack, 'HostedZone', { zoneName: 'test.public' });
+
+  // WHEN
+  new route53.ARecord(stack, 'Alias', {
+    zone,
+    recordName: '_foo',
+    target: route53.RecordTarget.fromAlias(new targets.ElasticBeanstalkEnvironmentEndpointTarget('mysampleenvironment.xyz.us-east-1.elasticbeanstalk.com')),
+  });
+
+  // THEN
+  expect(stack).toHaveResource('AWS::Route53::RecordSet', {
+    AliasTarget: {
+      DNSName: 'mysampleenvironment.xyz.us-east-1.elasticbeanstalk.com',
+      HostedZoneId: 'Z117KPS5GTRQ2G',
+    },
+  });
+});
diff --git a/packages/@aws-cdk/region-info/build-tools/fact-tables.ts b/packages/@aws-cdk/region-info/build-tools/fact-tables.ts
index 0e1f923dc2a02..6d95f24e5a7e8 100644
--- a/packages/@aws-cdk/region-info/build-tools/fact-tables.ts
+++ b/packages/@aws-cdk/region-info/build-tools/fact-tables.ts
@@ -72,6 +72,37 @@ export const ROUTE_53_BUCKET_WEBSITE_ZONE_IDS: { [region: string]: string } = {
   'us-west-2': 'Z3BJ6K6RIION7M',
 };
 
+/**
+ * The hosted zone Id of the Elastic Beanstalk environment.
+ *
+ * @see https://docs.aws.amazon.com/general/latest/gr/elasticbeanstalk.html
+ */
+export const EBS_ENV_ENDPOINT_HOSTED_ZONE_IDS: { [region: string]: string } = {
+  'af-south-1': 'Z1EI3BVKMKK4AM',
+  'ap-east-1': 'ZPWYUBWRU171A',
+  'ap-northeast-1': 'Z1R25G3KIG2GBW',
+  'ap-northeast-2': 'Z3JE5OI70TWKCP',
+  'ap-northeast-3': 'ZNE5GEY1TIAGY',
+  'ap-south-1': 'Z18NTBI3Y7N9TZ',
+  'ap-southeast-1': 'Z16FZ9L249IFLT',
+  'ap-southeast-2': 'Z2PCDNR3VC2G1N',
+  'ca-central-1': 'ZJFCZL7SSZB5I',
+  'eu-central-1': 'Z1FRNW7UH4DEZJ',
+  'eu-north-1': 'Z23GO28BZ5AETM',
+  'eu-south-1': 'Z10VDYYOA2JFKM',
+  'eu-west-1': 'Z2NYPWQ7DFZAZH',
+  'eu-west-2': 'Z1GKAAAUGATPF1',
+  'eu-west-3': 'Z5WN6GAYWG5OB',
+  'me-south-1': 'Z2BBTEKR2I36N2',
+  'sa-east-1': 'Z10X7K2B4QSOFV',
+  'us-east-1': 'Z117KPS5GTRQ2G',
+  'us-east-2': 'Z14LCN19Q5QHIC',
+  'us-gov-east-1': 'Z35TSARG0EJ4VU',
+  'us-gov-west-1': 'Z4KAURWC4UUUG',
+  'us-west-1': 'Z1LQECGX5PH1X',
+  'us-west-2': 'Z38NKT9BP95V3O',
+};
+
 interface Region { partition: string, domainSuffix: string }
 
 export const PARTITION_MAP: { [region: string]: Region } = {
diff --git a/packages/@aws-cdk/region-info/build-tools/generate-static-data.ts b/packages/@aws-cdk/region-info/build-tools/generate-static-data.ts
index dd42309b78c8a..006de89d3994d 100644
--- a/packages/@aws-cdk/region-info/build-tools/generate-static-data.ts
+++ b/packages/@aws-cdk/region-info/build-tools/generate-static-data.ts
@@ -4,7 +4,7 @@ import { Default } from '../lib/default';
 import { AWS_REGIONS, AWS_SERVICES } from './aws-entities';
 import {
   APPMESH_ECR_ACCOUNTS, AWS_CDK_METADATA, AWS_OLDER_REGIONS, CLOUDWATCH_LAMBDA_INSIGHTS_ARNS, DLC_REPOSITORY_ACCOUNTS,
-  ELBV2_ACCOUNTS, FIREHOSE_CIDR_BLOCKS, PARTITION_MAP, ROUTE_53_BUCKET_WEBSITE_ZONE_IDS,
+  ELBV2_ACCOUNTS, FIREHOSE_CIDR_BLOCKS, PARTITION_MAP, ROUTE_53_BUCKET_WEBSITE_ZONE_IDS, EBS_ENV_ENDPOINT_HOSTED_ZONE_IDS,
 } from './fact-tables';
 
 async function main(): Promise {
@@ -57,6 +57,9 @@ async function main(): Promise {
 
     registerFact(region, 'S3_STATIC_WEBSITE_ZONE_53_HOSTED_ZONE_ID', ROUTE_53_BUCKET_WEBSITE_ZONE_IDS[region] || '');
 
+    registerFact(region, 'EBS_ENV_ENDPOINT_HOSTED_ZONE_ID', EBS_ENV_ENDPOINT_HOSTED_ZONE_IDS[region] || '');
+
+
     registerFact(region, 'ELBV2_ACCOUNT', ELBV2_ACCOUNTS[region]);
 
     registerFact(region, 'DLC_REPOSITORY_ACCOUNT', DLC_REPOSITORY_ACCOUNTS[region]);
diff --git a/packages/@aws-cdk/region-info/lib/fact.ts b/packages/@aws-cdk/region-info/lib/fact.ts
index c099aced9fd55..8d4e33802be43 100644
--- a/packages/@aws-cdk/region-info/lib/fact.ts
+++ b/packages/@aws-cdk/region-info/lib/fact.ts
@@ -128,6 +128,11 @@ export class FactName {
    */
   public static readonly S3_STATIC_WEBSITE_ZONE_53_HOSTED_ZONE_ID = 's3-static-website:route-53-hosted-zone-id';
 
+  /**
+   * The hosted zone ID used by Route 53 to alias a EBS environment endpoint in this region (e.g: Z2O1EMRO9K5GLX)
+   */
+  public static readonly EBS_ENV_ENDPOINT_HOSTED_ZONE_ID = 'ebs-environment:route-53-hosted-zone-id';
+
   /**
    * The prefix for VPC Endpoint Service names,
    * cn.com.amazonaws.vpce for China regions,
diff --git a/packages/@aws-cdk/region-info/lib/region-info.ts b/packages/@aws-cdk/region-info/lib/region-info.ts
index baa2c43635892..3482acf66b9a1 100644
--- a/packages/@aws-cdk/region-info/lib/region-info.ts
+++ b/packages/@aws-cdk/region-info/lib/region-info.ts
@@ -77,6 +77,13 @@ export class RegionInfo {
     return Fact.find(this.name, FactName.S3_STATIC_WEBSITE_ZONE_53_HOSTED_ZONE_ID);
   }
 
+  /**
+  * The hosted zone ID used by Route 53 to alias a EBS environment endpoint in this region (e.g: Z2O1EMRO9K5GLX)
+  */
+  public get ebsEnvEndpointHostedZoneId(): string | undefined {
+    return Fact.find(this.name, FactName.EBS_ENV_ENDPOINT_HOSTED_ZONE_ID);
+  }
+
   /**
    * The prefix for VPC Endpoint Service names,
    * cn.com.amazonaws.vpce for China regions,

From c24af54946d3668afa596dbf2a776b7cf21f8a99 Mon Sep 17 00:00:00 2001
From: Zack Ganger 
Date: Thu, 28 Oct 2021 08:08:20 -0400
Subject: [PATCH 73/87] feat(ec2): VPC endpoint for AWS Xray  (#16788)

Adds a static instance of InterfaceVpcEndpointAwsService for Xray to simplify creation of endpoints for users. VPC endpoint support for XRay was [launched](https://aws.amazon.com/about-aws/whats-new/2021/05/aws-x-ray-now-supports-vpc-endpoints/) in May.

Modeled this addition on #16306

----

*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-ec2/lib/vpc-endpoint.ts | 1 +
 packages/@aws-cdk/aws-ec2/package.json        | 1 +
 2 files changed, 2 insertions(+)

diff --git a/packages/@aws-cdk/aws-ec2/lib/vpc-endpoint.ts b/packages/@aws-cdk/aws-ec2/lib/vpc-endpoint.ts
index 3282da410d09a..00c59bbd2a022 100644
--- a/packages/@aws-cdk/aws-ec2/lib/vpc-endpoint.ts
+++ b/packages/@aws-cdk/aws-ec2/lib/vpc-endpoint.ts
@@ -309,6 +309,7 @@ export class InterfaceVpcEndpointAwsService implements IInterfaceVpcEndpointServ
   public static readonly STEP_FUNCTIONS = new InterfaceVpcEndpointAwsService('states');
   public static readonly LAMBDA = new InterfaceVpcEndpointAwsService('lambda');
   public static readonly TRANSCRIBE = new InterfaceVpcEndpointAwsService('transcribe');
+  public static readonly XRAY = new InterfaceVpcEndpointAwsService('xray');
 
   /**
    * The name of the service.
diff --git a/packages/@aws-cdk/aws-ec2/package.json b/packages/@aws-cdk/aws-ec2/package.json
index b7ea820e221b5..6cf7d368e25a2 100644
--- a/packages/@aws-cdk/aws-ec2/package.json
+++ b/packages/@aws-cdk/aws-ec2/package.json
@@ -262,6 +262,7 @@
       "docs-public-apis:@aws-cdk/aws-ec2.InterfaceVpcEndpointAwsService.STEP_FUNCTIONS",
       "docs-public-apis:@aws-cdk/aws-ec2.InterfaceVpcEndpointAwsService.LAMBDA",
       "docs-public-apis:@aws-cdk/aws-ec2.InterfaceVpcEndpointAwsService.TRANSCRIBE",
+      "docs-public-apis:@aws-cdk/aws-ec2.InterfaceVpcEndpointAwsService.XRAY",
       "docs-public-apis:@aws-cdk/aws-ec2.Port.toString",
       "docs-public-apis:@aws-cdk/aws-ec2.PrivateSubnet.fromPrivateSubnetAttributes",
       "docs-public-apis:@aws-cdk/aws-ec2.PublicSubnet.fromPublicSubnetAttributes",

From 0318253b423bb65ca7e6bf65411df767f2734296 Mon Sep 17 00:00:00 2001
From: Christian Moore 
Date: Thu, 28 Oct 2021 09:03:53 -0400
Subject: [PATCH 74/87] feat(ec2): add c5ad instances (#16428)

Innocuous addition of c5ad instance class

----

*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-ec2/lib/instance-types.ts | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/packages/@aws-cdk/aws-ec2/lib/instance-types.ts b/packages/@aws-cdk/aws-ec2/lib/instance-types.ts
index 97d3d03e55219..4f81f970bf2db 100644
--- a/packages/@aws-cdk/aws-ec2/lib/instance-types.ts
+++ b/packages/@aws-cdk/aws-ec2/lib/instance-types.ts
@@ -213,6 +213,11 @@ export enum InstanceClass {
    */
   COMPUTE5_NVME_DRIVE = 'c5d',
 
+  /**
+   * Compute optimized instances with local NVME drive, 5th generation
+   */
+  C5D = 'c5d',
+
   /**
    * Compute optimized instances based on AMD EPYC, 5th generation.
    */
@@ -224,9 +229,14 @@ export enum InstanceClass {
   C5A = 'c5a',
 
   /**
-   * Compute optimized instances with local NVME drive, 5th generation
+   * Compute optimized instances with local NVME drive based on AMD EPYC, 5th generation.
    */
-  C5D = 'c5d',
+  COMPUTE5_AMD_NVME_DRIVE = 'c5ad',
+
+  /**
+   * Compute optimized instances with local NVME drive based on AMD EPYC, 5th generation.
+   */
+  C5AD = 'c5ad',
 
   /**
    * Compute optimized instances for high performance computing, 5th generation

From 4b32a25fd118c48999d81c5d4021a55142599cf6 Mon Sep 17 00:00:00 2001
From: Rico Huijbers 
Date: Thu, 28 Oct 2021 15:58:14 +0200
Subject: [PATCH 75/87] chore: disable 'rosetta strict' for all packages
 (#17211)

Currently, `strict` mode in Rosetta will fail the build in the pipeline
without failing the build in a PR review.

This causes unpredictable stoppages in our pipeline that we cannot
afford, so we're disabling the feature for now.

Strict mode will be re-enabled as soon as we are able to add Rosetta
checks to PR reviews.


----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
---
 packages/@aws-cdk/assertions/package.json                       | 2 +-
 packages/@aws-cdk/aws-kinesisfirehose-destinations/package.json | 2 +-
 packages/@aws-cdk/aws-redshift/package.json                     | 2 +-
 packages/@aws-cdk/cloud-assembly-schema/package.json            | 2 +-
 packages/@aws-cdk/cx-api/package.json                           | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/packages/@aws-cdk/assertions/package.json b/packages/@aws-cdk/assertions/package.json
index ac9a08ae297d6..2fe93a7d79d86 100644
--- a/packages/@aws-cdk/assertions/package.json
+++ b/packages/@aws-cdk/assertions/package.json
@@ -50,7 +50,7 @@
     "metadata": {
       "jsii": {
         "rosetta": {
-          "strict": true
+          "strict": false
         }
       }
     }
diff --git a/packages/@aws-cdk/aws-kinesisfirehose-destinations/package.json b/packages/@aws-cdk/aws-kinesisfirehose-destinations/package.json
index 36c981f2c54cd..6f1d68d6cedb3 100644
--- a/packages/@aws-cdk/aws-kinesisfirehose-destinations/package.json
+++ b/packages/@aws-cdk/aws-kinesisfirehose-destinations/package.json
@@ -32,7 +32,7 @@
     "metadata": {
       "jsii": {
         "rosetta": {
-          "strict": true
+          "strict": false
         }
       }
     }
diff --git a/packages/@aws-cdk/aws-redshift/package.json b/packages/@aws-cdk/aws-redshift/package.json
index d6ed1ff2f96ca..02fb952ab4c41 100644
--- a/packages/@aws-cdk/aws-redshift/package.json
+++ b/packages/@aws-cdk/aws-redshift/package.json
@@ -32,7 +32,7 @@
     "metadata": {
       "jsii": {
         "rosetta": {
-          "strict": true
+          "strict": false
         }
       }
     }
diff --git a/packages/@aws-cdk/cloud-assembly-schema/package.json b/packages/@aws-cdk/cloud-assembly-schema/package.json
index e6aee07a67f09..11226b0f1521a 100644
--- a/packages/@aws-cdk/cloud-assembly-schema/package.json
+++ b/packages/@aws-cdk/cloud-assembly-schema/package.json
@@ -32,7 +32,7 @@
     "metadata": {
       "jsii": {
         "rosetta": {
-          "strict": true
+          "strict": false
         }
       }
     }
diff --git a/packages/@aws-cdk/cx-api/package.json b/packages/@aws-cdk/cx-api/package.json
index 8d4293f2b5ee4..0a92e1c3492b6 100644
--- a/packages/@aws-cdk/cx-api/package.json
+++ b/packages/@aws-cdk/cx-api/package.json
@@ -32,7 +32,7 @@
     "metadata": {
       "jsii": {
         "rosetta": {
-          "strict": true
+          "strict": false
         }
       }
     }

From 6e13adc281722a491c0708954d7ed637ad45033b Mon Sep 17 00:00:00 2001
From: Vishal Gupta 
Date: Thu, 28 Oct 2021 07:52:44 -0700
Subject: [PATCH 76/87] feat(ec2): include p4d instance class (#17147)

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*

Instance class is missing p4d instance class. This PR adds that instance class.
---
 packages/@aws-cdk/aws-ec2/lib/instance-types.ts | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/packages/@aws-cdk/aws-ec2/lib/instance-types.ts b/packages/@aws-cdk/aws-ec2/lib/instance-types.ts
index 4f81f970bf2db..a2c5ccdadc760 100644
--- a/packages/@aws-cdk/aws-ec2/lib/instance-types.ts
+++ b/packages/@aws-cdk/aws-ec2/lib/instance-types.ts
@@ -452,10 +452,20 @@ export enum InstanceClass {
   PARALLEL3 = 'p3',
 
   /**
-   * Parallel-processing optimized instances, 3nd generation
+   * Parallel-processing optimized instances, 3rd generation
    */
   P3 = 'p3',
 
+  /**
+   * Parallel-processing optimized instances, 4th generation
+   */
+  PARALLEL4 = 'p4d',
+
+  /**
+   * Parallel-processing optimized instances, 4th generation
+   */
+  P4D = 'p4d',
+
   /**
    * Arm processor based instances, 1st generation
    */

From f7e68e9d1cbeb9882e38d91eec1ff19f58da6f1a Mon Sep 17 00:00:00 2001
From: Kyle Roach 
Date: Thu, 28 Oct 2021 11:47:13 -0400
Subject: [PATCH 77/87] chore(apigateway): specify description on `addApiKey()`
 (#17107)

Previously defining a description was not possible when using `addApiKey` method.

This PR enables this by moving the description field to ApiKeyOptions.


----

*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-apigateway/lib/api-key.ts | 14 +++++++-------
 .../aws-apigateway/test/api-key.test.ts         | 17 +++++++++++++++++
 2 files changed, 24 insertions(+), 7 deletions(-)

diff --git a/packages/@aws-cdk/aws-apigateway/lib/api-key.ts b/packages/@aws-cdk/aws-apigateway/lib/api-key.ts
index f48a01193385f..a8065430fef4c 100644
--- a/packages/@aws-cdk/aws-apigateway/lib/api-key.ts
+++ b/packages/@aws-cdk/aws-apigateway/lib/api-key.ts
@@ -40,6 +40,13 @@ export interface ApiKeyOptions extends ResourceOptions {
    * @default none
    */
   readonly value?: string;
+
+  /**
+   * A description of the purpose of the API key.
+   * @link http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-apikey.html#cfn-apigateway-apikey-description
+   * @default none
+   */
+  readonly description?: string;
 }
 
 /**
@@ -59,13 +66,6 @@ export interface ApiKeyProps extends ApiKeyOptions {
    */
   readonly customerId?: string;
 
-  /**
-   * A description of the purpose of the API key.
-   * @link http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-apikey.html#cfn-apigateway-apikey-description
-   * @default none
-   */
-  readonly description?: string;
-
   /**
    * Indicates whether the API key can be used by clients.
    * @link http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-apikey.html#cfn-apigateway-apikey-enabled
diff --git a/packages/@aws-cdk/aws-apigateway/test/api-key.test.ts b/packages/@aws-cdk/aws-apigateway/test/api-key.test.ts
index f4f348a2a3d23..6fee9378f1217 100644
--- a/packages/@aws-cdk/aws-apigateway/test/api-key.test.ts
+++ b/packages/@aws-cdk/aws-apigateway/test/api-key.test.ts
@@ -41,6 +41,23 @@ describe('api key', () => {
     });
   });
 
+  test('add description to apiKey', () => {
+    // GIVEN
+    const stack = new cdk.Stack();
+    const api = new apigateway.RestApi(stack, 'test-api');
+    api.root.addMethod('GET'); // api must have atleast one method.
+
+    // WHEN
+    api.addApiKey('my-api-key', {
+      description: 'The most secret api key',
+    });
+
+    // THEN
+    expect(stack).toHaveResource('AWS::ApiGateway::ApiKey', {
+      Description: 'The most secret api key',
+    });
+  });
+
   test('use an imported api key', () => {
     // GIVEN
     const stack = new cdk.Stack();

From 7f194000697b85deb410ae0d7f7d4ac3c2654bcc Mon Sep 17 00:00:00 2001
From: Mario Viens 
Date: Thu, 28 Oct 2021 09:40:40 -0700
Subject: [PATCH 78/87] docs(assert): clarify assert library use with monocdk.
 (#17202)

Using monocdk with the @aws-cdk/assert creates problems. I initially was going to create a PR to fix the problem it created (some circular dependency unravelling which JSON.stringify fails on, along with alarms not actually being found to be added to the stack I was testing), but instead I found this is what we should use instead, which this readme update would have saved me a lot of time troubleshooting.

This I believe should put this line right below the quote section in the top of both https://www.npmjs.com/package/@aws-cdk/assert and https://www.npmjs.com/package/@monocdk-experiment/assert

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
---
 packages/@aws-cdk/assert-internal/README.md | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/packages/@aws-cdk/assert-internal/README.md b/packages/@aws-cdk/assert-internal/README.md
index 9256b46d2b154..ae72469dc59e2 100644
--- a/packages/@aws-cdk/assert-internal/README.md
+++ b/packages/@aws-cdk/assert-internal/README.md
@@ -11,6 +11,8 @@
 > announced in the release notes. This means that while you may use them, you may need to update
 > your source code when upgrading to a newer version of this package.
 
+If using monocdk, use [@monocdk-experiment/assert](https://www.npmjs.com/package/@monocdk-experiment/assert) instead.
+
 ---
 
 

From 0cabb9f2d2f50c03337cd6f35bf47fc54ada3a21 Mon Sep 17 00:00:00 2001
From: Tatsuya Yamamoto 
Date: Fri, 29 Oct 2021 03:08:57 +0900
Subject: [PATCH 79/87] feat(iot): allow setting Actions of TopicRule (#17110)

I'm trying to implement aws-iot L2 Constructs.

This PR is the next step of #16681

refar:
- https://github.com/aws/aws-cdk/pull/16681#discussion_r733912215

----

*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-iot-actions/README.md   |  30 +++++
 .../@aws-cdk/aws-iot-actions/lib/index.ts     |   3 +-
 .../lib/lambda-function-action.ts             |  30 +++++
 .../@aws-cdk/aws-iot-actions/package.json     |  10 ++
 ...integ.lambda-function-action.expected.json |  97 +++++++++++++++
 .../lambda/integ.lambda-function-action.ts    |  31 +++++
 .../lambda/lambda-function-action.test.ts     |  57 +++++++++
 packages/@aws-cdk/aws-iot/README.md           |  35 ++++--
 packages/@aws-cdk/aws-iot/lib/action.ts       |  24 ++++
 packages/@aws-cdk/aws-iot/lib/index.ts        |   1 +
 packages/@aws-cdk/aws-iot/lib/iot-sql.ts      |   1 -
 packages/@aws-cdk/aws-iot/lib/topic-rule.ts   |  43 ++++++-
 .../test/integ.topic-rule.expected.json       |   8 +-
 .../@aws-cdk/aws-iot/test/integ.topic-rule.ts |   9 ++
 .../@aws-cdk/aws-iot/test/topic-rule.test.ts  | 115 +++++++++++++++++-
 tools/@aws-cdk/pkglint/lib/rules.ts           |   1 +
 16 files changed, 472 insertions(+), 23 deletions(-)
 create mode 100644 packages/@aws-cdk/aws-iot-actions/lib/lambda-function-action.ts
 create mode 100644 packages/@aws-cdk/aws-iot-actions/test/lambda/integ.lambda-function-action.expected.json
 create mode 100644 packages/@aws-cdk/aws-iot-actions/test/lambda/integ.lambda-function-action.ts
 create mode 100644 packages/@aws-cdk/aws-iot-actions/test/lambda/lambda-function-action.test.ts
 create mode 100644 packages/@aws-cdk/aws-iot/lib/action.ts

diff --git a/packages/@aws-cdk/aws-iot-actions/README.md b/packages/@aws-cdk/aws-iot-actions/README.md
index 1c098d25eb3de..67d9b2924dd53 100644
--- a/packages/@aws-cdk/aws-iot-actions/README.md
+++ b/packages/@aws-cdk/aws-iot-actions/README.md
@@ -18,3 +18,33 @@
 This library contains integration classes to send data to any number of
 supported AWS Services. Instances of these classes should be passed to
 `TopicRule` defined in `@aws-cdk/aws-iot`.
+
+Currently supported are:
+
+- Invoke a Lambda function
+
+## Invoke a Lambda function
+
+The code snippet below creates an AWS IoT Rule that invoke a Lambda function
+when it is triggered.
+
+```ts
+import * as iot from '@aws-cdk/aws-iot';
+import * as actions from '@aws-cdk/aws-iot-actions';
+import * as lambda from '@aws-cdk/aws-lambda';
+
+const func = new lambda.Function(this, 'MyFunction', {
+  runtime: lambda.Runtime.NODEJS_14_X,
+  handler: 'index.handler',
+  code: lambda.Code.fromInline(`
+    exports.handler = (event) => {
+      console.log("It is test for lambda action of AWS IoT Rule.", event);
+    };`
+  ),
+});
+
+new iot.TopicRule(this, 'TopicRule', {
+  sql: iot.IotSql.fromStringAsVer20160323("SELECT topic(2) as device_id, timestamp() as timestamp, temperature FROM 'device/+/data'"),
+  actions: [new actions.LambdaFunctionAction(func)],
+});
+```
diff --git a/packages/@aws-cdk/aws-iot-actions/lib/index.ts b/packages/@aws-cdk/aws-iot-actions/lib/index.ts
index 3e4b0ef0a73d4..751863744ffe2 100644
--- a/packages/@aws-cdk/aws-iot-actions/lib/index.ts
+++ b/packages/@aws-cdk/aws-iot-actions/lib/index.ts
@@ -1,2 +1 @@
-// this is placeholder for monocdk
-export const dummy = true;
+export * from './lambda-function-action';
diff --git a/packages/@aws-cdk/aws-iot-actions/lib/lambda-function-action.ts b/packages/@aws-cdk/aws-iot-actions/lib/lambda-function-action.ts
new file mode 100644
index 0000000000000..8296e112e8be5
--- /dev/null
+++ b/packages/@aws-cdk/aws-iot-actions/lib/lambda-function-action.ts
@@ -0,0 +1,30 @@
+import * as iam from '@aws-cdk/aws-iam';
+import * as iot from '@aws-cdk/aws-iot';
+import * as lambda from '@aws-cdk/aws-lambda';
+
+/**
+ * The action to invoke an AWS Lambda function, passing in an MQTT message.
+ */
+export class LambdaFunctionAction implements iot.IAction {
+  /**
+   * @param func The lambda function to be invoked by this action
+   */
+  constructor(private readonly func: lambda.IFunction) {}
+
+  bind(topicRule: iot.ITopicRule): iot.ActionConfig {
+    this.func.addPermission('invokedByAwsIotRule', {
+      action: 'lambda:InvokeFunction',
+      principal: new iam.ServicePrincipal('iot.amazonaws.com'),
+      sourceAccount: topicRule.env.account,
+      sourceArn: topicRule.topicRuleArn,
+    });
+
+    return {
+      configuration: {
+        lambda: {
+          functionArn: this.func.functionArn,
+        },
+      },
+    };
+  }
+}
diff --git a/packages/@aws-cdk/aws-iot-actions/package.json b/packages/@aws-cdk/aws-iot-actions/package.json
index 76878637e0430..3b66b73a1562e 100644
--- a/packages/@aws-cdk/aws-iot-actions/package.json
+++ b/packages/@aws-cdk/aws-iot-actions/package.json
@@ -79,9 +79,19 @@
     "jest": "^26.6.3"
   },
   "dependencies": {
+    "@aws-cdk/aws-iam": "0.0.0",
+    "@aws-cdk/aws-iot": "0.0.0",
+    "@aws-cdk/aws-lambda": "0.0.0",
+    "@aws-cdk/core": "0.0.0",
+    "constructs": "^3.3.69"
   },
   "homepage": "https://github.com/aws/aws-cdk",
   "peerDependencies": {
+    "@aws-cdk/aws-iam": "0.0.0",
+    "@aws-cdk/aws-iot": "0.0.0",
+    "@aws-cdk/aws-lambda": "0.0.0",
+    "@aws-cdk/core": "0.0.0",
+    "constructs": "^3.3.69"
   },
   "engines": {
     "node": ">= 10.13.0 <13 || >=13.7.0"
diff --git a/packages/@aws-cdk/aws-iot-actions/test/lambda/integ.lambda-function-action.expected.json b/packages/@aws-cdk/aws-iot-actions/test/lambda/integ.lambda-function-action.expected.json
new file mode 100644
index 0000000000000..345ead052c921
--- /dev/null
+++ b/packages/@aws-cdk/aws-iot-actions/test/lambda/integ.lambda-function-action.expected.json
@@ -0,0 +1,97 @@
+{
+  "Resources": {
+    "MyFunctionServiceRole3C357FF2": {
+      "Type": "AWS::IAM::Role",
+      "Properties": {
+        "AssumeRolePolicyDocument": {
+          "Statement": [
+            {
+              "Action": "sts:AssumeRole",
+              "Effect": "Allow",
+              "Principal": {
+                "Service": "lambda.amazonaws.com"
+              }
+            }
+          ],
+          "Version": "2012-10-17"
+        },
+        "ManagedPolicyArns": [
+          {
+            "Fn::Join": [
+              "",
+              [
+                "arn:",
+                {
+                  "Ref": "AWS::Partition"
+                },
+                ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
+              ]
+            ]
+          }
+        ]
+      }
+    },
+    "MyFunction3BAA72D1": {
+      "Type": "AWS::Lambda::Function",
+      "Properties": {
+        "Code": {
+          "ZipFile": "\n        exports.handler = (event) => {\n          console.log(\"It is test for lambda action of AWS IoT Rule.\", event);\n        };\""
+        },
+        "Role": {
+          "Fn::GetAtt": [
+            "MyFunctionServiceRole3C357FF2",
+            "Arn"
+          ]
+        },
+        "Handler": "index.handler",
+        "Runtime": "nodejs14.x"
+      },
+      "DependsOn": [
+        "MyFunctionServiceRole3C357FF2"
+      ]
+    },
+    "MyFunctioninvokedByAwsIotRule5581F304": {
+      "Type": "AWS::Lambda::Permission",
+      "Properties": {
+        "Action": "lambda:InvokeFunction",
+        "FunctionName": {
+          "Fn::GetAtt": [
+            "MyFunction3BAA72D1",
+            "Arn"
+          ]
+        },
+        "Principal": "iot.amazonaws.com",
+        "SourceAccount": {
+          "Ref": "AWS::AccountId"
+        },
+        "SourceArn": {
+          "Fn::GetAtt": [
+            "TopicRule40A4EA44",
+            "Arn"
+          ]
+        }
+      }
+    },
+    "TopicRule40A4EA44": {
+      "Type": "AWS::IoT::TopicRule",
+      "Properties": {
+        "TopicRulePayload": {
+          "Actions": [
+            {
+              "Lambda": {
+                "FunctionArn": {
+                  "Fn::GetAtt": [
+                    "MyFunction3BAA72D1",
+                    "Arn"
+                  ]
+                }
+              }
+            }
+          ],
+          "AwsIotSqlVersion": "2016-03-23",
+          "Sql": "SELECT topic(2) as device_id, timestamp() as timestamp, temperature FROM 'device/+/data'"
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/packages/@aws-cdk/aws-iot-actions/test/lambda/integ.lambda-function-action.ts b/packages/@aws-cdk/aws-iot-actions/test/lambda/integ.lambda-function-action.ts
new file mode 100644
index 0000000000000..58a7773afec03
--- /dev/null
+++ b/packages/@aws-cdk/aws-iot-actions/test/lambda/integ.lambda-function-action.ts
@@ -0,0 +1,31 @@
+/// !cdk-integ pragma:ignore-assets
+import * as iot from '@aws-cdk/aws-iot';
+import * as lambda from '@aws-cdk/aws-lambda';
+import * as cdk from '@aws-cdk/core';
+import * as actions from '../../lib';
+
+const app = new cdk.App();
+
+class TestStack extends cdk.Stack {
+  constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
+    super(scope, id, props);
+
+    const func = new lambda.Function(this, 'MyFunction', {
+      runtime: lambda.Runtime.NODEJS_14_X,
+      handler: 'index.handler',
+      code: lambda.Code.fromInline(`
+        exports.handler = (event) => {
+          console.log("It is test for lambda action of AWS IoT Rule.", event);
+        };"`,
+      ),
+    });
+
+    new iot.TopicRule(this, 'TopicRule', {
+      sql: iot.IotSql.fromStringAsVer20160323("SELECT topic(2) as device_id, timestamp() as timestamp, temperature FROM 'device/+/data'"),
+      actions: [new actions.LambdaFunctionAction(func)],
+    });
+  }
+}
+
+new TestStack(app, 'test-stack');
+app.synth();
diff --git a/packages/@aws-cdk/aws-iot-actions/test/lambda/lambda-function-action.test.ts b/packages/@aws-cdk/aws-iot-actions/test/lambda/lambda-function-action.test.ts
new file mode 100644
index 0000000000000..76263f5fa5e5c
--- /dev/null
+++ b/packages/@aws-cdk/aws-iot-actions/test/lambda/lambda-function-action.test.ts
@@ -0,0 +1,57 @@
+import { Template } from '@aws-cdk/assertions';
+import * as iot from '@aws-cdk/aws-iot';
+import * as lambda from '@aws-cdk/aws-lambda';
+import * as cdk from '@aws-cdk/core';
+import * as actions from '../../lib';
+
+test('create a topic rule with lambda action and a lambda permission to be invoked by the topic rule', () => {
+  // GIVEN
+  const stack = new cdk.Stack();
+  const topicRule = new iot.TopicRule(stack, 'MyTopicRule', {
+    sql: iot.IotSql.fromStringAsVer20160323("SELECT topic(2) as device_id FROM 'device/+/data'"),
+  });
+  const func = new lambda.Function(stack, 'MyFunction', {
+    runtime: lambda.Runtime.NODEJS_14_X,
+    handler: 'index.handler',
+    code: lambda.Code.fromInline('console.log("foo")'),
+  });
+
+  // WHEN
+  topicRule.addAction(new actions.LambdaFunctionAction(func));
+
+  // THEN
+  Template.fromStack(stack).hasResourceProperties('AWS::IoT::TopicRule', {
+    TopicRulePayload: {
+      Actions: [
+        {
+          Lambda: {
+            FunctionArn: {
+              'Fn::GetAtt': [
+                'MyFunction3BAA72D1',
+                'Arn',
+              ],
+            },
+          },
+        },
+      ],
+    },
+  });
+
+  Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Permission', {
+    Action: 'lambda:InvokeFunction',
+    FunctionName: {
+      'Fn::GetAtt': [
+        'MyFunction3BAA72D1',
+        'Arn',
+      ],
+    },
+    Principal: 'iot.amazonaws.com',
+    SourceAccount: { Ref: 'AWS::AccountId' },
+    SourceArn: {
+      'Fn::GetAtt': [
+        'MyTopicRule4EC2091C',
+        'Arn',
+      ],
+    },
+  });
+});
diff --git a/packages/@aws-cdk/aws-iot/README.md b/packages/@aws-cdk/aws-iot/README.md
index bbde9aae8a21d..6a9640629891a 100644
--- a/packages/@aws-cdk/aws-iot/README.md
+++ b/packages/@aws-cdk/aws-iot/README.md
@@ -40,16 +40,35 @@ import * as iot from '@aws-cdk/aws-iot';
 
 ## `TopicRule`
 
-The `TopicRule` construct defined Rules that give your devices the ability to
-interact with AWS services.
-
-For example, to define a rule:
+Create a topic rule that give your devices the ability to interact with AWS services.
+You can create a topic rule with an action that invoke the Lambda action as following:
 
 ```ts
-new iot.TopicRule(stack, 'MyTopicRule', {
-  topicRuleName: 'MyRuleName', // optional property
-  sql: iot.IotSql.fromStringAsVer20160323(
-    "SELECT topic(2) as device_id, temperature FROM 'device/+/data'",
+import * as iot from '@aws-cdk/aws-iot';
+import * as actions from '@aws-cdk/aws-iot-actions';
+import * as lambda from '@aws-cdk/aws-lambda';
+
+const func = new lambda.Function(this, 'MyFunction', {
+  runtime: lambda.Runtime.NODEJS_14_X,
+  handler: 'index.handler',
+  code: lambda.Code.fromInline(`
+    exports.handler = (event) => {
+      console.log("It is test for lambda action of AWS IoT Rule.", event);
+    };`
   ),
 });
+
+new iot.TopicRule(this, 'TopicRule', {
+  sql: iot.IotSql.fromStringAsVer20160323("SELECT topic(2) as device_id, timestamp() as timestamp FROM 'device/+/data'"),
+  actions: [new actions.LambdaFunctionAction(func)],
+});
+```
+
+Or, you can add an action after constructing the `TopicRule` instance as following:
+
+```ts
+const topicRule = new iot.TopicRule(this, 'TopicRule', {
+  sql: iot.IotSql.fromStringAsVer20160323("SELECT topic(2) as device_id, timestamp() as timestamp FROM 'device/+/data'"),
+});
+topicRule.addAction(new actions.LambdaFunctionAction(func))
 ```
diff --git a/packages/@aws-cdk/aws-iot/lib/action.ts b/packages/@aws-cdk/aws-iot/lib/action.ts
new file mode 100644
index 0000000000000..f22daf6194b1c
--- /dev/null
+++ b/packages/@aws-cdk/aws-iot/lib/action.ts
@@ -0,0 +1,24 @@
+import { CfnTopicRule } from './iot.generated';
+import { ITopicRule } from './topic-rule';
+
+/**
+ * An abstract action for TopicRule.
+ */
+export interface IAction {
+  /**
+   * Returns the topic rule action specification.
+   *
+   * @param topicRule The TopicRule that would trigger this action.
+   */
+  bind(topicRule: ITopicRule): ActionConfig;
+}
+
+/**
+ * Properties for an topic rule action
+ */
+export interface ActionConfig {
+  /**
+   * The configuration for this action.
+   */
+  readonly configuration: CfnTopicRule.ActionProperty;
+}
diff --git a/packages/@aws-cdk/aws-iot/lib/index.ts b/packages/@aws-cdk/aws-iot/lib/index.ts
index 18b6f2e03aaeb..f2e82a6c755b2 100644
--- a/packages/@aws-cdk/aws-iot/lib/index.ts
+++ b/packages/@aws-cdk/aws-iot/lib/index.ts
@@ -1,3 +1,4 @@
+export * from './action';
 export * from './iot-sql';
 export * from './topic-rule';
 
diff --git a/packages/@aws-cdk/aws-iot/lib/iot-sql.ts b/packages/@aws-cdk/aws-iot/lib/iot-sql.ts
index c673552743364..7014778cc94ab 100644
--- a/packages/@aws-cdk/aws-iot/lib/iot-sql.ts
+++ b/packages/@aws-cdk/aws-iot/lib/iot-sql.ts
@@ -56,7 +56,6 @@ export abstract class IotSql {
   public abstract bind(scope: Construct): IotSqlConfig;
 }
 
-
 class IotSqlImpl extends IotSql {
   constructor(private readonly version: string, private readonly sql: string) {
     super();
diff --git a/packages/@aws-cdk/aws-iot/lib/topic-rule.ts b/packages/@aws-cdk/aws-iot/lib/topic-rule.ts
index 17f121eb29ab3..a8cd21fe2bd96 100644
--- a/packages/@aws-cdk/aws-iot/lib/topic-rule.ts
+++ b/packages/@aws-cdk/aws-iot/lib/topic-rule.ts
@@ -1,5 +1,6 @@
-import { ArnFormat, Resource, Stack, IResource } from '@aws-cdk/core';
+import { ArnFormat, Resource, Stack, IResource, Lazy } from '@aws-cdk/core';
 import { Construct } from 'constructs';
+import { IAction } from './action';
 import { IotSql } from './iot-sql';
 import { CfnTopicRule } from './iot.generated';
 
@@ -28,11 +29,18 @@ export interface ITopicRule extends IResource {
  */
 export interface TopicRuleProps {
   /**
-   * The name of the rule.
+   * The name of the topic rule.
    * @default None
    */
   readonly topicRuleName?: string;
 
+  /**
+   * The actions associated with the topic rule.
+   *
+   * @default No actions will be perform
+   */
+  readonly actions?: IAction[];
+
   /**
    * A simplified SQL syntax to filter messages received on an MQTT topic and push the data elsewhere.
    *
@@ -69,17 +77,19 @@ export class TopicRule extends Resource implements ITopicRule {
   }
 
   /**
-   * Arn of this rule
+   * Arn of this topic rule
    * @attribute
    */
   public readonly topicRuleArn: string;
 
   /**
-   * Name of this rule
+   * Name of this topic rule
    * @attribute
    */
   public readonly topicRuleName: string;
 
+  private readonly actions: CfnTopicRule.ActionProperty[] = [];
+
   constructor(scope: Construct, id: string, props: TopicRuleProps) {
     super(scope, id, {
       physicalName: props.topicRuleName,
@@ -90,7 +100,7 @@ export class TopicRule extends Resource implements ITopicRule {
     const resource = new CfnTopicRule(this, 'Resource', {
       ruleName: this.physicalName,
       topicRulePayload: {
-        actions: [],
+        actions: Lazy.any({ produce: () => this.actions }),
         awsIotSqlVersion: sqlConfig.awsIotSqlVersion,
         sql: sqlConfig.sql,
       },
@@ -102,5 +112,28 @@ export class TopicRule extends Resource implements ITopicRule {
       resourceName: this.physicalName,
     });
     this.topicRuleName = this.getResourceNameAttribute(resource.ref);
+
+    props.actions?.forEach(action => {
+      this.addAction(action);
+    });
+  }
+
+  /**
+   * Add a action to the topic rule.
+   *
+   * @param action the action to associate with the topic rule.
+   */
+  public addAction(action: IAction): void {
+    const { configuration } = action.bind(this);
+
+    const keys = Object.keys(configuration);
+    if (keys.length === 0) {
+      throw new Error('An action property cannot be an empty object.');
+    }
+    if (keys.length > 1) {
+      throw new Error(`An action property cannot have multiple keys, received: ${keys}`);
+    }
+
+    this.actions.push(configuration);
   }
 }
diff --git a/packages/@aws-cdk/aws-iot/test/integ.topic-rule.expected.json b/packages/@aws-cdk/aws-iot/test/integ.topic-rule.expected.json
index cf4be2735229e..9daad98410825 100644
--- a/packages/@aws-cdk/aws-iot/test/integ.topic-rule.expected.json
+++ b/packages/@aws-cdk/aws-iot/test/integ.topic-rule.expected.json
@@ -4,7 +4,13 @@
       "Type": "AWS::IoT::TopicRule",
       "Properties": {
         "TopicRulePayload": {
-          "Actions": [],
+          "Actions": [
+            {
+              "Http": {
+                "Url": "https://example.com"
+              }
+            }
+          ],
           "AwsIotSqlVersion": "2015-10-08",
           "Sql": "SELECT topic(2) as device_id FROM 'device/+/data'"
         }
diff --git a/packages/@aws-cdk/aws-iot/test/integ.topic-rule.ts b/packages/@aws-cdk/aws-iot/test/integ.topic-rule.ts
index a06edc3c3f5e1..0f4bab54a9d2a 100644
--- a/packages/@aws-cdk/aws-iot/test/integ.topic-rule.ts
+++ b/packages/@aws-cdk/aws-iot/test/integ.topic-rule.ts
@@ -10,6 +10,15 @@ class TestStack extends cdk.Stack {
 
     new iot.TopicRule(this, 'TopicRule', {
       sql: iot.IotSql.fromStringAsVer20151008("SELECT topic(2) as device_id FROM 'device/+/data'"),
+      actions: [
+        {
+          bind: () => ({
+            configuration: {
+              http: { url: 'https://example.com' },
+            },
+          }),
+        },
+      ],
     });
   }
 }
diff --git a/packages/@aws-cdk/aws-iot/test/topic-rule.test.ts b/packages/@aws-cdk/aws-iot/test/topic-rule.test.ts
index 1dec8c3065a86..66246e860dddb 100644
--- a/packages/@aws-cdk/aws-iot/test/topic-rule.test.ts
+++ b/packages/@aws-cdk/aws-iot/test/topic-rule.test.ts
@@ -19,14 +19,14 @@ test('Default property', () => {
 
 test('can get topic rule name', () => {
   const stack = new cdk.Stack();
-  const rule = new iot.TopicRule(stack, 'MyTopicRule', {
+  const topicRule = new iot.TopicRule(stack, 'MyTopicRule', {
     sql: iot.IotSql.fromStringAsVer20151008("SELECT topic(2) as device_id, temperature FROM 'device/+/data'"),
   });
 
   new cdk.CfnResource(stack, 'Res', {
     type: 'Test::Resource',
     properties: {
-      TopicRuleName: rule.topicRuleName,
+      TopicRuleName: topicRule.topicRuleName,
     },
   });
 
@@ -37,14 +37,14 @@ test('can get topic rule name', () => {
 
 test('can get topic rule arn', () => {
   const stack = new cdk.Stack();
-  const rule = new iot.TopicRule(stack, 'MyTopicRule', {
+  const topicRule = new iot.TopicRule(stack, 'MyTopicRule', {
     sql: iot.IotSql.fromStringAsVer20151008("SELECT topic(2) as device_id, temperature FROM 'device/+/data'"),
   });
 
   new cdk.CfnResource(stack, 'Res', {
     type: 'Test::Resource',
     properties: {
-      TopicRuleArn: rule.topicRuleArn,
+      TopicRuleArn: topicRule.topicRuleArn,
     },
   });
 
@@ -100,16 +100,119 @@ test.each([
   }).toThrow('IoT SQL string cannot be empty');
 });
 
+test('can set actions', () => {
+  const stack = new cdk.Stack();
+
+  const action1: iot.IAction = {
+    bind: () => ({
+      configuration: {
+        http: { url: 'http://example.com' },
+      },
+    }),
+  };
+  const action2: iot.IAction = {
+    bind: () => ({
+      configuration: {
+        lambda: { functionArn: 'test-functionArn' },
+      },
+    }),
+  };
+
+  new iot.TopicRule(stack, 'MyTopicRule', {
+    sql: iot.IotSql.fromStringAsVer20151008("SELECT topic(2) as device_id, temperature FROM 'device/+/data'"),
+    actions: [action1, action2],
+  });
+
+  Template.fromStack(stack).hasResourceProperties('AWS::IoT::TopicRule', {
+    TopicRulePayload: {
+      Actions: [
+        { Http: { Url: 'http://example.com' } },
+        { Lambda: { FunctionArn: 'test-functionArn' } },
+      ],
+      Sql: "SELECT topic(2) as device_id, temperature FROM 'device/+/data'",
+    },
+  });
+});
+
+test('can add an action', () => {
+  const stack = new cdk.Stack();
+
+  const topicRule = new iot.TopicRule(stack, 'MyTopicRule', {
+    sql: iot.IotSql.fromStringAsVer20151008("SELECT topic(2) as device_id, temperature FROM 'device/+/data'"),
+  });
+  topicRule.addAction({
+    bind: () => ({
+      configuration: {
+        http: { url: 'http://example.com' },
+      },
+    }),
+  });
+  topicRule.addAction({
+    bind: () => ({
+      configuration: {
+        lambda: { functionArn: 'test-functionArn' },
+      },
+    }),
+  });
+
+  Template.fromStack(stack).hasResourceProperties('AWS::IoT::TopicRule', {
+    TopicRulePayload: {
+      Actions: [
+        { Http: { Url: 'http://example.com' } },
+        { Lambda: { FunctionArn: 'test-functionArn' } },
+      ],
+      Sql: "SELECT topic(2) as device_id, temperature FROM 'device/+/data'",
+    },
+  });
+});
+
+test('cannot add an action as empty object', () => {
+  const stack = new cdk.Stack();
+  const topicRule = new iot.TopicRule(stack, 'MyTopicRule', {
+    sql: iot.IotSql.fromStringAsVer20151008("SELECT topic(2) as device_id, temperature FROM 'device/+/data'"),
+  });
+
+  const emptyKeysAction: iot.IAction = {
+    bind: () => ({
+      configuration: {},
+    }),
+  };
+
+  expect(() => {
+    topicRule.addAction(emptyKeysAction);
+  }).toThrow('An action property cannot be an empty object.');
+});
+
+test('cannot add an action that have multiple keys', () => {
+  const stack = new cdk.Stack();
+  const topicRule = new iot.TopicRule(stack, 'MyTopicRule', {
+    sql: iot.IotSql.fromStringAsVer20151008("SELECT topic(2) as device_id, temperature FROM 'device/+/data'"),
+  });
+
+  const multipleKeysAction: iot.IAction = {
+    bind: () => ({
+      configuration: {
+        http: { url: 'http://example.com' },
+        lambda: { functionArn: 'test-functionArn' },
+      },
+    }),
+  };
+
+  expect(() => {
+    topicRule.addAction(multipleKeysAction);
+  }).toThrow('An action property cannot have multiple keys, received: http,lambda');
+});
+
 test('can import a TopicRule by ARN', () => {
   const stack = new cdk.Stack();
 
-  const topicRuleArn = 'arn:aws:iot:ap-northeast-1:123456789012:rule/my-rule-name';
+  const topicRuleArn = 'arn:aws:iot:ap-northeast-1:123456789012:rule/my-topic-rule-name';
 
   const topicRule = iot.TopicRule.fromTopicRuleArn(stack, 'TopicRuleFromArn', topicRuleArn);
 
   expect(topicRule).toMatchObject({
     topicRuleArn,
-    topicRuleName: 'my-rule-name',
+    topicRuleName: 'my-topic-rule-name',
   });
 });
 
diff --git a/tools/@aws-cdk/pkglint/lib/rules.ts b/tools/@aws-cdk/pkglint/lib/rules.ts
index e18fcb1086fdb..eda6436884d77 100644
--- a/tools/@aws-cdk/pkglint/lib/rules.ts
+++ b/tools/@aws-cdk/pkglint/lib/rules.ts
@@ -1653,6 +1653,7 @@ export class NoExperimentalDependents extends ValidationRule {
     ['@aws-cdk/aws-apigatewayv2-authorizers', ['@aws-cdk/aws-apigatewayv2']],
     ['@aws-cdk/aws-events-targets', ['@aws-cdk/aws-kinesisfirehose']],
     ['@aws-cdk/aws-kinesisfirehose-destinations', ['@aws-cdk/aws-kinesisfirehose']],
+    ['@aws-cdk/aws-iot-actions', ['@aws-cdk/aws-iot']],
   ]);
 
   private readonly excludedModules = ['@aws-cdk/cloudformation-include'];

From 0d7452ee3ce22179242241ed85cf55a173af19b5 Mon Sep 17 00:00:00 2001
From: Calvin Combs <66279577+comcalvi@users.noreply.github.com>
Date: Thu, 28 Oct 2021 12:30:43 -0700
Subject: [PATCH 80/87] chore: transfer ownership of cfn-include to @comcalvi
 (#17218)

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
---
 .github/workflows/issue-label-assign.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/issue-label-assign.yml b/.github/workflows/issue-label-assign.yml
index b7bfacd0126b0..f4d9f3b293c48 100644
--- a/.github/workflows/issue-label-assign.yml
+++ b/.github/workflows/issue-label-assign.yml
@@ -217,7 +217,7 @@ jobs:
            {"area":"@aws-cdk/cfnspec","keywords":["cfn-spec"],"labels":["@aws-cdk/cfnspec"],"assignees":["rix0rrr"]},
            {"area":"@aws-cdk/cloud-assembly-schema","keywords":["cloud-assembly-schema","manifest"],"labels":["@aws-cdk/cloud-assembly-schema"],"assignees":["rix0rrr"]},
            {"area":"@aws-cdk/cloudformation-diff","keywords":["cloudformation-diff","cfn-diff"],"labels":["@aws-cdk/cloudformation-diff"],"assignees":["skinny85"]},
-           {"area":"@aws-cdk/cloudformation-include","keywords":["cloudformation-include","cfn-include"],"labels":["@aws-cdk/cloudformation-include"],"assignees":["skinny85"]},
+           {"area":"@aws-cdk/cloudformation-include","keywords":["cloudformation-include","cfn-include"],"labels":["@aws-cdk/cloudformation-include"],"assignees":["comcalvi"]},
            {"area":"@aws-cdk/core","keywords":["cross-account","nested stacks","core"],"labels":["@aws-cdk/core"],"assignees":["rix0rrr"]},
            {"area":"@aws-cdk/custom-resources","keywords":["custom-resource","provider"],"labels":["@aws-cdk/custom-resources"],"assignees":["rix0rrr"]},
            {"area":"@aws-cdk/cx-api","keywords":["cx-api","cloudartifact","cloudassembly"],"labels":["@aws-cdk/cx-api"],"assignees":["rix0rrr"]},

From 4c6cee5027c1b72af9eec809f646bb5751d683e2 Mon Sep 17 00:00:00 2001
From: kaizen3031593 <36202692+kaizen3031593@users.noreply.github.com>
Date: Fri, 29 Oct 2021 04:33:34 -0400
Subject: [PATCH 81/87] chore(route53): make examples compile (#17226)

in this PR:
- chore(route53): make examples compile
- chore(route53-targets): make examples compile
- chore(route53-patterns): make examples compile

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
---
 .../@aws-cdk/aws-route53-patterns/README.md   | 20 ++---
 .../rosetta/default.ts-fixture                | 12 +++
 .../@aws-cdk/aws-route53-targets/README.md    | 71 ++++++++++++----
 .../rosetta/default.ts-fixture                | 12 +++
 packages/@aws-cdk/aws-route53/README.md       | 80 ++++++++-----------
 .../aws-route53/rosetta/default.ts-fixture    | 14 ++++
 6 files changed, 139 insertions(+), 70 deletions(-)
 create mode 100644 packages/@aws-cdk/aws-route53-patterns/rosetta/default.ts-fixture
 create mode 100644 packages/@aws-cdk/aws-route53-targets/rosetta/default.ts-fixture
 create mode 100644 packages/@aws-cdk/aws-route53/rosetta/default.ts-fixture

diff --git a/packages/@aws-cdk/aws-route53-patterns/README.md b/packages/@aws-cdk/aws-route53-patterns/README.md
index 4fa852aaad777..a8c9c6b3874e0 100644
--- a/packages/@aws-cdk/aws-route53-patterns/README.md
+++ b/packages/@aws-cdk/aws-route53-patterns/README.md
@@ -41,13 +41,13 @@ must be in US East (N. Virginia).
 The following example creates an HTTPS redirect from `foo.example.com` to `bar.example.com`
 As an existing certificate is not provided, one will be created in `us-east-1` by the CDK.
 
-  ```ts
-  new HttpsRedirect(stack, 'Redirect', {
-    recordNames: ['foo.example.com'],
-    targetDomain: 'bar.example.com',
-    zone: HostedZone.fromHostedZoneAttributes(stack, 'HostedZone', {
-      hostedZoneId: 'ID',
-      zoneName: 'example.com',
-    })
-  });
-  ```
+```ts
+new patterns.HttpsRedirect(this, 'Redirect', {
+  recordNames: ['foo.example.com'],
+  targetDomain: 'bar.example.com',
+  zone: route53.HostedZone.fromHostedZoneAttributes(this, 'HostedZone', {
+    hostedZoneId: 'ID',
+    zoneName: 'example.com',
+  }),
+});
+```
diff --git a/packages/@aws-cdk/aws-route53-patterns/rosetta/default.ts-fixture b/packages/@aws-cdk/aws-route53-patterns/rosetta/default.ts-fixture
new file mode 100644
index 0000000000000..1ec9038bfff0b
--- /dev/null
+++ b/packages/@aws-cdk/aws-route53-patterns/rosetta/default.ts-fixture
@@ -0,0 +1,12 @@
+// Fixture with packages imported, but nothing else
+import { Construct } from 'constructs';
+import { Stack } from '@aws-cdk/core';
+import * as route53 from '@aws-cdk/aws-route53';
+import * as patterns from '@aws-cdk/aws-route53-patterns';
+
+class Fixture extends Stack {
+  constructor(scope: Construct, id: string) {
+    super(scope, id);
+    /// here
+  }
+}
diff --git a/packages/@aws-cdk/aws-route53-targets/README.md b/packages/@aws-cdk/aws-route53-targets/README.md
index 6c703ad5adc8f..9d53630628ddd 100644
--- a/packages/@aws-cdk/aws-route53-targets/README.md
+++ b/packages/@aws-cdk/aws-route53-targets/README.md
@@ -14,9 +14,14 @@ This library contains Route53 Alias Record targets for:
 * API Gateway custom domains
 
   ```ts
+  import * as apigw from '@aws-cdk/aws-apigateway';
+
+  declare const zone: route53.HostedZone;
+  declare const restApi: apigw.LambdaRestApi;
+
   new route53.ARecord(this, 'AliasRecord', {
     zone,
-    target: route53.RecordTarget.fromAlias(new alias.ApiGateway(restApi)),
+    target: route53.RecordTarget.fromAlias(new targets.ApiGateway(restApi)),
     // or - route53.RecordTarget.fromAlias(new alias.ApiGatewayDomain(domainName)),
   });
   ```
@@ -24,38 +29,57 @@ This library contains Route53 Alias Record targets for:
 * API Gateway V2 custom domains
 
   ```ts
+  import * as apigwv2 from '@aws-cdk/aws-apigatewayv2';
+
+  declare const zone: route53.HostedZone;
+  declare const domainName: apigwv2.DomainName;
 
   new route53.ARecord(this, 'AliasRecord', {
     zone,
-    target: route53.RecordTarget.fromAlias(new alias.ApiGatewayv2DomainProperties(domainName.regionalDomainName, domainName.regionalHostedZoneId)),
+    target: route53.RecordTarget.fromAlias(new targets.ApiGatewayv2DomainProperties(domainName.regionalDomainName, domainName.regionalHostedZoneId)),
   });
   ```
 
 * CloudFront distributions
 
   ```ts
+  import * as cloudfront from '@aws-cdk/aws-cloudfront';
+
+  declare const zone: route53.HostedZone;
+  declare const distribution: cloudfront.CloudFrontWebDistribution;
+
   new route53.ARecord(this, 'AliasRecord', {
     zone,
-    target: route53.RecordTarget.fromAlias(new alias.CloudFrontTarget(distribution)),
+    target: route53.RecordTarget.fromAlias(new targets.CloudFrontTarget(distribution)),
   });
   ```
 
 * ELBv2 load balancers
 
   ```ts
+  import * as elbv2 from '@aws-cdk/aws-elasticloadbalancingv2';
+  
+  declare const zone: route53.HostedZone;
+  declare const lb: elbv2.ApplicationLoadBalancer;
+
   new route53.ARecord(this, 'AliasRecord', {
     zone,
-    target: route53.RecordTarget.fromAlias(new alias.LoadBalancerTarget(elbv2)),
-    // or - route53.RecordTarget.fromAlias(new alias.ApiGatewayDomain(domainName)),
+    target: route53.RecordTarget.fromAlias(new targets.LoadBalancerTarget(lb)),
+    // or - route53.RecordTarget.fromAlias(new targets.ApiGatewayDomain(domainName)),
   });
   ```
 
 * Classic load balancers
 
   ```ts
+  import * as elb from '@aws-cdk/aws-elasticloadbalancing';
+  
+  declare const zone: route53.HostedZone;
+  declare const lb: elb.LoadBalancer;
+
   new route53.ARecord(this, 'AliasRecord', {
     zone,
-    target: route53.RecordTarget.fromAlias(new alias.ClassicLoadBalancerTarget(elb)),
+    target: route53.RecordTarget.fromAlias(new targets.ClassicLoadBalancerTarget(lb)),
     // or - route53.RecordTarget.fromAlias(new alias.ApiGatewayDomain(domainName)),
   });
   ```
@@ -67,7 +91,12 @@ For example, if the Amazon-provided DNS for the load balancer is `ALB-xxxxxxx.us
 * GlobalAccelerator
 
   ```ts
-  new route53.ARecord(stack, 'AliasRecord', {
+  import * as globalaccelerator from '@aws-cdk/aws-globalaccelerator';
+
+  declare const zone: route53.HostedZone;
+  declare const accelerator: globalaccelerator.Accelerator;
+
+  new route53.ARecord(this, 'AliasRecord', {
     zone,
     target: route53.RecordTarget.fromAlias(new targets.GlobalAcceleratorTarget(accelerator)),
     // or - route53.RecordTarget.fromAlias(new targets.GlobalAcceleratorDomainTarget('xyz.awsglobalaccelerator.com')),
@@ -82,9 +111,14 @@ See [the documentation on DNS addressing](https://docs.aws.amazon.com/global-acc
 **Important:** Based on the CFN docs for VPCEndpoints - [see here](attrDnsEntries) - the attributes returned for DnsEntries in CloudFormation is a combination of the hosted zone ID and the DNS name. The entries are ordered as follows: regional public DNS, zonal public DNS, private DNS, and wildcard DNS. This order is not enforced for AWS Marketplace services, and therefore this CDK construct is ONLY guaranteed to work with non-marketplace services.
 
   ```ts
-  new route53.ARecord(stack, "AliasRecord", {
+  import * as ec2 from '@aws-cdk/aws-ec2';
+
+  declare const zone: route53.HostedZone;
+  declare const interfaceVpcEndpoint: ec2.InterfaceVpcEndpoint;
+
+  new route53.ARecord(this, "AliasRecord", {
     zone,
-    target: route53.RecordTarget.fromAlias(new alias.InterfaceVpcEndpointTarget(interfaceVpcEndpoint))
+    target: route53.RecordTarget.fromAlias(new targets.InterfaceVpcEndpointTarget(interfaceVpcEndpoint)),
   });
   ```
 
@@ -94,35 +128,44 @@ See [the documentation on DNS addressing](https://docs.aws.amazon.com/global-acc
 See [the Developer Guide](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/getting-started.html) for more info.
 
   ```ts
-  const [recordName, domainName] = ['www', 'example.com'];
+  import * as s3 from '@aws-cdk/aws-s3';
+  
+  const recordName = 'www';
+  const domainName = 'example.com';
 
-  const bucketWebsite = new Bucket(this, 'BucketWebsite', {
+  const bucketWebsite = new s3.Bucket(this, 'BucketWebsite', {
     bucketName: [recordName, domainName].join('.'), // www.example.com
     publicReadAccess: true,
     websiteIndexDocument: 'index.html',
   });
 
-  const zone = HostedZone.fromLookup(this, 'Zone', {domainName}); // example.com
+  const zone = route53.HostedZone.fromLookup(this, 'Zone', {domainName}); // example.com
 
   new route53.ARecord(this, 'AliasRecord', {
     zone,
     recordName, // www
-    target: route53.RecordTarget.fromAlias(new alias.BucketWebsiteTarget(bucket)),
+    target: route53.RecordTarget.fromAlias(new targets.BucketWebsiteTarget(bucketWebsite)),
   });
   ```
 
 * User pool domain
 
   ```ts
+  import * as cognito from '@aws-cdk/aws-cognito';
+
+  declare const zone: route53.HostedZone;
+  declare const domain: cognito.UserPoolDomain;
   new route53.ARecord(this, 'AliasRecord', {
     zone,
-    target: route53.RecordTarget.fromAlias(new alias.UserPoolDomainTarget(domain)),
+    target: route53.RecordTarget.fromAlias(new targets.UserPoolDomainTarget(domain)),
   });
   ```
 
 * Route 53 record
 
   ```ts
+  declare const zone: route53.HostedZone;
+  declare const record: route53.ARecord;
   new route53.ARecord(this, 'AliasRecord', {
     zone,
     target: route53.RecordTarget.fromAlias(new targets.Route53RecordTarget(record)),
diff --git a/packages/@aws-cdk/aws-route53-targets/rosetta/default.ts-fixture b/packages/@aws-cdk/aws-route53-targets/rosetta/default.ts-fixture
new file mode 100644
index 0000000000000..6274dd0805499
--- /dev/null
+++ b/packages/@aws-cdk/aws-route53-targets/rosetta/default.ts-fixture
@@ -0,0 +1,12 @@
+// Fixture with packages imported, but nothing else
+import { Construct } from 'constructs';
+import { Stack } from '@aws-cdk/core';
+import * as route53 from '@aws-cdk/aws-route53';
+import * as targets from '@aws-cdk/aws-route53-targets';
+
+class Fixture extends Stack {
+  constructor(scope: Construct, id: string) {
+    super(scope, id);
+    /// here
+  }
+}
diff --git a/packages/@aws-cdk/aws-route53/README.md b/packages/@aws-cdk/aws-route53/README.md
index d4376f335d848..46dce3574a130 100644
--- a/packages/@aws-cdk/aws-route53/README.md
+++ b/packages/@aws-cdk/aws-route53/README.md
@@ -14,10 +14,8 @@
 To add a public hosted zone:
 
 ```ts
-import * as route53 from '@aws-cdk/aws-route53';
-
 new route53.PublicHostedZone(this, 'HostedZone', {
-  zoneName: 'fully.qualified.domain.com'
+  zoneName: 'fully.qualified.domain.com',
 });
 ```
 
@@ -26,14 +24,11 @@ To add a private hosted zone, use `PrivateHostedZone`. Note that
 VPC you're configuring for private hosted zones.
 
 ```ts
-import * as ec2 from '@aws-cdk/aws-ec2';
-import * as route53 from '@aws-cdk/aws-route53';
-
-const vpc = new ec2.Vpc(this, 'VPC');
+declare const vpc: ec2.Vpc;
 
 const zone = new route53.PrivateHostedZone(this, 'HostedZone', {
   zoneName: 'fully.qualified.domain.com',
-  vpc    // At least one VPC has to be added to a Private Hosted Zone.
+  vpc,    // At least one VPC has to be added to a Private Hosted Zone.
 });
 ```
 
@@ -44,7 +39,7 @@ Additional VPCs can be added with `zone.addVpc()`.
 To add a TXT record to your zone:
 
 ```ts
-import * as route53 from '@aws-cdk/aws-route53';
+declare const myZone: route53.HostedZone;
 
 new route53.TxtRecord(this, 'TXTRecord', {
   zone: myZone,
@@ -54,7 +49,7 @@ new route53.TxtRecord(this, 'TXTRecord', {
                        // Defaults to zone root if not specified.
   values: [            // Will be quoted for you, and " will be escaped automatically.
     'Bar!',
-    'Baz?'
+    'Baz?',
   ],
   ttl: Duration.minutes(90),       // Optional - default is 30 minutes
 });
@@ -63,14 +58,14 @@ new route53.TxtRecord(this, 'TXTRecord', {
 To add a NS record to your zone:
 
 ```ts
-import * as route53 from '@aws-cdk/aws-route53';
+declare const myZone: route53.HostedZone;
 
 new route53.NsRecord(this, 'NSRecord', {
   zone: myZone,
   recordName: 'foo',  
   values: [            
     'ns-1.awsdns.co.uk.',
-    'ns-2.awsdns.com.'
+    'ns-2.awsdns.com.',
   ],
   ttl: Duration.minutes(90),       // Optional - default is 30 minutes
 });
@@ -79,7 +74,7 @@ new route53.NsRecord(this, 'NSRecord', {
 To add a DS record to your zone:
 
 ```ts
-import * as route53 from '@aws-cdk/aws-route53';
+declare const myZone: route53.HostedZone;
 
 new route53.DsRecord(this, 'DSRecord', {
   zone: myZone,
@@ -94,44 +89,41 @@ new route53.DsRecord(this, 'DSRecord', {
 To add an A record to your zone:
 
 ```ts
-import * as route53 from '@aws-cdk/aws-route53';
+declare const myZone: route53.HostedZone;
 
 new route53.ARecord(this, 'ARecord', {
   zone: myZone,
-  target: route53.RecordTarget.fromIpAddresses('1.2.3.4', '5.6.7.8')
+  target: route53.RecordTarget.fromIpAddresses('1.2.3.4', '5.6.7.8'),
 });
 ```
 
 To add an A record for an EC2 instance with an Elastic IP (EIP) to your zone:
 
 ```ts
-import * as ec2 from '@aws-cdk/aws-ec2';
-import * as route53 from '@aws-cdk/aws-route53';
-
-const instance = new ec2.Instance(this, 'Instance', {
-  // ...
-});
+declare const instance: ec2.Instance;
 
 const elasticIp = new ec2.CfnEIP(this, 'EIP', {
   domain: 'vpc',
-  instanceId: instance.instanceId
+  instanceId: instance.instanceId,
 });
 
+declare const myZone: route53.HostedZone;
 new route53.ARecord(this, 'ARecord', {
   zone: myZone,
-  target: route53.RecordTarget.fromIpAddresses(elasticIp.ref)
+  target: route53.RecordTarget.fromIpAddresses(elasticIp.ref),
 });
 ```
 
 To add an AAAA record pointing to a CloudFront distribution:
 
 ```ts
-import * as route53 from '@aws-cdk/aws-route53';
-import * as targets from '@aws-cdk/aws-route53-targets';
+import * as cloudfront from '@aws-cdk/aws-cloudfront';
 
+declare const myZone: route53.HostedZone;
+declare const distribution: cloudfront.CloudFrontWebDistribution;
 new route53.AaaaRecord(this, 'Alias', {
   zone: myZone,
-  target: route53.RecordTarget.fromAlias(new targets.CloudFrontTarget(distribution))
+  target: route53.RecordTarget.fromAlias(new targets.CloudFrontTarget(distribution)),
 });
 ```
 
@@ -145,8 +137,6 @@ To add a NS record to a HostedZone in different account you can do the following
 In the account containing the parent hosted zone:
 
 ```ts
-import * as route53 from '@aws-cdk/aws-route53';
-
 const parentZone = new route53.PublicHostedZone(this, 'HostedZone', {
   zoneName: 'someexample.com',
   crossAccountZoneDelegationPrincipal: new iam.AccountPrincipal('12345678901'),
@@ -157,11 +147,8 @@ const parentZone = new route53.PublicHostedZone(this, 'HostedZone', {
 In the account containing the child zone to be delegated:
 
 ```ts
-import * as iam from '@aws-cdk/aws-iam';
-import * as route53 from '@aws-cdk/aws-route53';
-
 const subZone = new route53.PublicHostedZone(this, 'SubZone', {
-  zoneName: 'sub.someexample.com'
+  zoneName: 'sub.someexample.com',
 });
 
 // import the delegation role by constructing the roleArn
@@ -188,8 +175,8 @@ If you don't know the ID of the Hosted Zone to import, you can use the
 `HostedZone.fromLookup`:
 
 ```ts
-HostedZone.fromLookup(this, 'MyZone', {
-  domainName: 'example.com'
+route53.HostedZone.fromLookup(this, 'MyZone', {
+  domainName: 'example.com',
 });
 ```
 
@@ -198,18 +185,19 @@ out the [documentation](https://docs.aws.amazon.com/cdk/latest/guide/environment
 automatically looks into your `~/.aws/config` file for the `[default]` profile.
 If you want to specify a different account run `cdk deploy --profile [profile]`.
 
-```ts
+```text
 new MyDevStack(app, 'dev', { 
   env: { 
     account: process.env.CDK_DEFAULT_ACCOUNT, 
-    region: process.env.CDK_DEFAULT_REGION 
-}});
+    region: process.env.CDK_DEFAULT_REGION,
+  },
+});
 ```
 
 If you know the ID and Name of a Hosted Zone, you can import it directly:
 
 ```ts
-const zone = HostedZone.fromHostedZoneAttributes(this, 'MyZone', {
+const zone = route53.HostedZone.fromHostedZoneAttributes(this, 'MyZone', {
   zoneName: 'example.com',
   hostedZoneId: 'ZOJJZC49E0EPZ',
 });
@@ -219,7 +207,7 @@ Alternatively, use the `HostedZone.fromHostedZoneId` to import hosted zones if
 you know the ID and the retrieval for the `zoneName` is undesirable.
 
 ```ts
-const zone = HostedZone.fromHostedZoneId(this, 'MyZone', 'ZOJJZC49E0EPZ');
+const zone = route53.HostedZone.fromHostedZoneId(this, 'MyZone', 'ZOJJZC49E0EPZ');
 ```
 
 ## VPC Endpoint Service Private DNS
@@ -245,22 +233,22 @@ Assuming your account has ownership of the particular domain/subdomain,
 this construct sets up the private DNS configuration on the endpoint service,
 creates all the necessary Route53 entries, and verifies domain ownership.
 
-```ts
+```ts nofixture
 import { Stack } from '@aws-cdk/core';
 import { Vpc, VpcEndpointService } from '@aws-cdk/aws-ec2';
 import { NetworkLoadBalancer } from '@aws-cdk/aws-elasticloadbalancingv2';
-import { PublicHostedZone } from '@aws-cdk/aws-route53';
+import { PublicHostedZone, VpcEndpointServiceDomainName } from '@aws-cdk/aws-route53';
 
-stack = new Stack();
-vpc = new Vpc(stack, 'VPC');
-nlb = new NetworkLoadBalancer(stack, 'NLB', {
+const stack = new Stack();
+const vpc = new Vpc(stack, 'VPC');
+const nlb = new NetworkLoadBalancer(stack, 'NLB', {
   vpc,
 });
-vpces = new VpcEndpointService(stack, 'VPCES', {
+const vpces = new VpcEndpointService(stack, 'VPCES', {
   vpcEndpointServiceLoadBalancers: [nlb],
 });
 // You must use a public hosted zone so domain ownership can be verified
-zone = new PublicHostedZone(stack, 'PHZ', {
+const zone = new PublicHostedZone(stack, 'PHZ', {
   zoneName: 'aws-cdk.dev',
 });
 new VpcEndpointServiceDomainName(stack, 'EndpointDomain', {
diff --git a/packages/@aws-cdk/aws-route53/rosetta/default.ts-fixture b/packages/@aws-cdk/aws-route53/rosetta/default.ts-fixture
new file mode 100644
index 0000000000000..6473005fda521
--- /dev/null
+++ b/packages/@aws-cdk/aws-route53/rosetta/default.ts-fixture
@@ -0,0 +1,14 @@
+// Fixture with packages imported, but nothing else
+import { Construct } from 'constructs';
+import { Duration, Stack } from '@aws-cdk/core';
+import * as route53 from '@aws-cdk/aws-route53';
+import * as targets from '@aws-cdk/aws-route53-targets';
+import * as ec2 from '@aws-cdk/aws-ec2';
+import * as iam from '@aws-cdk/aws-iam';
+
+class Fixture extends Stack {
+  constructor(scope: Construct, id: string) {
+    super(scope, id);
+    /// here
+  }
+}

From 888e5a06ca67b6e7438bfcc5923eeb46f55203f1 Mon Sep 17 00:00:00 2001
From: kaizen3031593 <36202692+kaizen3031593@users.noreply.github.com>
Date: Fri, 29 Oct 2021 05:28:31 -0400
Subject: [PATCH 82/87] chore(iam): make examples compile (#17195)

----

*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-iam/README.md           | 58 ++++++++++---------
 .../aws-iam/lib/permissions-boundary.ts       |  8 +--
 .../aws-iam/rosetta/default.ts-fixture        | 13 ++---
 3 files changed, 40 insertions(+), 39 deletions(-)

diff --git a/packages/@aws-cdk/aws-iam/README.md b/packages/@aws-cdk/aws-iam/README.md
index b54a0bff34fc4..a81b25d53e6ba 100644
--- a/packages/@aws-cdk/aws-iam/README.md
+++ b/packages/@aws-cdk/aws-iam/README.md
@@ -30,8 +30,8 @@ Managed policies can be attached using `xxx.addManagedPolicy(ManagedPolicy.fromA
 Many of the AWS CDK resources have `grant*` methods that allow you to grant other resources access to that resource. As an example, the following code gives a Lambda function write permissions (Put, Update, Delete) to a DynamoDB table.
 
 ```ts
-const fn = new lambda.Function(this, 'Function', functionProps);
-const table = new dynamodb.Table(this, 'Table', tableProps);
+declare const fn: lambda.Function;
+declare const table: dynamodb.Table;
 
 table.grantWriteData(fn);
 ```
@@ -39,8 +39,8 @@ table.grantWriteData(fn);
 The more generic `grant` method allows you to give specific permissions to a resource:
 
 ```ts
-const fn = new lambda.Function(this, 'Function', functionProps);
-const table = new dynamodb.Table(this, 'Table', tableProps);
+declare const fn: lambda.Function;
+declare const table: dynamodb.Table;
 
 table.grant(fn, 'dynamodb:PutItem');
 ```
@@ -186,7 +186,7 @@ const role = new iam.Role(this, 'MyRole', {
   assumedBy: new iam.CompositePrincipal(
     new iam.ServicePrincipal('ec2.amazonaws.com'),
     new iam.AccountPrincipal('1818188181818187272')
-  )
+  ),
 });
 ```
 
@@ -212,7 +212,7 @@ Cognito, Amazon, Google or Facebook, for example:
 const principal = new iam.WebIdentityPrincipal('cognito-identity.amazonaws.com')
   .withConditions({
     "StringEquals": { "cognito-identity.amazonaws.com:aud": "us-east-2:12345678-abcd-abcd-abcd-123456" },
-    "ForAnyValue:StringLike": {"cognito-identity.amazonaws.com:amr": "unauthenticated"}
+    "ForAnyValue:StringLike": {"cognito-identity.amazonaws.com:amr": "unauthenticated" },
   });
 ```
 
@@ -256,11 +256,11 @@ const customPolicyDocument = iam.PolicyDocument.fromJson(policyDocument);
 
 // You can pass this document as an initial document to a ManagedPolicy
 // or inline Policy.
-const newManagedPolicy = new ManagedPolicy(stack, 'MyNewManagedPolicy', {
-  document: customPolicyDocument
+const newManagedPolicy = new iam.ManagedPolicy(this, 'MyNewManagedPolicy', {
+  document: customPolicyDocument,
 });
-const newPolicy = new Policy(stack, 'MyNewPolicy', {
-  document: customPolicyDocument
+const newPolicy = new iam.Policy(this, 'MyNewPolicy', {
+  document: customPolicyDocument,
 });
 ```
 
@@ -296,15 +296,18 @@ const boundary2 = new iam.ManagedPolicy(this, 'Boundary2', {
 });
 
 // Directly apply the boundary to a Role you create
+declare const role: iam.Role;
 iam.PermissionsBoundary.of(role).apply(boundary);
 
 // Apply the boundary to an Role that was implicitly created for you
-iam.PermissionsBoundary.of(lambdaFunction).apply(boundary);
+declare const fn: lambda.Function;
+iam.PermissionsBoundary.of(fn).apply(boundary);
 
 // Apply the boundary to all Roles in a stack
-iam.PermissionsBoundary.of(stack).apply(boundary);
+iam.PermissionsBoundary.of(this).apply(boundary);
 
 // Remove a Permissions Boundary that is inherited, for example from the Stack level
+declare const customResource: CustomResource;
 iam.PermissionsBoundary.of(customResource).clear();
 ```
 
@@ -347,10 +350,13 @@ pool](https://docs.aws.amazon.com/cognito/latest/developerguide/open-id.html)
 you can reference the provider's ARN as follows:
 
 ```ts
+import * as cognito from '@aws-cdk/aws-cognito';
+
+declare const myProvider: iam.OpenIdConnectProvider;
 new cognito.CfnIdentityPool(this, 'IdentityPool', {
   openIdConnectProviderArns: [myProvider.openIdConnectProviderArn],
   // And the other properties for your identity pool
-  allowUnauthenticatedIdentities,
+  allowUnauthenticatedIdentities: false,
 });
 ```
 
@@ -359,7 +365,7 @@ The `OpenIdConnectPrincipal` class can be used as a principal used with a `OpenI
 ```ts
 const provider = new iam.OpenIdConnectProvider(this, 'MyProvider', {
   url: 'https://openid/connect',
-  clientIds: [ 'myclient1', 'myclient2' ]
+  clientIds: [ 'myclient1', 'myclient2' ],
 });
 const principal = new iam.OpenIdConnectPrincipal(provider);
 ```
@@ -410,25 +416,25 @@ new iam.Role(this, 'Role', {
 IAM manages users for your AWS account. To create a new user:
 
 ```ts
-const user = new User(this, 'MyUser');
+const user = new iam.User(this, 'MyUser');
 ```
 
 To import an existing user by name [with path](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html#identifiers-friendly-names):
 
 ```ts
-const user = User.fromUserName(stack, 'MyImportedUserByName', 'johnsmith');
+const user = iam.User.fromUserName(this, 'MyImportedUserByName', 'johnsmith');
 ```
 
 To import an existing user by ARN:
 
 ```ts
-const user = User.fromUserArn(this, 'MyImportedUserByArn', 'arn:aws:iam::123456789012:user/johnsmith');
+const user = iam.User.fromUserArn(this, 'MyImportedUserByArn', 'arn:aws:iam::123456789012:user/johnsmith');
 ```
 
 To import an existing user by attributes:
 
 ```ts
-const user = User.fromUserAttributes(stack, 'MyImportedUserByAttributes', {
+const user = iam.User.fromUserAttributes(this, 'MyImportedUserByAttributes', {
   userArn: 'arn:aws:iam::123456789012:user/johnsmith',
 });
 ```
@@ -436,8 +442,8 @@ const user = User.fromUserAttributes(stack, 'MyImportedUserByAttributes', {
 To add a user to a group (both for a new and imported user/group):
 
 ```ts
-const user = new User(this, 'MyUser'); // or User.fromUserName(stack, 'User', 'johnsmith');
-const group = new Group(this, 'MyGroup'); // or Group.fromGroupArn(stack, 'Group', 'arn:aws:iam::account-id:group/group-name');
+const user = new iam.User(this, 'MyUser'); // or User.fromUserName(stack, 'User', 'johnsmith');
+const group = new iam.Group(this, 'MyGroup'); // or Group.fromGroupArn(stack, 'Group', 'arn:aws:iam::account-id:group/group-name');
 
 user.addToGroup(group);
 // or
@@ -447,9 +453,9 @@ group.addUser(user);
 
 ## Features
 
- * Policy name uniqueness is enforced. If two policies by the same name are attached to the same
-   principal, the attachment will fail.
- * Policy names are not required - the CDK logical ID will be used and ensured to be unique.
- * Policies are validated during synthesis to ensure that they have actions, and that policies
-   attached to IAM principals specify relevant resources, while policies attached to resources
-   specify which IAM principals they apply to.
+  * Policy name uniqueness is enforced. If two policies by the same name are attached to the same
+    principal, the attachment will fail.
+  * Policy names are not required - the CDK logical ID will be used and ensured to be unique.
+  * Policies are validated during synthesis to ensure that they have actions, and that policies
+    attached to IAM principals specify relevant resources, while policies attached to resources
+    specify which IAM principals they apply to.
diff --git a/packages/@aws-cdk/aws-iam/lib/permissions-boundary.ts b/packages/@aws-cdk/aws-iam/lib/permissions-boundary.ts
index c1a3dde69a026..5084caf9fe4fc 100644
--- a/packages/@aws-cdk/aws-iam/lib/permissions-boundary.ts
+++ b/packages/@aws-cdk/aws-iam/lib/permissions-boundary.ts
@@ -6,10 +6,10 @@ import { IManagedPolicy } from './managed-policy';
 /**
  * Modify the Permissions Boundaries of Users and Roles in a construct tree
  *
- * @example
- *
- * const policy = ManagedPolicy.fromAwsManagedPolicyName('ReadOnlyAccess');
- * PermissionsBoundary.of(stack).apply(policy);
+ * ```ts
+ * const policy = iam.ManagedPolicy.fromAwsManagedPolicyName('ReadOnlyAccess');
+ * iam.PermissionsBoundary.of(this).apply(policy);
+ * ```
  */
 export class PermissionsBoundary {
   /**
diff --git a/packages/@aws-cdk/aws-iam/rosetta/default.ts-fixture b/packages/@aws-cdk/aws-iam/rosetta/default.ts-fixture
index a76493f53c694..a27f557ccf250 100644
--- a/packages/@aws-cdk/aws-iam/rosetta/default.ts-fixture
+++ b/packages/@aws-cdk/aws-iam/rosetta/default.ts-fixture
@@ -1,17 +1,12 @@
-import { Construct } from '@aws-cdk/core';
+import { Construct } from 'constructs';
+import { CustomResource, Stack } from '@aws-cdk/core';
 import * as codepipeline from '@aws-cdk/aws-codepipeline';
-import * as cognito from '@aws-cdk/aws-cognito';
 import * as dynamodb from '@aws-cdk/aws-dynamodb';
 import * as lambda from '@aws-cdk/aws-lambda';
 import * as iam from '@aws-cdk/aws-iam';
 
-declare const allowUnauthenticatedIdentities: boolean;
-declare const functionProps: lambda.FunctionProps;
-declare const myProvider: iam.OpenIdConnectProvider;
-declare const tableProps: dynamodb.TableProps;
-
-class fixture$construct extends Construct {
-  public constructor(scope: Construct, id: string) {
+class Fixture extends Stack {
+  constructor(scope: Construct, id: string) {
     super(scope, id);
 
     /// here

From 0a23953d92df070736f7d036cc2b24e68de4bf64 Mon Sep 17 00:00:00 2001
From: Kyle Roach 
Date: Fri, 29 Oct 2021 06:33:01 -0400
Subject: [PATCH 83/87] fix(elasticloadbalancingv2): always set stickiness
 (#17111)

CloudFormation does not process the removal of the stickiness attribute from the template as a delta that needs to be processed.

This results in scenarios where if a property was set in an application, that removing it would have no effect.

The fix to this is to always explicitly set the property so that a delta is always processed.

Fixes #16620


----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
---
 .../integ.all-service-addons.expected.json    | 22 ++++++++++-------
 .../integ.imported-environment.expected.json  | 22 ++++++++++-------
 .../test/http/integ.alb.expected.json         | 24 ++++++++++++-------
 .../test/integ.asg-w-elbv2.expected.json      | 18 +++++++++-----
 ...on-load-balanced-ecs-service.expected.json | 12 ++++++++++
 ...eg.alb-fargate-service-https.expected.json |  6 +++++
 .../fargate/integ.asset-image.expected.json   |  6 +++++
 ...oad-balanced-fargate-service.expected.json |  6 +++++
 .../fargate/integ.executionrole.expected.json |  6 +++++
 .../fargate/integ.l3-autocreate.expected.json |  6 +++++
 .../fargate/integ.l3-vpconly.expected.json    |  6 +++++
 .../test/fargate/integ.l3.expected.json       |  6 +++++
 .../integ.special-listener.expected.json      |  6 +++++
 .../test/ec2/integ.lb-awsvpc-nw.expected.json | 18 +++++++++-----
 .../test/ec2/integ.lb-bridge-nw.expected.json | 18 +++++++++-----
 .../fargate/integ.lb-awsvpc-nw.expected.json  | 18 +++++++++-----
 .../test/integ.alb-target.expected.json       |  6 +++++
 .../test/integ.lambda-target.expected.json    | 14 +++++++----
 .../lib/alb/application-target-group.ts       |  4 ++++
 .../test/alb/listener.test.ts                 |  8 +++++++
 .../test/alb/target-group.test.ts             |  4 ++++
 .../test/integ.alb.dualstack.expected.json    | 24 ++++++++++++++-----
 .../test/integ.alb2.expected.json             | 24 ++++++++++++++-----
 23 files changed, 217 insertions(+), 67 deletions(-)

diff --git a/packages/@aws-cdk-containers/ecs-service-extensions/test/integ.all-service-addons.expected.json b/packages/@aws-cdk-containers/ecs-service-extensions/test/integ.all-service-addons.expected.json
index afdf0319a819a..bd9224e586933 100644
--- a/packages/@aws-cdk-containers/ecs-service-extensions/test/integ.all-service-addons.expected.json
+++ b/packages/@aws-cdk-containers/ecs-service-extensions/test/integ.all-service-addons.expected.json
@@ -102,15 +102,15 @@
     "productionenvironmentvpcPublicSubnet1NATGateway6075E4CA": {
       "Type": "AWS::EC2::NatGateway",
       "Properties": {
+        "SubnetId": {
+          "Ref": "productionenvironmentvpcPublicSubnet1Subnet8D92C089"
+        },
         "AllocationId": {
           "Fn::GetAtt": [
             "productionenvironmentvpcPublicSubnet1EIP54BA88DB",
             "AllocationId"
           ]
         },
-        "SubnetId": {
-          "Ref": "productionenvironmentvpcPublicSubnet1Subnet8D92C089"
-        },
         "Tags": [
           {
             "Key": "Name",
@@ -199,15 +199,15 @@
     "productionenvironmentvpcPublicSubnet2NATGatewayE1850FCC": {
       "Type": "AWS::EC2::NatGateway",
       "Properties": {
+        "SubnetId": {
+          "Ref": "productionenvironmentvpcPublicSubnet2Subnet298E6C31"
+        },
         "AllocationId": {
           "Fn::GetAtt": [
             "productionenvironmentvpcPublicSubnet2EIP14CA46AA",
             "AllocationId"
           ]
         },
-        "SubnetId": {
-          "Ref": "productionenvironmentvpcPublicSubnet2Subnet298E6C31"
-        },
         "Tags": [
           {
             "Key": "Name",
@@ -296,15 +296,15 @@
     "productionenvironmentvpcPublicSubnet3NATGateway94604057": {
       "Type": "AWS::EC2::NatGateway",
       "Properties": {
+        "SubnetId": {
+          "Ref": "productionenvironmentvpcPublicSubnet3SubnetC7B5665D"
+        },
         "AllocationId": {
           "Fn::GetAtt": [
             "productionenvironmentvpcPublicSubnet3EIP53405AED",
             "AllocationId"
           ]
         },
-        "SubnetId": {
-          "Ref": "productionenvironmentvpcPublicSubnet3SubnetC7B5665D"
-        },
         "Tags": [
           {
             "Key": "Name",
@@ -2391,6 +2391,10 @@
           {
             "Key": "deregistration_delay.timeout_seconds",
             "Value": "10"
+          },
+          {
+            "Key": "stickiness.enabled",
+            "Value": "false"
           }
         ],
         "TargetType": "ip",
diff --git a/packages/@aws-cdk-containers/ecs-service-extensions/test/integ.imported-environment.expected.json b/packages/@aws-cdk-containers/ecs-service-extensions/test/integ.imported-environment.expected.json
index dbc216370e40d..c85f5d9b0231d 100644
--- a/packages/@aws-cdk-containers/ecs-service-extensions/test/integ.imported-environment.expected.json
+++ b/packages/@aws-cdk-containers/ecs-service-extensions/test/integ.imported-environment.expected.json
@@ -17,7 +17,7 @@
               },
               "/",
               {
-                "Ref": "AssetParametersb537a3d3462b62d59d4661ff456403d270823b5c9974ea4f4264ff95683a8ba8S3Bucket60C7B412"
+                "Ref": "AssetParameterse2fc78c01b63f40b6bbcc8ce3c0eaccd3bf8f0aa6196b65f8ee87fb97e343886S3Bucket85F9E22A"
               },
               "/",
               {
@@ -27,7 +27,7 @@
                     "Fn::Split": [
                       "||",
                       {
-                        "Ref": "AssetParametersb537a3d3462b62d59d4661ff456403d270823b5c9974ea4f4264ff95683a8ba8S3VersionKey6900DC52"
+                        "Ref": "AssetParameterse2fc78c01b63f40b6bbcc8ce3c0eaccd3bf8f0aa6196b65f8ee87fb97e343886S3VersionKey8103F967"
                       }
                     ]
                   }
@@ -40,7 +40,7 @@
                     "Fn::Split": [
                       "||",
                       {
-                        "Ref": "AssetParametersb537a3d3462b62d59d4661ff456403d270823b5c9974ea4f4264ff95683a8ba8S3VersionKey6900DC52"
+                        "Ref": "AssetParameterse2fc78c01b63f40b6bbcc8ce3c0eaccd3bf8f0aa6196b65f8ee87fb97e343886S3VersionKey8103F967"
                       }
                     ]
                   }
@@ -163,6 +163,10 @@
           {
             "Key": "deregistration_delay.timeout_seconds",
             "Value": "10"
+          },
+          {
+            "Key": "stickiness.enabled",
+            "Value": "false"
           }
         ],
         "TargetType": "ip",
@@ -358,17 +362,17 @@
     }
   },
   "Parameters": {
-    "AssetParametersb537a3d3462b62d59d4661ff456403d270823b5c9974ea4f4264ff95683a8ba8S3Bucket60C7B412": {
+    "AssetParameterse2fc78c01b63f40b6bbcc8ce3c0eaccd3bf8f0aa6196b65f8ee87fb97e343886S3Bucket85F9E22A": {
       "Type": "String",
-      "Description": "S3 bucket for asset \"b537a3d3462b62d59d4661ff456403d270823b5c9974ea4f4264ff95683a8ba8\""
+      "Description": "S3 bucket for asset \"e2fc78c01b63f40b6bbcc8ce3c0eaccd3bf8f0aa6196b65f8ee87fb97e343886\""
     },
-    "AssetParametersb537a3d3462b62d59d4661ff456403d270823b5c9974ea4f4264ff95683a8ba8S3VersionKey6900DC52": {
+    "AssetParameterse2fc78c01b63f40b6bbcc8ce3c0eaccd3bf8f0aa6196b65f8ee87fb97e343886S3VersionKey8103F967": {
       "Type": "String",
-      "Description": "S3 key for asset version \"b537a3d3462b62d59d4661ff456403d270823b5c9974ea4f4264ff95683a8ba8\""
+      "Description": "S3 key for asset version \"e2fc78c01b63f40b6bbcc8ce3c0eaccd3bf8f0aa6196b65f8ee87fb97e343886\""
     },
-    "AssetParametersb537a3d3462b62d59d4661ff456403d270823b5c9974ea4f4264ff95683a8ba8ArtifactHash5EEB924C": {
+    "AssetParameterse2fc78c01b63f40b6bbcc8ce3c0eaccd3bf8f0aa6196b65f8ee87fb97e343886ArtifactHash6FA4ABA8": {
       "Type": "String",
-      "Description": "Artifact hash for asset \"b537a3d3462b62d59d4661ff456403d270823b5c9974ea4f4264ff95683a8ba8\""
+      "Description": "Artifact hash for asset \"e2fc78c01b63f40b6bbcc8ce3c0eaccd3bf8f0aa6196b65f8ee87fb97e343886\""
     }
   }
 }
\ No newline at end of file
diff --git a/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/integ.alb.expected.json b/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/integ.alb.expected.json
index b9f5d96ff4656..65149587fb3ce 100644
--- a/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/integ.alb.expected.json
+++ b/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/integ.alb.expected.json
@@ -95,15 +95,15 @@
     "VPCPublicSubnet1NATGatewayE0556630": {
       "Type": "AWS::EC2::NatGateway",
       "Properties": {
+        "SubnetId": {
+          "Ref": "VPCPublicSubnet1SubnetB4246D30"
+        },
         "AllocationId": {
           "Fn::GetAtt": [
             "VPCPublicSubnet1EIP6AD938E8",
             "AllocationId"
           ]
         },
-        "SubnetId": {
-          "Ref": "VPCPublicSubnet1SubnetB4246D30"
-        },
         "Tags": [
           {
             "Key": "Name",
@@ -192,15 +192,15 @@
     "VPCPublicSubnet2NATGateway3C070193": {
       "Type": "AWS::EC2::NatGateway",
       "Properties": {
+        "SubnetId": {
+          "Ref": "VPCPublicSubnet2Subnet74179F39"
+        },
         "AllocationId": {
           "Fn::GetAtt": [
             "VPCPublicSubnet2EIP4947BC00",
             "AllocationId"
           ]
         },
-        "SubnetId": {
-          "Ref": "VPCPublicSubnet2Subnet74179F39"
-        },
         "Tags": [
           {
             "Key": "Name",
@@ -289,15 +289,15 @@
     "VPCPublicSubnet3NATGatewayD3048F5C": {
       "Type": "AWS::EC2::NatGateway",
       "Properties": {
+        "SubnetId": {
+          "Ref": "VPCPublicSubnet3Subnet631C5E25"
+        },
         "AllocationId": {
           "Fn::GetAtt": [
             "VPCPublicSubnet3EIPAD4BC883",
             "AllocationId"
           ]
         },
-        "SubnetId": {
-          "Ref": "VPCPublicSubnet3Subnet631C5E25"
-        },
         "Tags": [
           {
             "Key": "Name",
@@ -596,6 +596,12 @@
       "Properties": {
         "Port": 80,
         "Protocol": "HTTP",
+        "TargetGroupAttributes": [
+          {
+            "Key": "stickiness.enabled",
+            "Value": "false"
+          }
+        ],
         "VpcId": {
           "Ref": "VPCB9E5F0B4"
         }
diff --git a/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.expected.json b/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.expected.json
index 34f240a76559d..236be6f46be9e 100644
--- a/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.expected.json
+++ b/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.expected.json
@@ -95,15 +95,15 @@
     "VPCPublicSubnet1NATGatewayE0556630": {
       "Type": "AWS::EC2::NatGateway",
       "Properties": {
+        "SubnetId": {
+          "Ref": "VPCPublicSubnet1SubnetB4246D30"
+        },
         "AllocationId": {
           "Fn::GetAtt": [
             "VPCPublicSubnet1EIP6AD938E8",
             "AllocationId"
           ]
         },
-        "SubnetId": {
-          "Ref": "VPCPublicSubnet1SubnetB4246D30"
-        },
         "Tags": [
           {
             "Key": "Name",
@@ -192,15 +192,15 @@
     "VPCPublicSubnet2NATGateway3C070193": {
       "Type": "AWS::EC2::NatGateway",
       "Properties": {
+        "SubnetId": {
+          "Ref": "VPCPublicSubnet2Subnet74179F39"
+        },
         "AllocationId": {
           "Fn::GetAtt": [
             "VPCPublicSubnet2EIP4947BC00",
             "AllocationId"
           ]
         },
-        "SubnetId": {
-          "Ref": "VPCPublicSubnet2Subnet74179F39"
-        },
         "Tags": [
           {
             "Key": "Name",
@@ -671,6 +671,12 @@
       "Properties": {
         "Port": 80,
         "Protocol": "HTTP",
+        "TargetGroupAttributes": [
+          {
+            "Key": "stickiness.enabled",
+            "Value": "false"
+          }
+        ],
         "TargetType": "instance",
         "VpcId": {
           "Ref": "VPCB9E5F0B4"
diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/integ.multiple-application-load-balanced-ecs-service.expected.json b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/integ.multiple-application-load-balanced-ecs-service.expected.json
index 5ce81fe00ad59..4d4e00fe664e4 100644
--- a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/integ.multiple-application-load-balanced-ecs-service.expected.json
+++ b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/integ.multiple-application-load-balanced-ecs-service.expected.json
@@ -954,6 +954,12 @@
       "Properties": {
         "Port": 80,
         "Protocol": "HTTP",
+        "TargetGroupAttributes": [
+          {
+            "Key": "stickiness.enabled",
+            "Value": "false"
+          }
+        ],
         "TargetType": "instance",
         "VpcId": {
           "Ref": "Vpc8378EB38"
@@ -965,6 +971,12 @@
       "Properties": {
         "Port": 80,
         "Protocol": "HTTP",
+        "TargetGroupAttributes": [
+          {
+            "Key": "stickiness.enabled",
+            "Value": "false"
+          }
+        ],
         "TargetType": "instance",
         "VpcId": {
           "Ref": "Vpc8378EB38"
diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-https.expected.json b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-https.expected.json
index 76713f6d4ef64..ee6317ba0f94f 100644
--- a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-https.expected.json
+++ b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-https.expected.json
@@ -467,6 +467,12 @@
       "Properties": {
         "Port": 80,
         "Protocol": "HTTP",
+        "TargetGroupAttributes": [
+          {
+            "Key": "stickiness.enabled",
+            "Value": "false"
+          }
+        ],
         "TargetType": "ip",
         "VpcId": {
           "Ref": "Vpc8378EB38"
diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.asset-image.expected.json b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.asset-image.expected.json
index dc589f5d6c48f..1be85fbb5e688 100644
--- a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.asset-image.expected.json
+++ b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.asset-image.expected.json
@@ -453,6 +453,12 @@
       "Properties": {
         "Port": 80,
         "Protocol": "HTTP",
+        "TargetGroupAttributes": [
+          {
+            "Key": "stickiness.enabled",
+            "Value": "false"
+          }
+        ],
         "TargetType": "ip",
         "VpcId": {
           "Ref": "Vpc8378EB38"
diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.circuit-breaker-load-balanced-fargate-service.expected.json b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.circuit-breaker-load-balanced-fargate-service.expected.json
index 24b4bb012e384..e43d5c95abf8b 100644
--- a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.circuit-breaker-load-balanced-fargate-service.expected.json
+++ b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.circuit-breaker-load-balanced-fargate-service.expected.json
@@ -453,6 +453,12 @@
       "Properties": {
         "Port": 80,
         "Protocol": "HTTP",
+        "TargetGroupAttributes": [
+          {
+            "Key": "stickiness.enabled",
+            "Value": "false"
+          }
+        ],
         "TargetType": "ip",
         "VpcId": {
           "Ref": "Vpc8378EB38"
diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.executionrole.expected.json b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.executionrole.expected.json
index b3921b410fabd..6d2654abe539c 100644
--- a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.executionrole.expected.json
+++ b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.executionrole.expected.json
@@ -502,6 +502,12 @@
       "Properties": {
         "Port": 80,
         "Protocol": "HTTP",
+        "TargetGroupAttributes": [
+          {
+            "Key": "stickiness.enabled",
+            "Value": "false"
+          }
+        ],
         "TargetType": "ip",
         "VpcId": {
           "Ref": "Vpc8378EB38"
diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.l3-autocreate.expected.json b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.l3-autocreate.expected.json
index 61b34b57938cd..a61c1948d90fe 100644
--- a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.l3-autocreate.expected.json
+++ b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.l3-autocreate.expected.json
@@ -95,6 +95,12 @@
       "Properties": {
         "Port": 80,
         "Protocol": "HTTP",
+        "TargetGroupAttributes": [
+          {
+            "Key": "stickiness.enabled",
+            "Value": "false"
+          }
+        ],
         "TargetType": "ip",
         "VpcId": {
           "Ref": "EcsDefaultClusterMnL3mNNYNVpc7788A521"
diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.l3-vpconly.expected.json b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.l3-vpconly.expected.json
index d63db295a39cc..771eef386379d 100644
--- a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.l3-vpconly.expected.json
+++ b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.l3-vpconly.expected.json
@@ -450,6 +450,12 @@
       "Properties": {
         "Port": 80,
         "Protocol": "HTTP",
+        "TargetGroupAttributes": [
+          {
+            "Key": "stickiness.enabled",
+            "Value": "false"
+          }
+        ],
         "TargetType": "ip",
         "VpcId": {
           "Ref": "Vpc8378EB38"
diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.l3.expected.json b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.l3.expected.json
index 886e4a35dcf63..7ea739f68ff99 100644
--- a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.l3.expected.json
+++ b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.l3.expected.json
@@ -453,6 +453,12 @@
       "Properties": {
         "Port": 80,
         "Protocol": "HTTP",
+        "TargetGroupAttributes": [
+          {
+            "Key": "stickiness.enabled",
+            "Value": "false"
+          }
+        ],
         "TargetType": "ip",
         "VpcId": {
           "Ref": "Vpc8378EB38"
diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.special-listener.expected.json b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.special-listener.expected.json
index 7fa930b16d66d..91c1f4e575e23 100644
--- a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.special-listener.expected.json
+++ b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.special-listener.expected.json
@@ -692,6 +692,12 @@
       "Properties": {
         "Port": 80,
         "Protocol": "HTTP",
+        "TargetGroupAttributes": [
+          {
+            "Key": "stickiness.enabled",
+            "Value": "false"
+          }
+        ],
         "TargetType": "ip",
         "VpcId": {
           "Ref": "Vpc8378EB38"
diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/integ.lb-awsvpc-nw.expected.json b/packages/@aws-cdk/aws-ecs/test/ec2/integ.lb-awsvpc-nw.expected.json
index 1fef2d83e2784..fb1143317da2c 100644
--- a/packages/@aws-cdk/aws-ecs/test/ec2/integ.lb-awsvpc-nw.expected.json
+++ b/packages/@aws-cdk/aws-ecs/test/ec2/integ.lb-awsvpc-nw.expected.json
@@ -95,15 +95,15 @@
     "VpcPublicSubnet1NATGateway4D7517AA": {
       "Type": "AWS::EC2::NatGateway",
       "Properties": {
+        "SubnetId": {
+          "Ref": "VpcPublicSubnet1Subnet5C2D37C4"
+        },
         "AllocationId": {
           "Fn::GetAtt": [
             "VpcPublicSubnet1EIPD7E02669",
             "AllocationId"
           ]
         },
-        "SubnetId": {
-          "Ref": "VpcPublicSubnet1Subnet5C2D37C4"
-        },
         "Tags": [
           {
             "Key": "Name",
@@ -192,15 +192,15 @@
     "VpcPublicSubnet2NATGateway9182C01D": {
       "Type": "AWS::EC2::NatGateway",
       "Properties": {
+        "SubnetId": {
+          "Ref": "VpcPublicSubnet2Subnet691E08A3"
+        },
         "AllocationId": {
           "Fn::GetAtt": [
             "VpcPublicSubnet2EIP3C605A87",
             "AllocationId"
           ]
         },
-        "SubnetId": {
-          "Ref": "VpcPublicSubnet2Subnet691E08A3"
-        },
         "Tags": [
           {
             "Key": "Name",
@@ -1070,6 +1070,12 @@
       "Properties": {
         "Port": 80,
         "Protocol": "HTTP",
+        "TargetGroupAttributes": [
+          {
+            "Key": "stickiness.enabled",
+            "Value": "false"
+          }
+        ],
         "TargetType": "ip",
         "VpcId": {
           "Ref": "Vpc8378EB38"
diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/integ.lb-bridge-nw.expected.json b/packages/@aws-cdk/aws-ecs/test/ec2/integ.lb-bridge-nw.expected.json
index 1bcb9d34f8dbd..662773111278c 100644
--- a/packages/@aws-cdk/aws-ecs/test/ec2/integ.lb-bridge-nw.expected.json
+++ b/packages/@aws-cdk/aws-ecs/test/ec2/integ.lb-bridge-nw.expected.json
@@ -95,15 +95,15 @@
     "VpcPublicSubnet1NATGateway4D7517AA": {
       "Type": "AWS::EC2::NatGateway",
       "Properties": {
+        "SubnetId": {
+          "Ref": "VpcPublicSubnet1Subnet5C2D37C4"
+        },
         "AllocationId": {
           "Fn::GetAtt": [
             "VpcPublicSubnet1EIPD7E02669",
             "AllocationId"
           ]
         },
-        "SubnetId": {
-          "Ref": "VpcPublicSubnet1Subnet5C2D37C4"
-        },
         "Tags": [
           {
             "Key": "Name",
@@ -192,15 +192,15 @@
     "VpcPublicSubnet2NATGateway9182C01D": {
       "Type": "AWS::EC2::NatGateway",
       "Properties": {
+        "SubnetId": {
+          "Ref": "VpcPublicSubnet2Subnet691E08A3"
+        },
         "AllocationId": {
           "Fn::GetAtt": [
             "VpcPublicSubnet2EIP3C605A87",
             "AllocationId"
           ]
         },
-        "SubnetId": {
-          "Ref": "VpcPublicSubnet2Subnet691E08A3"
-        },
         "Tags": [
           {
             "Key": "Name",
@@ -1034,6 +1034,12 @@
       "Properties": {
         "Port": 80,
         "Protocol": "HTTP",
+        "TargetGroupAttributes": [
+          {
+            "Key": "stickiness.enabled",
+            "Value": "false"
+          }
+        ],
         "TargetType": "instance",
         "VpcId": {
           "Ref": "Vpc8378EB38"
diff --git a/packages/@aws-cdk/aws-ecs/test/fargate/integ.lb-awsvpc-nw.expected.json b/packages/@aws-cdk/aws-ecs/test/fargate/integ.lb-awsvpc-nw.expected.json
index b0e138464af2a..de47fd2260762 100644
--- a/packages/@aws-cdk/aws-ecs/test/fargate/integ.lb-awsvpc-nw.expected.json
+++ b/packages/@aws-cdk/aws-ecs/test/fargate/integ.lb-awsvpc-nw.expected.json
@@ -95,15 +95,15 @@
     "VpcPublicSubnet1NATGateway4D7517AA": {
       "Type": "AWS::EC2::NatGateway",
       "Properties": {
+        "SubnetId": {
+          "Ref": "VpcPublicSubnet1Subnet5C2D37C4"
+        },
         "AllocationId": {
           "Fn::GetAtt": [
             "VpcPublicSubnet1EIPD7E02669",
             "AllocationId"
           ]
         },
-        "SubnetId": {
-          "Ref": "VpcPublicSubnet1Subnet5C2D37C4"
-        },
         "Tags": [
           {
             "Key": "Name",
@@ -192,15 +192,15 @@
     "VpcPublicSubnet2NATGateway9182C01D": {
       "Type": "AWS::EC2::NatGateway",
       "Properties": {
+        "SubnetId": {
+          "Ref": "VpcPublicSubnet2Subnet691E08A3"
+        },
         "AllocationId": {
           "Fn::GetAtt": [
             "VpcPublicSubnet2EIP3C605A87",
             "AllocationId"
           ]
         },
-        "SubnetId": {
-          "Ref": "VpcPublicSubnet2Subnet691E08A3"
-        },
         "Tags": [
           {
             "Key": "Name",
@@ -649,6 +649,12 @@
       "Properties": {
         "Port": 80,
         "Protocol": "HTTP",
+        "TargetGroupAttributes": [
+          {
+            "Key": "stickiness.enabled",
+            "Value": "false"
+          }
+        ],
         "TargetType": "ip",
         "VpcId": {
           "Ref": "Vpc8378EB38"
diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2-targets/test/integ.alb-target.expected.json b/packages/@aws-cdk/aws-elasticloadbalancingv2-targets/test/integ.alb-target.expected.json
index 8832e3edf3726..ff70395ffda8b 100644
--- a/packages/@aws-cdk/aws-elasticloadbalancingv2-targets/test/integ.alb-target.expected.json
+++ b/packages/@aws-cdk/aws-elasticloadbalancingv2-targets/test/integ.alb-target.expected.json
@@ -462,6 +462,12 @@
       "Properties": {
         "Port": 80,
         "Protocol": "HTTP",
+        "TargetGroupAttributes": [
+          {
+            "Key": "stickiness.enabled",
+            "Value": "false"
+          }
+        ],
         "TargetType": "ip",
         "VpcId": {
           "Ref": "Vpc8378EB38"
diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2-targets/test/integ.lambda-target.expected.json b/packages/@aws-cdk/aws-elasticloadbalancingv2-targets/test/integ.lambda-target.expected.json
index cca2c6d366998..75905be0cd5ba 100644
--- a/packages/@aws-cdk/aws-elasticloadbalancingv2-targets/test/integ.lambda-target.expected.json
+++ b/packages/@aws-cdk/aws-elasticloadbalancingv2-targets/test/integ.lambda-target.expected.json
@@ -95,15 +95,15 @@
     "StackPublicSubnet1NATGatewayD2E1ABF7": {
       "Type": "AWS::EC2::NatGateway",
       "Properties": {
+        "SubnetId": {
+          "Ref": "StackPublicSubnet1Subnet0AD81D22"
+        },
         "AllocationId": {
           "Fn::GetAtt": [
             "StackPublicSubnet1EIPBDAAB2A5",
             "AllocationId"
           ]
         },
-        "SubnetId": {
-          "Ref": "StackPublicSubnet1Subnet0AD81D22"
-        },
         "Tags": [
           {
             "Key": "Name",
@@ -404,6 +404,12 @@
     "LBListenerTargetsGroup76EF81E8": {
       "Type": "AWS::ElasticLoadBalancingV2::TargetGroup",
       "Properties": {
+        "TargetGroupAttributes": [
+          {
+            "Key": "stickiness.enabled",
+            "Value": "false"
+          }
+        ],
         "Targets": [
           {
             "Id": {
@@ -457,13 +463,13 @@
         "Code": {
           "ZipFile": "\ndef handler(event, context):\n  return {\n    \"isBase64Encoded\": False,\n    \"statusCode\": 200,\n    \"statusDescription\": \"200 OK\",\n    \"headers\": {\n        \"Set-cookie\": \"cookies\",\n        \"Content-Type\": \"application/json\"\n    },\n    \"body\": \"Hello from Lambda\"\n  }\n      "
         },
-        "Handler": "index.handler",
         "Role": {
           "Fn::GetAtt": [
             "FunServiceRole3CC876D7",
             "Arn"
           ]
         },
+        "Handler": "index.handler",
         "Runtime": "python3.6"
       },
       "DependsOn": [
diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-target-group.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-target-group.ts
index d1329665ba7d6..025d655aef181 100644
--- a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-target-group.ts
+++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-target-group.ts
@@ -144,9 +144,13 @@ export class ApplicationTargetGroup extends TargetGroupBase implements IApplicat
         }
         this.setAttribute('slow_start.duration_seconds', props.slowStart.toSeconds().toString());
       }
+
       if (props.stickinessCookieDuration) {
         this.enableCookieStickiness(props.stickinessCookieDuration, props.stickinessCookieName);
+      } else {
+        this.setAttribute('stickiness.enabled', 'false');
       }
+
       if (props.loadBalancingAlgorithmType) {
         this.setAttribute('load_balancing.algorithm.type', props.loadBalancingAlgorithmType);
       }
diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/listener.test.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/listener.test.ts
index 885c872482e9c..c47585d98a5f7 100644
--- a/packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/listener.test.ts
+++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/listener.test.ts
@@ -862,6 +862,10 @@ describe('tests', () => {
           Key: 'deregistration_delay.timeout_seconds',
           Value: '30',
         },
+        {
+          Key: 'stickiness.enabled',
+          Value: 'false',
+        },
       ],
     });
   });
@@ -883,6 +887,10 @@ describe('tests', () => {
     // THEN
     expect(stack).toHaveResource('AWS::ElasticLoadBalancingV2::TargetGroup', {
       TargetGroupAttributes: [
+        {
+          Key: 'stickiness.enabled',
+          Value: 'false',
+        },
         {
           Key: 'load_balancing.algorithm.type',
           Value: 'least_outstanding_requests',
diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/target-group.test.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/target-group.test.ts
index 078be310dd3f8..313985e09d3ee 100644
--- a/packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/target-group.test.ts
+++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/target-group.test.ts
@@ -171,6 +171,10 @@ describe('tests', () => {
     // THEN
     expect(stack).toHaveResource('AWS::ElasticLoadBalancingV2::TargetGroup', {
       TargetGroupAttributes: [
+        {
+          Key: 'stickiness.enabled',
+          Value: 'false',
+        },
         {
           Key: 'load_balancing.algorithm.type',
           Value: 'least_outstanding_requests',
diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/test/integ.alb.dualstack.expected.json b/packages/@aws-cdk/aws-elasticloadbalancingv2/test/integ.alb.dualstack.expected.json
index 4358667cb43ed..780859bd7f314 100644
--- a/packages/@aws-cdk/aws-elasticloadbalancingv2/test/integ.alb.dualstack.expected.json
+++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/test/integ.alb.dualstack.expected.json
@@ -120,15 +120,15 @@
     "VPCPublicSubnet1NATGatewayE0556630": {
       "Type": "AWS::EC2::NatGateway",
       "Properties": {
+        "SubnetId": {
+          "Ref": "VPCPublicSubnet1SubnetB4246D30"
+        },
         "AllocationId": {
           "Fn::GetAtt": [
             "VPCPublicSubnet1EIP6AD938E8",
             "AllocationId"
           ]
         },
-        "SubnetId": {
-          "Ref": "VPCPublicSubnet1SubnetB4246D30"
-        },
         "Tags": [
           {
             "Key": "Name",
@@ -254,15 +254,15 @@
     "VPCPublicSubnet2NATGateway3C070193": {
       "Type": "AWS::EC2::NatGateway",
       "Properties": {
+        "SubnetId": {
+          "Ref": "VPCPublicSubnet2Subnet74179F39"
+        },
         "AllocationId": {
           "Fn::GetAtt": [
             "VPCPublicSubnet2EIP4947BC00",
             "AllocationId"
           ]
         },
-        "SubnetId": {
-          "Ref": "VPCPublicSubnet2Subnet74179F39"
-        },
         "Tags": [
           {
             "Key": "Name",
@@ -529,6 +529,12 @@
       "Properties": {
         "Port": 80,
         "Protocol": "HTTP",
+        "TargetGroupAttributes": [
+          {
+            "Key": "stickiness.enabled",
+            "Value": "false"
+          }
+        ],
         "Targets": [
           {
             "Id": "10.0.128.4"
@@ -545,6 +551,12 @@
       "Properties": {
         "Port": 80,
         "Protocol": "HTTP",
+        "TargetGroupAttributes": [
+          {
+            "Key": "stickiness.enabled",
+            "Value": "false"
+          }
+        ],
         "Targets": [
           {
             "Id": "10.0.128.5"
diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/test/integ.alb2.expected.json b/packages/@aws-cdk/aws-elasticloadbalancingv2/test/integ.alb2.expected.json
index ef8989719a37e..9aa4015d15f18 100644
--- a/packages/@aws-cdk/aws-elasticloadbalancingv2/test/integ.alb2.expected.json
+++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/test/integ.alb2.expected.json
@@ -95,15 +95,15 @@
     "VPCPublicSubnet1NATGatewayE0556630": {
       "Type": "AWS::EC2::NatGateway",
       "Properties": {
+        "SubnetId": {
+          "Ref": "VPCPublicSubnet1SubnetB4246D30"
+        },
         "AllocationId": {
           "Fn::GetAtt": [
             "VPCPublicSubnet1EIP6AD938E8",
             "AllocationId"
           ]
         },
-        "SubnetId": {
-          "Ref": "VPCPublicSubnet1SubnetB4246D30"
-        },
         "Tags": [
           {
             "Key": "Name",
@@ -192,15 +192,15 @@
     "VPCPublicSubnet2NATGateway3C070193": {
       "Type": "AWS::EC2::NatGateway",
       "Properties": {
+        "SubnetId": {
+          "Ref": "VPCPublicSubnet2Subnet74179F39"
+        },
         "AllocationId": {
           "Fn::GetAtt": [
             "VPCPublicSubnet2EIP4947BC00",
             "AllocationId"
           ]
         },
-        "SubnetId": {
-          "Ref": "VPCPublicSubnet2Subnet74179F39"
-        },
         "Tags": [
           {
             "Key": "Name",
@@ -438,6 +438,12 @@
       "Properties": {
         "Port": 80,
         "Protocol": "HTTP",
+        "TargetGroupAttributes": [
+          {
+            "Key": "stickiness.enabled",
+            "Value": "false"
+          }
+        ],
         "Targets": [
           {
             "Id": "10.0.128.4"
@@ -454,6 +460,12 @@
       "Properties": {
         "Port": 80,
         "Protocol": "HTTP",
+        "TargetGroupAttributes": [
+          {
+            "Key": "stickiness.enabled",
+            "Value": "false"
+          }
+        ],
         "Targets": [
           {
             "Id": "10.0.128.5"

From 7a333b018c9bb2430165177d3e65614cf1d66519 Mon Sep 17 00:00:00 2001
From: Jonathan Goldwasser 
Date: Fri, 29 Oct 2021 13:28:43 +0200
Subject: [PATCH 84/87] feat(core): subtract Durations (#16734)

Add a `.minus()` method to `Duration`.

Closes #16535


----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
---
 packages/@aws-cdk/core/README.md             |  9 ++++++++-
 packages/@aws-cdk/core/lib/duration.ts       | 13 +++++++++++--
 packages/@aws-cdk/core/test/duration.test.ts |  6 +++++-
 packages/aws-cdk-lib/README.md               |  9 ++++++++-
 4 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/packages/@aws-cdk/core/README.md b/packages/@aws-cdk/core/README.md
index 79ac6e6bb3e4d..611467116459e 100644
--- a/packages/@aws-cdk/core/README.md
+++ b/packages/@aws-cdk/core/README.md
@@ -172,6 +172,13 @@ Duration.days(7)        // 7 days
 Duration.parse('PT5M')  // 5 minutes
 ```
 
+Durations can be added or subtracted together:
+
+```ts
+Duration.minutes(1).plus(Duration.seconds(60)); // 2 minutes
+Duration.minutes(5).minus(Duration.seconds(10)); // 290 secondes
+```
+
 ## Size (Digital Information Quantity)
 
 To make specification of digital storage quantities unambiguous, a class called
@@ -805,7 +812,7 @@ regionTable.findInMap('us-east-2', 'regionName');
 ```
 
 On the other hand, the following code will produce the "Mappings" section shown above,
-since the top-level key is an unresolved token. The call to `findInMap` will return a token that resolves to 
+since the top-level key is an unresolved token. The call to `findInMap` will return a token that resolves to
 `{ "Fn::FindInMap": [ "RegionTable", { "Ref": "AWS::Region" }, "regionName" ] }`.
 
 ```ts
diff --git a/packages/@aws-cdk/core/lib/duration.ts b/packages/@aws-cdk/core/lib/duration.ts
index 0061e7928e900..5c7bb804b917c 100644
--- a/packages/@aws-cdk/core/lib/duration.ts
+++ b/packages/@aws-cdk/core/lib/duration.ts
@@ -105,8 +105,17 @@ export class Duration {
    */
   public plus(rhs: Duration): Duration {
     const targetUnit = finestUnit(this.unit, rhs.unit);
-    const total = convert(this.amount, this.unit, targetUnit, {}) + convert(rhs.amount, rhs.unit, targetUnit, {});
-    return new Duration(total, targetUnit);
+    const res = convert(this.amount, this.unit, targetUnit, {}) + convert(rhs.amount, rhs.unit, targetUnit, {});
+    return new Duration(res, targetUnit);
+  }
+
+  /**
+   * Substract two Durations together
+   */
+  public minus(rhs: Duration): Duration {
+    const targetUnit = finestUnit(this.unit, rhs.unit);
+    const res = convert(this.amount, this.unit, targetUnit, {}) - convert(rhs.amount, rhs.unit, targetUnit, {});
+    return new Duration(res, targetUnit);
   }
 
   /**
diff --git a/packages/@aws-cdk/core/test/duration.test.ts b/packages/@aws-cdk/core/test/duration.test.ts
index 68da12881d3ba..c7cf230308634 100644
--- a/packages/@aws-cdk/core/test/duration.test.ts
+++ b/packages/@aws-cdk/core/test/duration.test.ts
@@ -170,8 +170,12 @@ describe('duration', () => {
     expect(Duration.minutes(1).plus(Duration.seconds(30)).toSeconds()).toEqual(Duration.seconds(90).toSeconds());
     expect(Duration.minutes(1).plus(Duration.seconds(30)).toMinutes({ integral: false }))
       .toEqual(Duration.seconds(90).toMinutes({ integral: false }));
+  });
 
-
+  test('subtract two durations', () => {
+    expect(Duration.minutes(1).minus(Duration.seconds(30)).toSeconds()).toEqual(Duration.seconds(30).toSeconds());
+    expect(Duration.minutes(1).minus(Duration.seconds(30)).toMinutes({ integral: false }))
+      .toEqual(Duration.seconds(30).toMinutes({ integral: false }));
   });
 
   test('get unit label from duration', () => {
diff --git a/packages/aws-cdk-lib/README.md b/packages/aws-cdk-lib/README.md
index 40fc7c0d880af..254a58738b26d 100644
--- a/packages/aws-cdk-lib/README.md
+++ b/packages/aws-cdk-lib/README.md
@@ -205,6 +205,13 @@ Duration.days(7)        // 7 days
 Duration.parse('PT5M')  // 5 minutes
 ```
 
+Durations can be added or subtracted together:
+
+```ts
+Duration.minutes(1).plus(Duration.seconds(60)); // 2 minutes
+Duration.minutes(5).minus(Duration.seconds(10)); // 290 secondes
+```
+
 ## Size (Digital Information Quantity)
 
 To make specification of digital storage quantities unambiguous, a class called
@@ -838,7 +845,7 @@ regionTable.findInMap('us-east-2', 'regionName');
 ```
 
 On the other hand, the following code will produce the "Mappings" section shown above,
-since the top-level key is an unresolved token. The call to `findInMap` will return a token that resolves to 
+since the top-level key is an unresolved token. The call to `findInMap` will return a token that resolves to
 `{ "Fn::FindInMap": [ "RegionTable", { "Ref": "AWS::Region" }, "regionName" ] }`.
 
 ```ts

From 56974ac4152bc082470d56dd66e4ef7aad042815 Mon Sep 17 00:00:00 2001
From: Makoto Nagai 
Date: Fri, 29 Oct 2021 14:26:41 +0200
Subject: [PATCH 85/87] fix(lambda-event-sources): dynamo batch size cannot be
 a CfnParameter (#16540)

fixes #16221

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
---
 .../aws-lambda-event-sources/lib/dynamodb.ts  |  6 ++-
 .../test/dynamo.test.ts                       | 43 +++++++++++++++++++
 2 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/packages/@aws-cdk/aws-lambda-event-sources/lib/dynamodb.ts b/packages/@aws-cdk/aws-lambda-event-sources/lib/dynamodb.ts
index f316ba69cf9ed..3d0fd78c915fc 100644
--- a/packages/@aws-cdk/aws-lambda-event-sources/lib/dynamodb.ts
+++ b/packages/@aws-cdk/aws-lambda-event-sources/lib/dynamodb.ts
@@ -1,6 +1,6 @@
 import * as dynamodb from '@aws-cdk/aws-dynamodb';
 import * as lambda from '@aws-cdk/aws-lambda';
-import { Names } from '@aws-cdk/core';
+import { Names, Token } from '@aws-cdk/core';
 import { StreamEventSource, StreamEventSourceProps } from './stream';
 
 export interface DynamoEventSourceProps extends StreamEventSourceProps {
@@ -15,7 +15,9 @@ export class DynamoEventSource extends StreamEventSource {
   constructor(private readonly table: dynamodb.ITable, props: DynamoEventSourceProps) {
     super(props);
 
-    if (this.props.batchSize !== undefined && (this.props.batchSize < 1 || this.props.batchSize > 1000)) {
+    if (this.props.batchSize !== undefined
+      && !Token.isUnresolved(this.props.batchSize)
+      && (this.props.batchSize < 1 || this.props.batchSize > 1000)) {
       throw new Error(`Maximum batch size must be between 1 and 1000 inclusive (given ${this.props.batchSize})`);
     }
   }
diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/dynamo.test.ts b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamo.test.ts
index 3e90ab5a4ab3b..97bd42c07145f 100644
--- a/packages/@aws-cdk/aws-lambda-event-sources/test/dynamo.test.ts
+++ b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamo.test.ts
@@ -136,6 +136,49 @@ describe('DynamoEventSource', () => {
     });
 
 
+  });
+
+  test('pass validation if batchsize is token', () => {
+    // GIVEN
+    const stack = new cdk.Stack();
+    const fn = new TestFunction(stack, 'Fn');
+    const table = new dynamodb.Table(stack, 'T', {
+      partitionKey: {
+        name: 'id',
+        type: dynamodb.AttributeType.STRING,
+      },
+      stream: dynamodb.StreamViewType.NEW_IMAGE,
+    });
+    const batchSize = new cdk.CfnParameter(stack, 'BatchSize', {
+      type: 'Number',
+      default: 100,
+      minValue: 1,
+      maxValue: 1000,
+    });
+    // WHEN
+    fn.addEventSource(new sources.DynamoEventSource(table, {
+      batchSize: batchSize.valueAsNumber,
+      startingPosition: lambda.StartingPosition.LATEST,
+    }));
+
+    // THEN
+    Template.fromStack(stack).hasResourceProperties('AWS::Lambda::EventSourceMapping', {
+      'EventSourceArn': {
+        'Fn::GetAtt': [
+          'TD925BC7E',
+          'StreamArn',
+        ],
+      },
+      'FunctionName': {
+        'Ref': 'Fn9270CBC0',
+      },
+      'BatchSize': {
+        'Ref': 'BatchSize',
+      },
+      'StartingPosition': 'LATEST',
+    });
+
+
   });
 
   test('fails if streaming not enabled on table', () => {

From 56033a2a6d4be0444694d9f88260c574a4fa1a1d Mon Sep 17 00:00:00 2001
From: Jonathan Goldwasser 
Date: Fri, 29 Oct 2021 15:20:26 +0200
Subject: [PATCH 86/87] feat(lambda-nodejs): esbuild charset option (#16726)

Support `esbuild` charset option.

Closes #16668


----

*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-lambda-nodejs/README.md |  5 ++-
 .../aws-lambda-nodejs/lib/bundling.ts         |  1 +
 .../@aws-cdk/aws-lambda-nodejs/lib/types.ts   | 38 +++++++++++++++++--
 .../aws-lambda-nodejs/test/bundling.test.ts   |  4 +-
 4 files changed, 42 insertions(+), 6 deletions(-)

diff --git a/packages/@aws-cdk/aws-lambda-nodejs/README.md b/packages/@aws-cdk/aws-lambda-nodejs/README.md
index 6e901612539d8..9bf47f0631d57 100644
--- a/packages/@aws-cdk/aws-lambda-nodejs/README.md
+++ b/packages/@aws-cdk/aws-lambda-nodejs/README.md
@@ -187,8 +187,9 @@ new lambda.NodejsFunction(this, 'my-handler', {
     keepNames: true, // defaults to false
     tsconfig: 'custom-tsconfig.json', // use custom-tsconfig.json instead of default,
     metafile: true, // include meta file, defaults to false
-    banner : '/* comments */', // requires esbuild >= 0.9.0, defaults to none
-    footer : '/* comments */', // requires esbuild >= 0.9.0, defaults to none
+    banner: '/* comments */', // requires esbuild >= 0.9.0, defaults to none
+    footer: '/* comments */', // requires esbuild >= 0.9.0, defaults to none
+    charset: Charset.UTF8, // do not escape non-ASCII characters, defaults to Charset.ASCII
   },
 });
 ```
diff --git a/packages/@aws-cdk/aws-lambda-nodejs/lib/bundling.ts b/packages/@aws-cdk/aws-lambda-nodejs/lib/bundling.ts
index e53e5e092de7c..3bd05a7ccb39d 100644
--- a/packages/@aws-cdk/aws-lambda-nodejs/lib/bundling.ts
+++ b/packages/@aws-cdk/aws-lambda-nodejs/lib/bundling.ts
@@ -200,6 +200,7 @@ export class Bundling implements cdk.BundlingOptions {
       ...this.props.metafile ? [`--metafile=${pathJoin(options.outputDir, 'index.meta.json')}`] : [],
       ...this.props.banner ? [`--banner:js=${JSON.stringify(this.props.banner)}`] : [],
       ...this.props.footer ? [`--footer:js=${JSON.stringify(this.props.footer)}`] : [],
+      ...this.props.charset ? [`--charset=${this.props.charset}`] : [],
     ];
 
     let depsCommand = '';
diff --git a/packages/@aws-cdk/aws-lambda-nodejs/lib/types.ts b/packages/@aws-cdk/aws-lambda-nodejs/lib/types.ts
index 6bd26c846c6fe..55606f66b2507 100644
--- a/packages/@aws-cdk/aws-lambda-nodejs/lib/types.ts
+++ b/packages/@aws-cdk/aws-lambda-nodejs/lib/types.ts
@@ -113,7 +113,7 @@ export interface BundlingOptions {
    * bundle buddy can consume esbuild's metadata format and generates a treemap visualization
    * of the modules in your bundle and how much space each one takes up.
    * @see https://esbuild.github.io/api/#metafile
-   * @default - false
+   * @default false
    */
   readonly metafile?: boolean
 
@@ -124,7 +124,7 @@ export interface BundlingOptions {
    *
    * This is commonly used to insert comments:
    *
-   * @default -  no comments are passed
+   * @default - no comments are passed
    */
   readonly banner? : string
 
@@ -135,10 +135,23 @@ export interface BundlingOptions {
    *
    * This is commonly used to insert comments
    *
-   * @default -  no comments are passed
+   * @default - no comments are passed
    */
   readonly footer? : string
 
+  /**
+   * The charset to use for esbuild's output.
+   *
+   * By default esbuild's output is ASCII-only. Any non-ASCII characters are escaped
+   * using backslash escape sequences. Using escape sequences makes the generated output
+   * slightly bigger, and also makes it harder to read. If you would like for esbuild to print
+   * the original characters without using escape sequences, use `Charset.UTF8`.
+   *
+   * @see https://esbuild.github.io/api/#charset
+   * @default Charset.ASCII
+   */
+  readonly charset?: Charset;
+
   /**
    * Environment variables defined when bundling runs.
    *
@@ -310,3 +323,22 @@ export enum SourceMapMode {
    */
   BOTH = 'both'
 }
+
+/**
+ * Charset for esbuild's output
+ */
+export enum Charset {
+  /**
+   * ASCII
+   *
+   * Any non-ASCII characters are escaped using backslash escape sequences
+   */
+  ASCII = 'ascii',
+
+  /**
+   * UTF-8
+   *
+   * Keep original characters without using escape sequences
+   */
+  UTF8 = 'utf8'
+}
diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/bundling.test.ts b/packages/@aws-cdk/aws-lambda-nodejs/test/bundling.test.ts
index 02b6030ae3e12..f4e974c08fdce 100644
--- a/packages/@aws-cdk/aws-lambda-nodejs/test/bundling.test.ts
+++ b/packages/@aws-cdk/aws-lambda-nodejs/test/bundling.test.ts
@@ -6,7 +6,7 @@ import { AssetHashType, DockerImage } from '@aws-cdk/core';
 import { version as delayVersion } from 'delay/package.json';
 import { Bundling } from '../lib/bundling';
 import { PackageInstallation } from '../lib/package-installation';
-import { LogLevel, SourceMapMode } from '../lib/types';
+import { Charset, LogLevel, SourceMapMode } from '../lib/types';
 import * as util from '../lib/util';
 
 
@@ -198,6 +198,7 @@ test('esbuild bundling with esbuild options', () => {
     metafile: true,
     banner: '/* comments */',
     footer: '/* comments */',
+    charset: Charset.UTF8,
     forceDockerBundling: true,
     define: {
       'process.env.KEY': JSON.stringify('VALUE'),
@@ -221,6 +222,7 @@ test('esbuild bundling with esbuild options', () => {
           defineInstructions,
           '--log-level=silent --keep-names --tsconfig=/asset-input/lib/custom-tsconfig.ts',
           '--metafile=/asset-output/index.meta.json --banner:js="/* comments */" --footer:js="/* comments */"',
+          '--charset=utf8',
         ].join(' '),
       ],
     }),

From 54f7f5a7774a00d62808c11aeb057850aefb5216 Mon Sep 17 00:00:00 2001
From: AWS CDK Team 
Date: Fri, 29 Oct 2021 15:50:10 +0000
Subject: [PATCH 87/87] chore(release): 1.130.0

---
 CHANGELOG.md    | 44 ++++++++++++++++++++++++++++++++++++++++++++
 version.v1.json |  2 +-
 2 files changed, 45 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 511ed1a25dabd..4c9ab93b5e534 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,50 @@
 
 All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
 
+## [1.130.0](https://github.com/aws/aws-cdk/compare/v1.129.0...v1.130.0) (2021-10-29)
+
+
+### Features
+
+* **amplify:** Add support for custom headers in the App ([#17102](https://github.com/aws/aws-cdk/issues/17102)) ([9f3abd7](https://github.com/aws/aws-cdk/commit/9f3abd745c98a65e7314528f40d08ea2ecbe19a6)), closes [#17084](https://github.com/aws/aws-cdk/issues/17084)
+* **aws-route53-targets:** Support for Elastic Beanstalk environment URLs ([#16305](https://github.com/aws/aws-cdk/issues/16305)) ([bc07cb0](https://github.com/aws/aws-cdk/commit/bc07cb0e383aa64280a9c7f8ac4870d296830cf7))
+* **cli:** deployment progress shows stack name ([#16604](https://github.com/aws/aws-cdk/issues/16604)) ([322cf10](https://github.com/aws/aws-cdk/commit/322cf10ef3257b9d20d898882a14de91110a0033))
+* **cloudfront:** add amplify managed cache policy  ([#16880](https://github.com/aws/aws-cdk/issues/16880)) ([8d0c555](https://github.com/aws/aws-cdk/commit/8d0c555d048c07518c89e69951a1e9f21ba99bd7))
+* **codebuild:** add fromEcrRepository to LinuxGpuBuildImage ([#17170](https://github.com/aws/aws-cdk/issues/17170)) ([7585680](https://github.com/aws/aws-cdk/commit/758568007bf82a97ed6edba3ef4717735b224bf9)), closes [#16500](https://github.com/aws/aws-cdk/issues/16500)
+* **core:** Docker tags can be prefixed ([#17028](https://github.com/aws/aws-cdk/issues/17028)) ([d298696](https://github.com/aws/aws-cdk/commit/d298696a7d8978296a34294484cea80f91ebe880))
+* **core:** subtract Durations ([#16734](https://github.com/aws/aws-cdk/issues/16734)) ([7a333b0](https://github.com/aws/aws-cdk/commit/7a333b018c9bb2430165177d3e65614cf1d66519)), closes [#16535](https://github.com/aws/aws-cdk/issues/16535)
+* **ec2:** add c5ad instances ([#16428](https://github.com/aws/aws-cdk/issues/16428)) ([0318253](https://github.com/aws/aws-cdk/commit/0318253b423bb65ca7e6bf65411df767f2734296))
+* **ec2:** add region parameter for UserData via addS3DownloadCommand  ([#16667](https://github.com/aws/aws-cdk/issues/16667)) ([691d377](https://github.com/aws/aws-cdk/commit/691d3771d32002b3cd4cb1221af92762b749e716)), closes [#8287](https://github.com/aws/aws-cdk/issues/8287)
+* **ec2:** add vpcArn to IVpc and Vpc ([#16666](https://github.com/aws/aws-cdk/issues/16666)) ([7b31376](https://github.com/aws/aws-cdk/commit/7b31376e6349440f7b215d6e11c3dd900d50df34)), closes [#16493](https://github.com/aws/aws-cdk/issues/16493)
+* **ec2:** add X2g instances (for RDS) ([#17081](https://github.com/aws/aws-cdk/issues/17081)) ([443a23e](https://github.com/aws/aws-cdk/commit/443a23e8c1e0de97f6ae05a3e451b0407165a447)), closes [/github.com/aws/aws-cdk/issues/16948#issuecomment-946254267](https://github.com/aws//github.com/aws/aws-cdk/issues/16948/issues/issuecomment-946254267) [#16948](https://github.com/aws/aws-cdk/issues/16948)
+* **ec2:** include p4d instance class ([#17147](https://github.com/aws/aws-cdk/issues/17147)) ([6e13adc](https://github.com/aws/aws-cdk/commit/6e13adc281722a491c0708954d7ed637ad45033b))
+* **ec2:** look up VPC from different regions ([#16728](https://github.com/aws/aws-cdk/issues/16728)) ([f1e244b](https://github.com/aws/aws-cdk/commit/f1e244b331f95253030bae0525775683b5a350c4)), closes [#10208](https://github.com/aws/aws-cdk/issues/10208)
+* **ec2:** VPC endpoint for AWS Xray  ([#16788](https://github.com/aws/aws-cdk/issues/16788)) ([c24af54](https://github.com/aws/aws-cdk/commit/c24af54946d3668afa596dbf2a776b7cf21f8a99)), closes [#16306](https://github.com/aws/aws-cdk/issues/16306)
+* **events:** DLQ support for EventBus target  ([#16383](https://github.com/aws/aws-cdk/issues/16383)) ([dbb3f25](https://github.com/aws/aws-cdk/commit/dbb3f25904403bfc020a081e94270f5c16a7606f)), closes [#15954](https://github.com/aws/aws-cdk/issues/15954)
+* **iot:** add the TopicRule L2 construct ([#16681](https://github.com/aws/aws-cdk/issues/16681)) ([86f85ce](https://github.com/aws/aws-cdk/commit/86f85ce10f78b86133f9dab9851e56d03fb28cc0)), closes [#16602](https://github.com/aws/aws-cdk/issues/16602)
+* **iot:** allow setting Actions of TopicRule ([#17110](https://github.com/aws/aws-cdk/issues/17110)) ([0cabb9f](https://github.com/aws/aws-cdk/commit/0cabb9f2d2f50c03337cd6f35bf47fc54ada3a21)), closes [#16681](https://github.com/aws/aws-cdk/issues/16681) [/github.com/aws/aws-cdk/pull/16681#discussion_r733912215](https://github.com/aws//github.com/aws/aws-cdk/pull/16681/issues/discussion_r733912215)
+* **iot:** create new aws-iot-actions module ([#17112](https://github.com/aws/aws-cdk/issues/17112)) ([06838e6](https://github.com/aws/aws-cdk/commit/06838e66db0c9a48e2aa7da1e7707fda335bb62c)), closes [#16681](https://github.com/aws/aws-cdk/issues/16681) [/github.com/aws/aws-cdk/pull/16681#discussion_r733912215](https://github.com/aws//github.com/aws/aws-cdk/pull/16681/issues/discussion_r733912215)
+* **lambda-nodejs:** esbuild charset option ([#16726](https://github.com/aws/aws-cdk/issues/16726)) ([56033a2](https://github.com/aws/aws-cdk/commit/56033a2a6d4be0444694d9f88260c574a4fa1a1d)), closes [#16668](https://github.com/aws/aws-cdk/issues/16668)
+* **lambda-nodejs:** typescript emitDecoratorMetadata support ([#16543](https://github.com/aws/aws-cdk/issues/16543)) ([55d3c50](https://github.com/aws/aws-cdk/commit/55d3c507707192d7aa5ea4a38ee0d1cb58f07e06)), closes [#13767](https://github.com/aws/aws-cdk/issues/13767)
+* **rds:** support backtrackWindow in DatabaseCluster ([#17160](https://github.com/aws/aws-cdk/issues/17160)) ([fcd17e9](https://github.com/aws/aws-cdk/commit/fcd17e9c9a9e1b83a29c140d558f696c0290bfd7)), closes [#9369](https://github.com/aws/aws-cdk/issues/9369) [#9369](https://github.com/aws/aws-cdk/issues/9369)
+* **route53:** Expose VpcEndpointServiceDomainName domain name as a property  ([#16458](https://github.com/aws/aws-cdk/issues/16458)) ([e063fbd](https://github.com/aws/aws-cdk/commit/e063fbd3a31bdce046b2598e4a429c45d016f055))
+* **sns:** addSubscription returns the created Subscription ([#16785](https://github.com/aws/aws-cdk/issues/16785)) ([62f389e](https://github.com/aws/aws-cdk/commit/62f389ea0522cbaefca5ca17080228031d401ce6))
+* **synthetics:** add syn-nodejs-puppeteer-3.3 runtime ([#17132](https://github.com/aws/aws-cdk/issues/17132)) ([8343bec](https://github.com/aws/aws-cdk/commit/8343beccbee06f453b63387f54768b320fe01339))
+
+
+### Bug Fixes
+
+* **cli:** downgrade bootstrap stack error message needs a hint for new-style synthesis ([#16237](https://github.com/aws/aws-cdk/issues/16237)) ([e55301b](https://github.com/aws/aws-cdk/commit/e55301b635374a87822f78870981a9e06e13d99e))
+* **core:** `DefaultSynthesizer` deployments are never skipped ([#17099](https://github.com/aws/aws-cdk/issues/17099)) ([c74b012](https://github.com/aws/aws-cdk/commit/c74b0127af95f8e86b95a0be2f2c6cb30fab1103)), closes [#16959](https://github.com/aws/aws-cdk/issues/16959)
+* **core:** SecretValue.secretsManager fails for tokenized secret-id  ([#16230](https://github.com/aws/aws-cdk/issues/16230)) ([5831456](https://github.com/aws/aws-cdk/commit/5831456465fa44af96a268de56db0e3a8d3c2ea6)), closes [#16166](https://github.com/aws/aws-cdk/issues/16166)
+* **custom-resources:** invalid service name leads to unhelpful error message ([#16718](https://github.com/aws/aws-cdk/issues/16718)) ([354686b](https://github.com/aws/aws-cdk/commit/354686b189377dd1daae7ba616e8fb62488d9855)), closes [#7312](https://github.com/aws/aws-cdk/issues/7312)
+* **custom-resources:** Role Session Name can exceed maximum size ([#16680](https://github.com/aws/aws-cdk/issues/16680)) ([3617b70](https://github.com/aws/aws-cdk/commit/3617b70527516237955b8415fcfc8b58d3e23b3c))
+* **elasticloadbalancingv2:** always set stickiness ([#17111](https://github.com/aws/aws-cdk/issues/17111)) ([0a23953](https://github.com/aws/aws-cdk/commit/0a23953d92df070736f7d036cc2b24e68de4bf64)), closes [#16620](https://github.com/aws/aws-cdk/issues/16620)
+* **lambda-event-sources:** dynamo batch size cannot be a CfnParameter ([#16540](https://github.com/aws/aws-cdk/issues/16540)) ([56974ac](https://github.com/aws/aws-cdk/commit/56974ac4152bc082470d56dd66e4ef7aad042815)), closes [#16221](https://github.com/aws/aws-cdk/issues/16221)
+* **logs:** Apply tags to log retention Lambda  ([#17029](https://github.com/aws/aws-cdk/issues/17029)) ([a6aaa64](https://github.com/aws/aws-cdk/commit/a6aaa64bf9779b984f20d18881b4f6e510ac091a)), closes [#15032](https://github.com/aws/aws-cdk/issues/15032)
+* **rds:** using both Instance imports & exports for Postgres fails deployment ([#17060](https://github.com/aws/aws-cdk/issues/17060)) ([ab627c6](https://github.com/aws/aws-cdk/commit/ab627c69e9edac82b1fd07d2c9ee1b05f7dc3166)), closes [#16757](https://github.com/aws/aws-cdk/issues/16757)
+* **redshift:** cluster uses key ARN instead of key ID ([#17108](https://github.com/aws/aws-cdk/issues/17108)) ([bdf30c6](https://github.com/aws/aws-cdk/commit/bdf30c696b04b26a8e41548839d5c4cf61d471cc)), closes [#17032](https://github.com/aws/aws-cdk/issues/17032)
+
 ## [1.129.0](https://github.com/aws/aws-cdk/compare/v1.128.0...v1.129.0) (2021-10-21)
 
 
diff --git a/version.v1.json b/version.v1.json
index cdb974a76d7f9..cf3002b8d98b8 100644
--- a/version.v1.json
+++ b/version.v1.json
@@ -1,3 +1,3 @@
 {
-  "version": "1.129.0"
+  "version": "1.130.0"
 }
\ No newline at end of file