From b8f02eca3445553df591721dcd0733fc0deb028b Mon Sep 17 00:00:00 2001 From: Christopher Rybicki Date: Wed, 22 Sep 2021 14:35:46 -0700 Subject: [PATCH 01/89] 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 72102c750bfd6564cd51c1a5d8abc79b1ba1d3ce Mon Sep 17 00:00:00 2001 From: Ayush Goyal Date: Sun, 17 Oct 2021 20:32:03 +0530 Subject: [PATCH 02/89] feat(eks): configure serviceIpv4Cidr on the cluster (#16957) Refs: 1. https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-eks-cluster-kubernetesnetworkconfig.html 2. https://docs.aws.amazon.com/eks/latest/APIReference/API_KubernetesNetworkConfigRequest.html#AmazonEKS-Type-KubernetesNetworkConfigRequest-serviceIpv4Cidr Notes: 1. Currently I have not updated the integ tests since the deployed takes a lot of time and it requires inferentia service limit increase. Do you think this change needs an integ tests updating (tried it out locally and it succeeded till auto-scaling)? 2. Couldn't find a good place in the Readme to add this feature. Would really help if we could come up with a good explanation and place for the same. Closes #16541 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../@aws-cdk/aws-eks/lib/cluster-resource.ts | 2 ++ packages/@aws-cdk/aws-eks/lib/cluster.ts | 12 ++++++++++ .../@aws-cdk/aws-eks/test/cluster.test.ts | 22 +++++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/packages/@aws-cdk/aws-eks/lib/cluster-resource.ts b/packages/@aws-cdk/aws-eks/lib/cluster-resource.ts index 662f4e345a24c..88f3cd0138344 100644 --- a/packages/@aws-cdk/aws-eks/lib/cluster-resource.ts +++ b/packages/@aws-cdk/aws-eks/lib/cluster-resource.ts @@ -16,6 +16,7 @@ export interface ClusterResourceProps { readonly resourcesVpcConfig: CfnCluster.ResourcesVpcConfigProperty; readonly roleArn: string; readonly encryptionConfig?: Array; + readonly kubernetesNetworkConfig?: CfnCluster.KubernetesNetworkConfigProperty; readonly name: string; readonly version?: string; readonly endpointPrivateAccess: boolean; @@ -78,6 +79,7 @@ export class ClusterResource extends CoreConstruct { version: props.version, roleArn: props.roleArn, encryptionConfig: props.encryptionConfig, + kubernetesNetworkConfig: props.kubernetesNetworkConfig, resourcesVpcConfig: { subnetIds: (props.resourcesVpcConfig as CfnCluster.ResourcesVpcConfigProperty).subnetIds, securityGroupIds: (props.resourcesVpcConfig as CfnCluster.ResourcesVpcConfigProperty).securityGroupIds, diff --git a/packages/@aws-cdk/aws-eks/lib/cluster.ts b/packages/@aws-cdk/aws-eks/lib/cluster.ts index 2db0438537f97..76c59f740f6f2 100644 --- a/packages/@aws-cdk/aws-eks/lib/cluster.ts +++ b/packages/@aws-cdk/aws-eks/lib/cluster.ts @@ -540,6 +540,15 @@ export interface ClusterOptions extends CommonClusterOptions { * using AWS-Managed encryption keys. */ readonly secretsEncryptionKey?: kms.IKey; + + /** + * The CIDR block to assign Kubernetes service IP addresses from. + * + * @default - Kubernetes assigns addresses from either the + * 10.100.0.0/16 or 172.20.0.0/16 CIDR blocks + * @see https://docs.aws.amazon.com/eks/latest/APIReference/API_KubernetesNetworkConfigRequest.html#AmazonEKS-Type-KubernetesNetworkConfigRequest-serviceIpv4Cidr + */ + readonly serviceIpv4Cidr?: string; } /** @@ -1223,6 +1232,9 @@ export class Cluster extends ClusterBase { resources: ['secrets'], }], } : {}), + kubernetesNetworkConfig: props.serviceIpv4Cidr ? { + serviceIpv4Cidr: props.serviceIpv4Cidr, + } : undefined, endpointPrivateAccess: this.endpointAccess._config.privateAccess, endpointPublicAccess: this.endpointAccess._config.publicAccess, publicAccessCidrs: this.endpointAccess._config.publicCidrs, diff --git a/packages/@aws-cdk/aws-eks/test/cluster.test.ts b/packages/@aws-cdk/aws-eks/test/cluster.test.ts index 14e2bfad0746b..295092509ffd2 100644 --- a/packages/@aws-cdk/aws-eks/test/cluster.test.ts +++ b/packages/@aws-cdk/aws-eks/test/cluster.test.ts @@ -2888,4 +2888,26 @@ describe('cluster', () => { expect(providerNestedStackTemplate?.Resources?.Handler886CB40B?.Properties?.MemorySize).toEqual(4096); }); + + test('create a cluster using custom kubernetes network config', () => { + // GIVEN + const { stack } = testFixture(); + const customCidr = '172.16.0.0/12'; + + // WHEN + new eks.Cluster(stack, 'Cluster', { + version: CLUSTER_VERSION, + serviceIpv4Cidr: customCidr, + }); + + // THEN + expect(stack).toHaveResourceLike('Custom::AWSCDK-EKS-Cluster', { + Config: { + kubernetesNetworkConfig: { + serviceIpv4Cidr: customCidr, + }, + }, + }); + + }); }); From 999e99924804d8ee2c2962fa7ed86023b3f7d590 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Mon, 18 Oct 2021 11:10:24 +0200 Subject: [PATCH 03/89] chore(pipelines): deprecate legacy API (#17034) The presence of the legacy API for CDK Pipelines confuses people who didn't read the README or the blog post, but go from a copy/pasted example they found on the internet and then proceed to explore the API. Clearly deprecate the legacy classes to avoid confusion. ---- *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 | 6 +++--- .../legacy/actions/deploy-cdk-stack-action.ts | 10 ++++++++++ .../legacy/actions/publish-assets-action.ts | 4 ++++ .../legacy/actions/update-pipeline-action.ts | 4 ++++ .../@aws-cdk/pipelines/lib/legacy/pipeline.ts | 4 ++++ .../@aws-cdk/pipelines/lib/legacy/stage.ts | 18 ++++++++++++++++++ .../lib/legacy/synths/simple-synth-action.ts | 12 ++++++++++++ .../legacy/validation/shell-script-action.ts | 4 ++++ 8 files changed, 59 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk/cx-api/lib/features.ts b/packages/@aws-cdk/cx-api/lib/features.ts index 554c41929651d..986be7f4e136b 100644 --- a/packages/@aws-cdk/cx-api/lib/features.ts +++ b/packages/@aws-cdk/cx-api/lib/features.ts @@ -175,9 +175,9 @@ export const CLOUDFRONT_DEFAULT_SECURITY_POLICY_TLS_V1_2_2021 = '@aws-cdk/aws-cl */ export const FUTURE_FLAGS: { [key: string]: any } = { [APIGATEWAY_USAGEPLANKEY_ORDERINSENSITIVE_ID]: true, - [ENABLE_STACK_NAME_DUPLICATES_CONTEXT]: 'true', - [ENABLE_DIFF_NO_FAIL_CONTEXT]: 'true', - [STACK_RELATIVE_EXPORTS_CONTEXT]: 'true', + [ENABLE_STACK_NAME_DUPLICATES_CONTEXT]: true, + [ENABLE_DIFF_NO_FAIL_CONTEXT]: true, + [STACK_RELATIVE_EXPORTS_CONTEXT]: true, [DOCKER_IGNORE_SUPPORT]: true, [SECRETS_MANAGER_PARSE_OWNED_SECRET_NAME]: true, [KMS_DEFAULT_KEY_POLICIES]: true, diff --git a/packages/@aws-cdk/pipelines/lib/legacy/actions/deploy-cdk-stack-action.ts b/packages/@aws-cdk/pipelines/lib/legacy/actions/deploy-cdk-stack-action.ts index af6b7821a308d..1fc92da472ea1 100644 --- a/packages/@aws-cdk/pipelines/lib/legacy/actions/deploy-cdk-stack-action.ts +++ b/packages/@aws-cdk/pipelines/lib/legacy/actions/deploy-cdk-stack-action.ts @@ -16,6 +16,8 @@ import { Construct as CoreConstruct } from '@aws-cdk/core'; /** * Customization options for a DeployCdkStackAction + * + * @deprecated This class is part of the old API. Use the API based on the `CodePipeline` class instead */ export interface DeployCdkStackActionOptions { /** @@ -68,6 +70,8 @@ export interface DeployCdkStackActionOptions { /** * Properties for a DeployCdkStackAction + * + * @deprecated This class is part of the old API. Use the API based on the `CodePipeline` class instead */ export interface DeployCdkStackActionProps extends DeployCdkStackActionOptions { /** @@ -129,6 +133,8 @@ export interface DeployCdkStackActionProps extends DeployCdkStackActionOptions { /** * Options for the 'fromStackArtifact' operation + * + * @deprecated This class is part of the old API. Use the API based on the `CodePipeline` class instead */ export interface CdkStackActionFromArtifactOptions extends DeployCdkStackActionOptions { /** @@ -147,6 +153,8 @@ export interface CdkStackActionFromArtifactOptions extends DeployCdkStackActionO * * You do not need to instantiate this action yourself -- it will automatically * be added by the pipeline when you add stack artifacts or entire stages. + * + * @deprecated This class is part of the old API. Use the API based on the `CodePipeline` class instead */ export class DeployCdkStackAction implements codepipeline.IAction { /** @@ -317,6 +325,8 @@ function roleFromPlaceholderArn(scope: Construct, region: string | undefined, /** * Options for CdkDeployAction.fromStackArtifact + * + * @deprecated This class is part of the old API. Use the API based on the `CodePipeline` class instead */ export interface FromStackArtifactOptions { /** diff --git a/packages/@aws-cdk/pipelines/lib/legacy/actions/publish-assets-action.ts b/packages/@aws-cdk/pipelines/lib/legacy/actions/publish-assets-action.ts index 1c112aec9afbe..055744cb971c2 100644 --- a/packages/@aws-cdk/pipelines/lib/legacy/actions/publish-assets-action.ts +++ b/packages/@aws-cdk/pipelines/lib/legacy/actions/publish-assets-action.ts @@ -17,6 +17,8 @@ import { Construct as CoreConstruct } from '@aws-cdk/core'; /** * Props for a PublishAssetsAction + * + * @deprecated This class is part of the old API. Use the API based on the `CodePipeline` class instead */ export interface PublishAssetsActionProps { /** @@ -111,6 +113,8 @@ export interface PublishAssetsActionProps { * * You do not need to instantiate this action -- it will automatically * be added by the pipeline when you add stacks that use assets. + * + * @deprecated This class is part of the old API. Use the API based on the `CodePipeline` class instead */ export class PublishAssetsAction extends CoreConstruct implements codepipeline.IAction { private readonly action: codepipeline.IAction; diff --git a/packages/@aws-cdk/pipelines/lib/legacy/actions/update-pipeline-action.ts b/packages/@aws-cdk/pipelines/lib/legacy/actions/update-pipeline-action.ts index bc50e80c0aa56..da4278dd6faf2 100644 --- a/packages/@aws-cdk/pipelines/lib/legacy/actions/update-pipeline-action.ts +++ b/packages/@aws-cdk/pipelines/lib/legacy/actions/update-pipeline-action.ts @@ -14,6 +14,8 @@ import { Construct as CoreConstruct } from '@aws-cdk/core'; /** * Props for the UpdatePipelineAction + * + * @deprecated This class is part of the old API. Use the API based on the `CodePipeline` class instead */ export interface UpdatePipelineActionProps { /** @@ -79,6 +81,8 @@ export interface UpdatePipelineActionProps { * * You do not need to instantiate this action -- it will automatically * be added by the pipeline. + * + * @deprecated This class is part of the old API. Use the API based on the `CodePipeline` class instead */ export class UpdatePipelineAction extends CoreConstruct implements codepipeline.IAction { private readonly action: codepipeline.IAction; diff --git a/packages/@aws-cdk/pipelines/lib/legacy/pipeline.ts b/packages/@aws-cdk/pipelines/lib/legacy/pipeline.ts index 60f158f298fce..f4910d1916771 100644 --- a/packages/@aws-cdk/pipelines/lib/legacy/pipeline.ts +++ b/packages/@aws-cdk/pipelines/lib/legacy/pipeline.ts @@ -21,6 +21,8 @@ import { Construct as CoreConstruct } from '@aws-cdk/core'; const CODE_BUILD_LENGTH_LIMIT = 100; /** * Properties for a CdkPipeline + * + * @deprecated This class is part of the old API. Use the API based on the `CodePipeline` class instead */ export interface CdkPipelineProps { /** @@ -206,6 +208,8 @@ export interface CdkPipelineProps { * - Asset publishing. * - Keeping the pipeline up-to-date as the CDK apps change. * - Using stack outputs later on in the pipeline. + * + * @deprecated This class is part of the old API. Use the API based on the `CodePipeline` class instead */ export class CdkPipeline extends CoreConstruct { private readonly _pipeline: codepipeline.Pipeline; diff --git a/packages/@aws-cdk/pipelines/lib/legacy/stage.ts b/packages/@aws-cdk/pipelines/lib/legacy/stage.ts index bfb997e908196..c054e9a0592fb 100644 --- a/packages/@aws-cdk/pipelines/lib/legacy/stage.ts +++ b/packages/@aws-cdk/pipelines/lib/legacy/stage.ts @@ -20,6 +20,8 @@ import { Construct as CoreConstruct } from '@aws-cdk/core'; /** * Construction properties for a CdkStage + * + * @deprecated This class is part of the old API. Use the API based on the `CodePipeline` class instead */ export interface CdkStageProps { /** @@ -70,6 +72,8 @@ export interface CdkStageProps { * * You don't need to instantiate this class directly. Use * `cdkPipeline.addStage()` instead. + * + * @deprecated This class is part of the old API. Use the API based on the `CodePipeline` class instead */ export class CdkStage extends CoreConstruct { private _nextSequentialRunOrder = 1; // Must start at 1 eh @@ -396,6 +400,8 @@ export class CdkStage extends CoreConstruct { /** * Additional options for adding a stack deployment + * + * @deprecated This class is part of the old API. Use the API based on the `CodePipeline` class instead */ export interface AddStackOptions { /** @@ -415,6 +421,8 @@ export interface AddStackOptions { /** * A single output of a Stack + * + * @deprecated This class is part of the old API. Use the API based on the `CodePipeline` class instead */ export class StackOutput { /** @@ -448,6 +456,8 @@ function isAssetManifest(s: cxapi.CloudArtifact): s is cxapi.AssetManifestArtifa /** * Features that the Stage needs from its environment + * + * @deprecated This class is part of the old API. Use the API based on the `CodePipeline` class instead */ export interface IStageHost { /** @@ -463,6 +473,8 @@ export interface IStageHost { /** * Instructions to publish certain assets + * + * @deprecated This class is part of the old API. Use the API based on the `CodePipeline` class instead */ export interface AssetPublishingCommand { /** @@ -493,6 +505,8 @@ export interface AssetPublishingCommand { /** * Base options for a pipelines stage + * + * @deprecated This class is part of the old API. Use the API based on the `CodePipeline` class instead */ export interface BaseStageOptions { /** @@ -522,6 +536,8 @@ export interface BaseStageOptions { /** * Options for adding an application stage to a pipeline + * + * @deprecated This class is part of the old API. Use the API based on the `CodePipeline` class instead */ export interface AddStageOptions extends BaseStageOptions { /** @@ -546,6 +562,8 @@ export interface AddStageOptions extends BaseStageOptions { /** * Options for addManualApproval + * + * @deprecated This class is part of the old API. Use the API based on the `CodePipeline` class instead */ export interface AddManualApprovalOptions { /** diff --git a/packages/@aws-cdk/pipelines/lib/legacy/synths/simple-synth-action.ts b/packages/@aws-cdk/pipelines/lib/legacy/synths/simple-synth-action.ts index 1fd0b96bb2db6..226a75d2ed23c 100644 --- a/packages/@aws-cdk/pipelines/lib/legacy/synths/simple-synth-action.ts +++ b/packages/@aws-cdk/pipelines/lib/legacy/synths/simple-synth-action.ts @@ -19,6 +19,8 @@ import { Construct } from '@aws-cdk/core'; /** * Configuration options for a SimpleSynth + * + * @deprecated This class is part of the old API. Use the API based on the `CodePipeline` class instead */ export interface SimpleSynthOptions { /** @@ -128,6 +130,8 @@ export interface SimpleSynthOptions { /** * Construction props for SimpleSynthAction + * + * @deprecated This class is part of the old API. Use the API based on the `CodePipeline` class instead */ export interface SimpleSynthActionProps extends SimpleSynthOptions { /** @@ -192,6 +196,8 @@ export interface SimpleSynthActionProps extends SimpleSynthOptions { /** * Specification of an additional artifact to generate + * + * @deprecated This class is part of the old API. Use the API based on the `CodePipeline` class instead */ export interface AdditionalArtifact { /** @@ -207,6 +213,8 @@ export interface AdditionalArtifact { /** * A standard synth with a generated buildspec + * + * @deprecated This class is part of the old API. Use the API based on the `CodePipeline` class instead */ export class SimpleSynthAction implements codepipeline.IAction, iam.IGrantable { @@ -479,6 +487,8 @@ export class SimpleSynthAction implements codepipeline.IAction, iam.IGrantable { /** * Options for a convention-based synth using NPM + * + * @deprecated This class is part of the old API. Use the API based on the `CodePipeline` class instead */ export interface StandardNpmSynthOptions extends SimpleSynthOptions { /** @@ -520,6 +530,8 @@ export interface StandardNpmSynthOptions extends SimpleSynthOptions { /** * Options for a convention-based synth using Yarn + * + * @deprecated This class is part of the old API. Use the API based on the `CodePipeline` class instead */ export interface StandardYarnSynthOptions extends SimpleSynthOptions { /** diff --git a/packages/@aws-cdk/pipelines/lib/legacy/validation/shell-script-action.ts b/packages/@aws-cdk/pipelines/lib/legacy/validation/shell-script-action.ts index 436f099d3c67d..78f223919cafd 100644 --- a/packages/@aws-cdk/pipelines/lib/legacy/validation/shell-script-action.ts +++ b/packages/@aws-cdk/pipelines/lib/legacy/validation/shell-script-action.ts @@ -13,6 +13,8 @@ import { Construct } from '@aws-cdk/core'; /** * Properties for ShellScriptAction + * + * @deprecated This class is part of the old API. Use the API based on the `CodePipeline` class instead */ export interface ShellScriptActionProps { /** @@ -122,6 +124,8 @@ export interface ShellScriptActionProps { /** * Validate a revision using shell commands + * + * @deprecated This class is part of the old API. Use the API based on the `CodePipeline` class instead */ export class ShellScriptAction implements codepipeline.IAction, iam.IGrantable { private _project?: codebuild.IProject; From 69ac520452b219bf242f2fbb4740f6b1b8b8790f Mon Sep 17 00:00:00 2001 From: TakaakiFuruse Date: Mon, 18 Oct 2021 23:44:39 +0900 Subject: [PATCH 04/89] feat(stepfunctions-tasks): add `enableNetworkIsolation` property to `SageMakerCreateTrainingJobProps` (#16792) Closes #16779. This PR adds an option of `EnableNetworkIsolation` to `SageMakerCreateTrainingJob` class and enables a user to use AWS Marketplace. [Doc](https://docs.aws.amazon.com/sagemaker/latest/dg/mkt-algo-model-internet-free.html) says a user must turn the option to True when they attempt to use a machine learning model from AWS Marketplace. *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-tasks/README.md | 4 ++++ .../lib/sagemaker/create-training-job.ts | 8 ++++++++ .../test/sagemaker/create-training-job.test.ts | 2 ++ 3 files changed, 14 insertions(+) diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/README.md b/packages/@aws-cdk/aws-stepfunctions-tasks/README.md index d33d3c7ff801e..a0f47ee7519c1 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/README.md +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/README.md @@ -969,6 +969,10 @@ disable this behavior. Step Functions supports [AWS SageMaker](https://docs.aws.amazon.com/step-functions/latest/dg/connect-sagemaker.html) through the service integration pattern. +If your training job or model uses resources from AWS Marketplace, +[network isolation is required](https://docs.aws.amazon.com/sagemaker/latest/dg/mkt-algo-model-internet-free.html). +To do so, set the `enableNetworkIsolation` property to `true` for `SageMakerCreateModel` or `SageMakerCreateTrainingJob`. + ### Create Training Job You can call the [`CreateTrainingJob`](https://docs.aws.amazon.com/sagemaker/latest/dg/API_CreateTrainingJob.html) API from a `Task` state. diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/lib/sagemaker/create-training-job.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/lib/sagemaker/create-training-job.ts index 0aa9954e859d5..64680dc357747 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/lib/sagemaker/create-training-job.ts +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/lib/sagemaker/create-training-job.ts @@ -32,6 +32,13 @@ export interface SageMakerCreateTrainingJobProps extends sfn.TaskStateBaseProps */ readonly algorithmSpecification: AlgorithmSpecification; + /** + * Isolates the training container. No inbound or outbound network calls can be made to or from the training container. + * + * @default false + */ + readonly enableNetworkIsolation?: boolean; + /** * Algorithm-specific parameters that influence the quality of the model. Set hyperparameters before you start the learning process. * For a list of hyperparameters provided by Amazon SageMaker @@ -217,6 +224,7 @@ export class SageMakerCreateTrainingJob extends sfn.TaskStateBase implements iam private renderParameters(): { [key: string]: any } { return { TrainingJobName: this.props.trainingJobName, + EnableNetworkIsolation: this.props.enableNetworkIsolation, RoleArn: this._role!.roleArn, ...this.renderAlgorithmSpecification(this.algorithmSpecification), ...this.renderInputDataConfig(this.inputDataConfig), diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/sagemaker/create-training-job.test.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/sagemaker/create-training-job.test.ts index 59f5a1bb36229..e16d20f94cfeb 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/sagemaker/create-training-job.test.ts +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/sagemaker/create-training-job.test.ts @@ -142,6 +142,7 @@ test('create complex training job', () => { }, ], }, + enableNetworkIsolation: true, hyperparameters: { lr: '0.1', }, @@ -221,6 +222,7 @@ test('create complex training job', () => { { Name: 'mymetric', Regex: 'regex_pattern' }, ], }, + EnableNetworkIsolation: true, HyperParameters: { lr: '0.1', }, From 30f45847b21e57011f3b1dddd713d16d5f4aad30 Mon Sep 17 00:00:00 2001 From: Grzegorz Kozub Date: Mon, 18 Oct 2021 18:25:51 +0200 Subject: [PATCH 05/89] docs(pipelines): fix typo in `CdkPipelineProps` (#16920) Removed duplicate word in documentation. ---- *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/lib/legacy/pipeline.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/pipelines/lib/legacy/pipeline.ts b/packages/@aws-cdk/pipelines/lib/legacy/pipeline.ts index f4910d1916771..ef0d1d209619b 100644 --- a/packages/@aws-cdk/pipelines/lib/legacy/pipeline.ts +++ b/packages/@aws-cdk/pipelines/lib/legacy/pipeline.ts @@ -51,7 +51,7 @@ export interface CdkPipelineProps { * You can choose to not pass this value, in which case a new CodePipeline is * created with default settings. * - * If you pass an existing CodePipeline, it should should have been created + * If you pass an existing CodePipeline, it should have been created * with `restartExecutionOnUpdate: true`. * * [disable-awslint:ref-via-interface] From d0a27c15d66c00aef9288d514498d68e8f0d886a Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Mon, 18 Oct 2021 19:26:10 +0200 Subject: [PATCH 06/89] chore(v2): minimum supported node version is now v14 (#17036) This is the current active LTS version and is a good minimum requirement. Re-introduction of #11964. Fixes #16438 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .yarnrc | 1 + tools/@aws-cdk/pkglint/lib/rules.ts | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.yarnrc b/.yarnrc index ac05beb3696fd..019f345f39305 100644 --- a/.yarnrc +++ b/.yarnrc @@ -7,3 +7,4 @@ # be forced to registry.yarnpkg.com. # https://github.com/npm/cli/issues/3783 registry "https://registry.npmjs.org" +ignore-engines true # the 'engines' key for 'aws-cdk-lib' has specifies node14 as min while v1 will remain at node10 diff --git a/tools/@aws-cdk/pkglint/lib/rules.ts b/tools/@aws-cdk/pkglint/lib/rules.ts index f991f7b0a2441..e18fcb1086fdb 100644 --- a/tools/@aws-cdk/pkglint/lib/rules.ts +++ b/tools/@aws-cdk/pkglint/lib/rules.ts @@ -1129,7 +1129,11 @@ export class MustHaveNodeEnginesDeclaration extends ValidationRule { public readonly name = 'package-info/engines'; public validate(pkg: PackageJson): void { - expectJSON(this.name, pkg, 'engines.node', '>= 10.13.0 <13 || >=13.7.0'); + if (cdkMajorVersion() === 2) { + expectJSON(this.name, pkg, 'engines.node', '>= 14.15.0'); + } else { + expectJSON(this.name, pkg, 'engines.node', '>= 10.13.0 <13 || >=13.7.0'); + } } } From 83cf9b8770880ba5ec448bb7389606025543a692 Mon Sep 17 00:00:00 2001 From: Tom Keller <1083460+kellertk@users.noreply.github.com> Date: Mon, 18 Oct 2021 16:49:43 -0700 Subject: [PATCH 07/89] chore: minor GitHub action changes (#17022) * chore: run issue cleanup action more frequently This changes the issue cleanup action to run 6 times per day (once every four hours) insted of only once per day. * chore: create action documentation Documents each of the GitHub actions in the repo and their owners --- .github/workflows/README.md | 47 ++++++++++++++++++++++++ .github/workflows/close-stale-issues.yml | 2 +- 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/README.md diff --git a/.github/workflows/README.md b/.github/workflows/README.md new file mode 100644 index 0000000000000..9d54ed7236ef7 --- /dev/null +++ b/.github/workflows/README.md @@ -0,0 +1,47 @@ +# AWS CDK GitHub Actions + +These workflows and actions are configured in the AWS CDK GitHub repository. + +## Pull Request Triggered + +### Auto Approve +[auto-approve.yml](auto-approve.yml): Approves merging PRs with the +`pr/auto-approve` label. +Owner: Core CDK team + +### PR Linter +[pr-linter.yml](pr-linter.yml): Runs `tools/@aws-cdk-prlint` on each PR to +check for correctness. +Owner: Core CDK team + +### v2-main PR automation +[v2-pull-request.yml](v2-pull-request.yml): Runs `pkglint` on merge forward PRs +and commits the results. +Owner: Core CDK team + +### Label Assigner +[issue-label-assign.yml](issue-label-assign.yml): Github action for automatically adding labels and/or setting assignees when an Issue or PR is opened or edited based on user-defined Area +Owner: CDK support team + +## Issue Triggered + +### Closed Issue Message +[closed-issue-message.yml](closed-issue-message.yml): Adds a reminder message +to issues that are closed. +Owner: CDK support team + +### Label Assigner +[issue-label-assign.yml](issue-label-assign.yml): Github action for automatically adding labels and/or setting assignees when an Issue or PR is opened or edited based on user-defined Area +Owner: CDK support team + +## Scheduled Actions + +### Issue Lifecycle Handling +[close-stale-issues.yml](close-stale-issues.yml): Handles labeling issues and +PRs with `closing-soon`, `response-requested`, etc. +Owner: CDK support team + +### Yarn Upgrader +[yarn-upgrade.yml](yarn-upgrade.yml): Upgrades yarn dependencies and creates a +patch file for downloading. +Owner: Core CDK team \ No newline at end of file diff --git a/.github/workflows/close-stale-issues.yml b/.github/workflows/close-stale-issues.yml index 487a095e0c372..ee427df90ef79 100644 --- a/.github/workflows/close-stale-issues.yml +++ b/.github/workflows/close-stale-issues.yml @@ -4,7 +4,7 @@ name: "Close Stale Issues" on: workflow_dispatch: schedule: - - cron: "0 6 * * *" + - cron: "0 */4 * * *" jobs: cleanup: From ef7e20df08b4321f210bfc050afa42d7b4901931 Mon Sep 17 00:00:00 2001 From: Jericho Tolentino <68654047+jericht@users.noreply.github.com> Date: Tue, 19 Oct 2021 04:07:27 -0500 Subject: [PATCH 08/89] feat(aws-autoscaling): add flag and aspect to require imdsv2 (#16052) Partially fixes: https://github.com/aws/aws-cdk/issues/5137 Related PR: https://github.com/aws/aws-cdk/pull/16051 **Note:** I have some concerns about duplicated code between this and the above linked PR. Please see that PR for more details. ### Changes Adds an aspect that can enable/disable IMDSv1 on AutoScalingGroups ### Testing Added unit tests ---- *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 | 26 ++++++ .../aws-autoscaling/lib/aspects/index.ts | 1 + .../lib/aspects/require-imdsv2-aspect.ts | 38 +++++++++ .../aws-autoscaling/lib/auto-scaling-group.ts | 13 +++ .../@aws-cdk/aws-autoscaling/lib/index.ts | 1 + .../aspects/require-imdsv2-aspect.test.ts | 79 +++++++++++++++++++ .../test/auto-scaling-group.test.ts | 21 +++++ 7 files changed, 179 insertions(+) create mode 100644 packages/@aws-cdk/aws-autoscaling/lib/aspects/index.ts create mode 100644 packages/@aws-cdk/aws-autoscaling/lib/aspects/require-imdsv2-aspect.ts create mode 100644 packages/@aws-cdk/aws-autoscaling/test/aspects/require-imdsv2-aspect.test.ts diff --git a/packages/@aws-cdk/aws-autoscaling/README.md b/packages/@aws-cdk/aws-autoscaling/README.md index 67e55eee91a9f..75aa4f66807e2 100644 --- a/packages/@aws-cdk/aws-autoscaling/README.md +++ b/packages/@aws-cdk/aws-autoscaling/README.md @@ -378,6 +378,32 @@ new autoscaling.AutoScalingGroup(stack, 'ASG', { }); ``` +## Configuring Instance Metadata Service (IMDS) + +### Toggling IMDSv1 + +You can configure [EC2 Instance Metadata Service](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html) options to either +allow both IMDSv1 and IMDSv2 or enforce IMDSv2 when interacting with the IMDS. + +To do this for a single `AutoScalingGroup`, you can use set the `requireImdsv2` property. +The example below demonstrates IMDSv2 being required on a single `AutoScalingGroup`: + +```ts +new autoscaling.AutoScalingGroup(stack, 'ASG', { + requireImdsv2: true, + // ... +}); +``` + +You can also use `AutoScalingGroupRequireImdsv2Aspect` to apply the operation to multiple AutoScalingGroups. +The example below demonstrates the `AutoScalingGroupRequireImdsv2Aspect` being used to require IMDSv2 for all AutoScalingGroups in a stack: + +```ts +const aspect = new autoscaling.AutoScalingGroupRequireImdsv2Aspect(); + +Aspects.of(stack).add(aspect); +``` + ## Future work * [ ] CloudWatch Events (impossible to add currently as the AutoScalingGroup ARN is diff --git a/packages/@aws-cdk/aws-autoscaling/lib/aspects/index.ts b/packages/@aws-cdk/aws-autoscaling/lib/aspects/index.ts new file mode 100644 index 0000000000000..31fc534776144 --- /dev/null +++ b/packages/@aws-cdk/aws-autoscaling/lib/aspects/index.ts @@ -0,0 +1 @@ +export * from './require-imdsv2-aspect'; \ No newline at end of file diff --git a/packages/@aws-cdk/aws-autoscaling/lib/aspects/require-imdsv2-aspect.ts b/packages/@aws-cdk/aws-autoscaling/lib/aspects/require-imdsv2-aspect.ts new file mode 100644 index 0000000000000..e399dce585d79 --- /dev/null +++ b/packages/@aws-cdk/aws-autoscaling/lib/aspects/require-imdsv2-aspect.ts @@ -0,0 +1,38 @@ +import * as cdk from '@aws-cdk/core'; +import { AutoScalingGroup } from '../auto-scaling-group'; +import { CfnLaunchConfiguration } from '../autoscaling.generated'; + +/** + * Aspect that makes IMDSv2 required on instances deployed by AutoScalingGroups. + */ +export class AutoScalingGroupRequireImdsv2Aspect implements cdk.IAspect { + constructor() { + } + + public visit(node: cdk.IConstruct): void { + if (!(node instanceof AutoScalingGroup)) { + return; + } + + const launchConfig = node.node.tryFindChild('LaunchConfig') as CfnLaunchConfiguration; + if (cdk.isResolvableObject(launchConfig.metadataOptions)) { + this.warn(node, 'CfnLaunchConfiguration.MetadataOptions field is a CDK token.'); + return; + } + + launchConfig.metadataOptions = { + ...launchConfig.metadataOptions, + httpTokens: 'required', + }; + } + + /** + * Adds a warning annotation to a node. + * + * @param node The scope to add the warning to. + * @param message The warning message. + */ + protected warn(node: cdk.IConstruct, message: string) { + cdk.Annotations.of(node).addWarning(`${AutoScalingGroupRequireImdsv2Aspect.name} failed on node ${node.node.id}: ${message}`); + } +} diff --git a/packages/@aws-cdk/aws-autoscaling/lib/auto-scaling-group.ts b/packages/@aws-cdk/aws-autoscaling/lib/auto-scaling-group.ts index 027034249c4dd..45fd06c478dfc 100644 --- a/packages/@aws-cdk/aws-autoscaling/lib/auto-scaling-group.ts +++ b/packages/@aws-cdk/aws-autoscaling/lib/auto-scaling-group.ts @@ -7,6 +7,7 @@ import * as sns from '@aws-cdk/aws-sns'; import { Annotations, + Aspects, Aws, CfnAutoScalingRollingUpdate, CfnCreationPolicy, CfnUpdatePolicy, Duration, Fn, IResource, Lazy, PhysicalName, Resource, Stack, Tags, @@ -14,6 +15,7 @@ import { Tokenization, withResolved, } from '@aws-cdk/core'; import { Construct } from 'constructs'; +import { AutoScalingGroupRequireImdsv2Aspect } from './aspects'; import { CfnAutoScalingGroup, CfnAutoScalingGroupProps, CfnLaunchConfiguration } from './autoscaling.generated'; import { BasicLifecycleHookProps, LifecycleHook } from './lifecycle-hook'; import { BasicScheduledActionProps, ScheduledAction } from './scheduled-action'; @@ -384,6 +386,13 @@ export interface AutoScalingGroupProps extends CommonAutoScalingGroupProps { * @default - default options */ readonly initOptions?: ApplyCloudFormationInitOptions; + + /** + * Whether IMDSv2 should be required on launched instances. + * + * @default - false + */ + readonly requireImdsv2?: boolean; } /** @@ -1065,6 +1074,10 @@ export class AutoScalingGroup extends AutoScalingGroupBase implements } this.spotPrice = props.spotPrice; + + if (props.requireImdsv2) { + Aspects.of(this).add(new AutoScalingGroupRequireImdsv2Aspect()); + } } /** diff --git a/packages/@aws-cdk/aws-autoscaling/lib/index.ts b/packages/@aws-cdk/aws-autoscaling/lib/index.ts index 69fede92e300b..186d1a3058fae 100644 --- a/packages/@aws-cdk/aws-autoscaling/lib/index.ts +++ b/packages/@aws-cdk/aws-autoscaling/lib/index.ts @@ -1,3 +1,4 @@ +export * from './aspects'; export * from './auto-scaling-group'; export * from './schedule'; export * from './lifecycle-hook'; diff --git a/packages/@aws-cdk/aws-autoscaling/test/aspects/require-imdsv2-aspect.test.ts b/packages/@aws-cdk/aws-autoscaling/test/aspects/require-imdsv2-aspect.test.ts new file mode 100644 index 0000000000000..22a58f097a98b --- /dev/null +++ b/packages/@aws-cdk/aws-autoscaling/test/aspects/require-imdsv2-aspect.test.ts @@ -0,0 +1,79 @@ +import { + expect as expectCDK, + haveResourceLike, +} from '@aws-cdk/assert-internal'; +import '@aws-cdk/assert-internal/jest'; +import * as ec2 from '@aws-cdk/aws-ec2'; +import * as cdk from '@aws-cdk/core'; +import { + AutoScalingGroup, + AutoScalingGroupRequireImdsv2Aspect, + CfnLaunchConfiguration, +} from '../../lib'; + +describe('AutoScalingGroupRequireImdsv2Aspect', () => { + let app: cdk.App; + let stack: cdk.Stack; + let vpc: ec2.Vpc; + + beforeEach(() => { + app = new cdk.App(); + stack = new cdk.Stack(app, 'Stack'); + vpc = new ec2.Vpc(stack, 'Vpc'); + }); + + test('warns when metadataOptions is a token', () => { + // GIVEN + const asg = new AutoScalingGroup(stack, 'AutoScalingGroup', { + vpc, + instanceType: new ec2.InstanceType('t2.micro'), + machineImage: ec2.MachineImage.latestAmazonLinux(), + }); + const launchConfig = asg.node.tryFindChild('LaunchConfig') as CfnLaunchConfiguration; + launchConfig.metadataOptions = fakeToken(); + const aspect = new AutoScalingGroupRequireImdsv2Aspect(); + + // WHEN + cdk.Aspects.of(stack).add(aspect); + + // THEN + expectCDK(stack).notTo(haveResourceLike('AWS::AutoScaling::LaunchConfiguration', { + MetadataOptions: { + HttpTokens: 'required', + }, + })); + expect(asg.node.metadataEntry).toContainEqual({ + data: expect.stringContaining('CfnLaunchConfiguration.MetadataOptions field is a CDK token.'), + type: 'aws:cdk:warning', + trace: undefined, + }); + }); + + test('requires IMDSv2', () => { + // GIVEN + new AutoScalingGroup(stack, 'AutoScalingGroup', { + vpc, + instanceType: new ec2.InstanceType('t2.micro'), + machineImage: ec2.MachineImage.latestAmazonLinux(), + }); + const aspect = new AutoScalingGroupRequireImdsv2Aspect(); + + // WHEN + cdk.Aspects.of(stack).add(aspect); + + // THEN + expectCDK(stack).to(haveResourceLike('AWS::AutoScaling::LaunchConfiguration', { + MetadataOptions: { + HttpTokens: 'required', + }, + })); + }); +}); + +function fakeToken(): cdk.IResolvable { + return { + creationStack: [], + resolve: (_c) => {}, + toString: () => '', + }; +} diff --git a/packages/@aws-cdk/aws-autoscaling/test/auto-scaling-group.test.ts b/packages/@aws-cdk/aws-autoscaling/test/auto-scaling-group.test.ts index 64795593e8ec4..d74860638fd30 100644 --- a/packages/@aws-cdk/aws-autoscaling/test/auto-scaling-group.test.ts +++ b/packages/@aws-cdk/aws-autoscaling/test/auto-scaling-group.test.ts @@ -1364,6 +1364,27 @@ describe('auto scaling group', () => { }); + + test('requires imdsv2', () => { + // GIVEN + const stack = new cdk.Stack(); + const vpc = mockVpc(stack); + + // WHEN + new autoscaling.AutoScalingGroup(stack, 'MyASG', { + vpc, + instanceType: new ec2.InstanceType('t2.micro'), + machineImage: ec2.MachineImage.latestAmazonLinux(), + requireImdsv2: true, + }); + + // THEN + expect(stack).toHaveResourceLike('AWS::AutoScaling::LaunchConfiguration', { + MetadataOptions: { + HttpTokens: 'required', + }, + }); + }); }); function mockVpc(stack: cdk.Stack) { From 86f2714613f06aaf2bcee27da2f66066c8e863d0 Mon Sep 17 00:00:00 2001 From: Adam Ruka Date: Tue, 19 Oct 2021 03:01:47 -0700 Subject: [PATCH 09/89] fix(cfn-diff): correctly handle Date strings in diff (#16591) Turns out, `parseFloat()` in JavaScript is even crazier than we thought, and returns nonsense like `2021` for a string containing a Date like `'2021-10-25'`. For that reason, add an explicit check that the string parsed looks like a number before calling `parseFloat()`. Fixes #16444 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../cloudformation-diff/lib/diff-template.ts | 8 ++- .../cloudformation-diff/lib/diff/util.ts | 18 ++----- .../test/diff-template.test.ts | 51 +++++++------------ 3 files changed, 27 insertions(+), 50 deletions(-) diff --git a/packages/@aws-cdk/cloudformation-diff/lib/diff-template.ts b/packages/@aws-cdk/cloudformation-diff/lib/diff-template.ts index b3f282802b675..6e06e56f90af1 100644 --- a/packages/@aws-cdk/cloudformation-diff/lib/diff-template.ts +++ b/packages/@aws-cdk/cloudformation-diff/lib/diff-template.ts @@ -99,13 +99,17 @@ function calculateTemplateDiff(currentTemplate: { [key: string]: any }, newTempl for (const key of unionOf(Object.keys(currentTemplate), Object.keys(newTemplate)).sort()) { const oldValue = currentTemplate[key]; const newValue = newTemplate[key]; - if (deepEqual(oldValue, newValue)) { continue; } + if (deepEqual(oldValue, newValue)) { + continue; + } const handler: DiffHandler = DIFF_HANDLERS[key] || ((_diff, oldV, newV) => unknown[key] = impl.diffUnknown(oldV, newV)); handler(differences, oldValue, newValue); } - if (Object.keys(unknown).length > 0) { differences.unknown = new types.DifferenceCollection(unknown); } + if (Object.keys(unknown).length > 0) { + differences.unknown = new types.DifferenceCollection(unknown); + } return new types.TemplateDiff(differences); } diff --git a/packages/@aws-cdk/cloudformation-diff/lib/diff/util.ts b/packages/@aws-cdk/cloudformation-diff/lib/diff/util.ts index 59c8606be0a35..1cbd4b1a111d7 100644 --- a/packages/@aws-cdk/cloudformation-diff/lib/diff/util.ts +++ b/packages/@aws-cdk/cloudformation-diff/lib/diff/util.ts @@ -138,20 +138,10 @@ export function unionOf(lv: string[] | Set, rv: string[] | Set): * A parseFloat implementation that does the right thing for * strings like '0.0.0' * (for which JavaScript's parseFloat() returns 0). + * We return NaN for all of these strings that do not represent numbers, + * and so comparing them fails, + * and doesn't short-circuit the diff logic. */ function safeParseFloat(str: string): number { - const ret = parseFloat(str); - const nonNumericRegex = /\d*\.\d+\./; - if (ret === 0) { - // if the str is exactly '0', that's OK; - // but parseFloat() also returns 0 for things like '0.0'; - // in this case, return NaN, so we'll fall back to string comparison - return str === '0' ? ret : NaN; - } else if (nonNumericRegex.test(str)) { - // if the str contains non-numeric characters, - // return NaN, so we'll fall back to string comparison - return NaN; - } else { - return ret; - } + return Number(str); } diff --git a/packages/@aws-cdk/cloudformation-diff/test/diff-template.test.ts b/packages/@aws-cdk/cloudformation-diff/test/diff-template.test.ts index 9241d0e8e28eb..d43ec99808d31 100644 --- a/packages/@aws-cdk/cloudformation-diff/test/diff-template.test.ts +++ b/packages/@aws-cdk/cloudformation-diff/test/diff-template.test.ts @@ -582,70 +582,57 @@ test('when a property changes including equivalent DependsOn', () => { expect(differences.resources.differenceCount).toBe(1); }); -test('when a property with a number-like format changes', () => { - const bucketName = 'ShineyBucketName'; - const tagChanges = { - '0.31.1-prod': '0.31.2-prod', - '8.0.5.5.4-identifier': '8.0.5.5.5-identifier', - '1.1.1.1': '1.1.2.2', - '1.2.3': '1.2.4', - '2.2.2.2': '2.2.3.2', - '3.3.3.3': '3.4.3.3', - }; - const oldTags = Object.keys(tagChanges); - const newTags = Object.values(tagChanges); +test.each([ + ['0.31.1-prod', '0.31.2-prod'], + ['8.0.5.5.4-identifier', '8.0.5.5.5-identifier'], + ['1.1.1.1', '1.1.1.2'], + ['1.2.3', '1.2.4'], + ['2.2.2.2', '2.2.3.2'], + ['3.3.3.3', '3.4.3.3'], + ['2021-10-23T06:07:08.000Z', '2021-10-23T09:10:11.123Z'], +])("reports a change when a string property with a number-like format changes from '%s' to '%s'", (oldValue, newValue) => { + // GIVEN const currentTemplate = { Resources: { - QueueResource: { - Type: 'AWS::SQS::Queue', - }, BucketResource: { Type: 'AWS::S3::Bucket', Properties: { - BucketName: bucketName, - Tags: oldTags, + Tags: [oldValue], }, }, }, }; const newTemplate = { Resources: { - QueueResource: { - Type: 'AWS::SQS::Queue', - }, BucketResource: { Type: 'AWS::S3::Bucket', Properties: { - BucketName: bucketName, - Tags: newTags, + Tags: [newValue], }, }, }, }; - + // WHEN const differences = diffTemplate(currentTemplate, newTemplate); + + // THEN expect(differences.differenceCount).toBe(1); expect(differences.resources.differenceCount).toBe(1); const difference = differences.resources.changes.BucketResource; expect(difference).not.toBeUndefined(); expect(difference?.oldResourceType).toEqual('AWS::S3::Bucket'); expect(difference?.propertyUpdates).toEqual({ - Tags: { oldValue: oldTags, newValue: newTags, changeImpact: ResourceImpact.WILL_UPDATE, isDifferent: true }, + Tags: { oldValue: [oldValue], newValue: [newValue], changeImpact: ResourceImpact.WILL_UPDATE, isDifferent: true }, }); }); test('when a property with a number-like format doesn\'t change', () => { - const bucketName = 'ShineyBucketName'; const tags = ['0.31.1-prod', '8.0.5.5.4-identifier', '1.1.1.1', '1.2.3']; const currentTemplate = { Resources: { - QueueResource: { - Type: 'AWS::SQS::Queue', - }, BucketResource: { Type: 'AWS::S3::Bucket', Properties: { - BucketName: bucketName, Tags: tags, }, }, @@ -653,13 +640,9 @@ test('when a property with a number-like format doesn\'t change', () => { }; const newTemplate = { Resources: { - QueueResource: { - Type: 'AWS::SQS::Queue', - }, BucketResource: { Type: 'AWS::S3::Bucket', Properties: { - BucketName: bucketName, Tags: tags, }, }, @@ -671,4 +654,4 @@ test('when a property with a number-like format doesn\'t change', () => { expect(differences.resources.differenceCount).toBe(0); const difference = differences.resources.changes.BucketResource; expect(difference).toBeUndefined(); -}); \ No newline at end of file +}); From 605027fc471b007ee63cd3abdcb0fd09f81c58a5 Mon Sep 17 00:00:00 2001 From: Pat Myron Date: Tue, 19 Oct 2021 03:56:35 -0700 Subject: [PATCH 10/89] chore(region-info): cn-northwest-1 (Ningxia) ROUTE_53_BUCKET_WEBSITE_ZONE_ID (#17024) https://docs.aws.amazon.com/general/latest/gr/s3.html#s3_region, https://github.com/hashicorp/terraform-provider-aws/pull/21337 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../aws-route53-targets/test/bucket-website-target.test.ts | 4 ++-- packages/@aws-cdk/region-info/build-tools/fact-tables.ts | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk/aws-route53-targets/test/bucket-website-target.test.ts b/packages/@aws-cdk/aws-route53-targets/test/bucket-website-target.test.ts index eebb53b2d488a..ff1938e66447b 100644 --- a/packages/@aws-cdk/aws-route53-targets/test/bucket-website-target.test.ts +++ b/packages/@aws-cdk/aws-route53-targets/test/bucket-website-target.test.ts @@ -74,10 +74,10 @@ test('throws if region agnostic', () => { }).toThrow(/Cannot use an S3 record alias in region-agnostic stacks/); }); -test('throws if bucket website hosting is unavailable (cn-northwest-1)', () => { +test('throws if bucket website hosting is unavailable (cn-north-1)', () => { // GIVEN const app = new App(); - const stack = new Stack(app, 'test', { env: { region: 'cn-northwest-1' } }); + const stack = new Stack(app, 'test', { env: { region: 'cn-north-1' } }); const bucketWebsite = new s3.Bucket(stack, 'Bucket'); 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 28d61f7fd9387..3ce1d5de6b55b 100644 --- a/packages/@aws-cdk/region-info/build-tools/fact-tables.ts +++ b/packages/@aws-cdk/region-info/build-tools/fact-tables.ts @@ -43,7 +43,7 @@ export const AWS_CDK_METADATA = new Set([ /** * The hosted zone Id if using an alias record in Route53. * - * @see https://docs.aws.amazon.com/general/latest/gr/rande.html#s3_website_region_endpoints + * @see https://docs.aws.amazon.com/general/latest/gr/s3.html#s3_region */ export const ROUTE_53_BUCKET_WEBSITE_ZONE_IDS: { [region: string]: string } = { 'af-south-1': 'Z11KHD8FBVPUYU', @@ -55,6 +55,7 @@ export const ROUTE_53_BUCKET_WEBSITE_ZONE_IDS: { [region: string]: string } = { 'ap-southeast-1': 'Z3O0J2DXBE1FTB', 'ap-southeast-2': 'Z1WCIGYICN2BYD', 'ca-central-1': 'Z1QDHH18159H29', + 'cn-northwest-1': 'Z282HJ1KT0DH03', 'eu-central-1': 'Z21DNDUVLTQW6Q', 'eu-north-1': 'Z3BAZG2TWCNX0D', 'eu-south-1': 'Z3IXVV8C73GIO3', From b5f5182123928f66c7eab4465f1b75bce0328be8 Mon Sep 17 00:00:00 2001 From: Pat Myron Date: Tue, 19 Oct 2021 04:50:27 -0700 Subject: [PATCH 11/89] chore(region-info): cn-north-1/cn-northwest-1 (China) APPMESH_ECR_ACCOUNTS (#17025) https://docs.amazonaws.cn/app-mesh/latest/userguide/envoy.html https://aws.amazon.com/about-aws/whats-new/2021/09/aws-app-mesh-aws-china-regions/ https://github.com/aws/aws-app-mesh-roadmap/issues/1 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/@aws-cdk/region-info/build-tools/fact-tables.ts | 3 +++ 1 file changed, 3 insertions(+) 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 3ce1d5de6b55b..0e1f923dc2a02 100644 --- a/packages/@aws-cdk/region-info/build-tools/fact-tables.ts +++ b/packages/@aws-cdk/region-info/build-tools/fact-tables.ts @@ -136,6 +136,7 @@ export const DLC_REPOSITORY_ACCOUNTS: { [region: string]: string } = { }; // https://docs.aws.amazon.com/app-mesh/latest/userguide/envoy.html +// https://docs.amazonaws.cn/app-mesh/latest/userguide/envoy.html export const APPMESH_ECR_ACCOUNTS: { [region: string]: string } = { 'af-south-1': '924023996002', 'ap-east-1': '856666278305', @@ -146,6 +147,8 @@ export const APPMESH_ECR_ACCOUNTS: { [region: string]: string } = { 'ap-southeast-1': '840364872350', 'ap-southeast-2': '840364872350', 'ca-central-1': '840364872350', + 'cn-north-1': '919366029133', + 'cn-northwest-1': '919830735681', 'eu-central-1': '840364872350', 'eu-north-1': '840364872350', 'eu-south-1': '422531588944', From d1cee62b5b9960860e1ff59dc095ba52d3f9de31 Mon Sep 17 00:00:00 2001 From: kaylanm <1063516+kaylanm@users.noreply.github.com> Date: Tue, 19 Oct 2021 08:43:33 -0400 Subject: [PATCH 12/89] chore: fix typo in 'subnet' (#17046) Fix typographical errors in the spelling of 'subnet' in the ec2 & eks modules. ---- *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/test/vpc.test.ts | 2 +- packages/@aws-cdk/aws-eks/lib/cluster.ts | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/@aws-cdk/aws-ec2/test/vpc.test.ts b/packages/@aws-cdk/aws-ec2/test/vpc.test.ts index ca375dc7fe321..90942056865c7 100644 --- a/packages/@aws-cdk/aws-ec2/test/vpc.test.ts +++ b/packages/@aws-cdk/aws-ec2/test/vpc.test.ts @@ -361,7 +361,7 @@ describe('vpc', () => { } }); - test('with custom subents and natGateways = 2 there should be only two NATGW', () => { + test('with custom subnets and natGateways = 2 there should be only two NATGW', () => { const stack = getTestStack(); new Vpc(stack, 'TheVPC', { cidr: '10.0.0.0/21', diff --git a/packages/@aws-cdk/aws-eks/lib/cluster.ts b/packages/@aws-cdk/aws-eks/lib/cluster.ts index 76c59f740f6f2..c1d00a9dcd767 100644 --- a/packages/@aws-cdk/aws-eks/lib/cluster.ts +++ b/packages/@aws-cdk/aws-eks/lib/cluster.ts @@ -1191,7 +1191,7 @@ export class Cluster extends ClusterBase { this.onEventLayer = props.onEventLayer; this.kubectlMemory = props.kubectlMemory; - const privateSubents = this.selectPrivateSubnets().slice(0, 16); + const privateSubnets = this.selectPrivateSubnets().slice(0, 16); const publicAccessDisabled = !this.endpointAccess._config.publicAccess; const publicAccessRestricted = !publicAccessDisabled && this.endpointAccess._config.publicCidrs @@ -1199,19 +1199,19 @@ export class Cluster extends ClusterBase { // validate endpoint access configuration - if (privateSubents.length === 0 && publicAccessDisabled) { + if (privateSubnets.length === 0 && publicAccessDisabled) { // no private subnets and no public access at all, no good. throw new Error('Vpc must contain private subnets when public endpoint access is disabled'); } - if (privateSubents.length === 0 && publicAccessRestricted) { - // no private subents and public access is restricted, no good. + if (privateSubnets.length === 0 && publicAccessRestricted) { + // no private subnets and public access is restricted, no good. throw new Error('Vpc must contain private subnets when public endpoint access is restricted'); } const placeClusterHandlerInVpc = props.placeClusterHandlerInVpc ?? false; - if (placeClusterHandlerInVpc && privateSubents.length === 0) { + if (placeClusterHandlerInVpc && privateSubnets.length === 0) { throw new Error('Cannot place cluster handler in the VPC since no private subnets could be selected'); } @@ -1240,11 +1240,11 @@ export class Cluster extends ClusterBase { publicAccessCidrs: this.endpointAccess._config.publicCidrs, secretsEncryptionKey: props.secretsEncryptionKey, vpc: this.vpc, - subnets: placeClusterHandlerInVpc ? privateSubents : undefined, + subnets: placeClusterHandlerInVpc ? privateSubnets : undefined, onEventLayer: this.onEventLayer, }); - if (this.endpointAccess._config.privateAccess && privateSubents.length !== 0) { + if (this.endpointAccess._config.privateAccess && privateSubnets.length !== 0) { // when private access is enabled and the vpc has private subnets, lets connect // the provider to the vpc so that it will work even when restricting public access. @@ -1254,7 +1254,7 @@ export class Cluster extends ClusterBase { throw new Error('Private endpoint access requires the VPC to have DNS support and DNS hostnames enabled. Use `enableDnsHostnames: true` and `enableDnsSupport: true` when creating the VPC.'); } - this.kubectlPrivateSubnets = privateSubents; + this.kubectlPrivateSubnets = privateSubnets; // the vpc must exist in order to properly delete the cluster (since we run `kubectl delete`). // this ensures that. From 707fa003a458039878a1ae5173b6665a84c1170b Mon Sep 17 00:00:00 2001 From: Cory Hall <43035978+corymhall@users.noreply.github.com> Date: Tue, 19 Oct 2021 09:35:20 -0400 Subject: [PATCH 13/89] fix(events): PhysicalName.GENERATE_IF_NEEDED does not work for EventBus (#17008) fixes an issue where the generate when needed marker was not being passed through to the physicalName fix #14337 ---- *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/lib/event-bus.ts | 4 ++- .../aws-events/test/event-bus.test.ts | 30 ++++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/aws-events/lib/event-bus.ts b/packages/@aws-cdk/aws-events/lib/event-bus.ts index df0859b3d3259..bdddbc9cceb61 100644 --- a/packages/@aws-cdk/aws-events/lib/event-bus.ts +++ b/packages/@aws-cdk/aws-events/lib/event-bus.ts @@ -276,6 +276,8 @@ export class EventBus extends EventBusBase { ); } return { eventBusName: eventSourceName, eventSourceName }; + } else { + return { eventBusName: props.eventBusName }; } } return { eventBusName: defaultEventBusName }; @@ -311,7 +313,7 @@ export class EventBus extends EventBusBase { super(scope, id, { physicalName: eventBusName }); const eventBus = new CfnEventBus(this, 'Resource', { - name: eventBusName, + name: this.physicalName, eventSourceName, }); diff --git a/packages/@aws-cdk/aws-events/test/event-bus.test.ts b/packages/@aws-cdk/aws-events/test/event-bus.test.ts index b4384255ea7b4..e50f0b24db771 100644 --- a/packages/@aws-cdk/aws-events/test/event-bus.test.ts +++ b/packages/@aws-cdk/aws-events/test/event-bus.test.ts @@ -1,6 +1,6 @@ import '@aws-cdk/assert-internal/jest'; import * as iam from '@aws-cdk/aws-iam'; -import { Aws, CfnResource, Stack, Arn } from '@aws-cdk/core'; +import { Aws, CfnResource, Stack, Arn, App, PhysicalName, CfnOutput } from '@aws-cdk/core'; import { EventBus } from '../lib'; describe('event bus', () => { @@ -515,4 +515,32 @@ describe('event bus', () => { }); + test('cross account event bus uses generated physical name', () => { + // GIVEN + const app = new App(); + const stack1 = new Stack(app, 'Stack1', { + env: { + account: '11111111111', + region: 'us-east-1', + }, + }); + const stack2 = new Stack(app, 'Stack2', { + env: { + account: '22222222222', + region: 'us-east-1', + }, + }); + + // WHEN + const bus1 = new EventBus(stack1, 'Bus', { + eventBusName: PhysicalName.GENERATE_IF_NEEDED, + }); + + new CfnOutput(stack2, 'BusName', { value: bus1.eventBusName }); + + // THEN + expect(stack1).toHaveResource('AWS::Events::EventBus', { + Name: 'stack1stack1busca19bdf8ab2e51b62a5a', + }); + }); }); From b3c00c026deda7be50bd68dbdba516185ec14e9f Mon Sep 17 00:00:00 2001 From: Nick Lynch Date: Tue, 19 Oct 2021 15:27:48 +0100 Subject: [PATCH 14/89] chore(codepipeline-actions): remove merge conflict marker (#17054) This causes a rather weird effect in the docs for this class: https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-codepipeline-actions.ServiceCatalogDeployActionBeta1.html ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../lib/servicecatalog/deploy-action-beta1.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/@aws-cdk/aws-codepipeline-actions/lib/servicecatalog/deploy-action-beta1.ts b/packages/@aws-cdk/aws-codepipeline-actions/lib/servicecatalog/deploy-action-beta1.ts index 34b055c14735b..302b82b2a8725 100644 --- a/packages/@aws-cdk/aws-codepipeline-actions/lib/servicecatalog/deploy-action-beta1.ts +++ b/packages/@aws-cdk/aws-codepipeline-actions/lib/servicecatalog/deploy-action-beta1.ts @@ -35,12 +35,8 @@ export interface ServiceCatalogDeployActionBeta1Props extends codepipeline.Commo /** * CodePipeline action to connect to an existing ServiceCatalog product. -<<<<<<< HEAD:packages/@aws-cdk/aws-codepipeline-actions/lib/servicecatalog/deploy-action.ts * * **Note**: this class is still experimental, and may have breaking changes in the future! - * -======= ->>>>>>> master:packages/@aws-cdk/aws-codepipeline-actions/lib/servicecatalog/deploy-action-beta1.ts */ export class ServiceCatalogDeployActionBeta1 extends Action { private readonly templatePath: string; From 7fda90318e18b3a5d126b040e35a0146634d5f2d Mon Sep 17 00:00:00 2001 From: Ayush Goyal Date: Tue, 19 Oct 2021 20:51:50 +0530 Subject: [PATCH 15/89] feat(events): Add DLQ support for SQS target (#16916) feat(events-targets): Add DLQ support for SQS target closes #16417 ---- *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 | 2 +- .../@aws-cdk/aws-events-targets/lib/sqs.ts | 9 ++- .../integ.sqs-event-rule-target.expected.json | 52 ++++++++++++++ .../test/sqs/integ.sqs-event-rule-target.ts | 6 +- .../aws-events-targets/test/sqs/sqs.test.ts | 72 +++++++++++++++++++ 5 files changed, 137 insertions(+), 4 deletions(-) diff --git a/packages/@aws-cdk/aws-events-targets/README.md b/packages/@aws-cdk/aws-events-targets/README.md index 994c24ab8a0a5..a5c8fde1d9d98 100644 --- a/packages/@aws-cdk/aws-events-targets/README.md +++ b/packages/@aws-cdk/aws-events-targets/README.md @@ -35,7 +35,7 @@ EventBridge. ## Event retry policy and using dead-letter queues -The Codebuild, CodePipeline, Lambda, StepFunctions and LogGroup targets support attaching a [dead letter queue and setting retry policies](https://docs.aws.amazon.com/eventbridge/latest/userguide/rule-dlq.html). See the [lambda example](#invoke-a-lambda-function). +The Codebuild, CodePipeline, Lambda, StepFunctions, LogGroup and SQSQueue targets support attaching a [dead letter queue and setting retry policies](https://docs.aws.amazon.com/eventbridge/latest/userguide/rule-dlq.html). See the [lambda example](#invoke-a-lambda-function). Use [escape hatches](https://docs.aws.amazon.com/cdk/latest/guide/cfn_layer.html) for the other target types. ## Invoke a Lambda function diff --git a/packages/@aws-cdk/aws-events-targets/lib/sqs.ts b/packages/@aws-cdk/aws-events-targets/lib/sqs.ts index 43fb9b8ed15d0..465f0355516cf 100644 --- a/packages/@aws-cdk/aws-events-targets/lib/sqs.ts +++ b/packages/@aws-cdk/aws-events-targets/lib/sqs.ts @@ -1,11 +1,12 @@ 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 { addToDeadLetterQueueResourcePolicy, TargetBaseProps, bindBaseTargetConfig } from './util'; /** * Customize the SQS Queue Event Target */ -export interface SqsQueueProps { +export interface SqsQueueProps extends TargetBaseProps { /** * Message Group ID for messages sent to this queue @@ -24,7 +25,6 @@ export interface SqsQueueProps { * @default the entire EventBridge event */ readonly message?: events.RuleTargetInput; - } /** @@ -62,7 +62,12 @@ export class SqsQueue implements events.IRuleTarget { // deduplicated automatically this.queue.grantSendMessages(new iam.ServicePrincipal('events.amazonaws.com', principalOpts)); + if (this.props.deadLetterQueue) { + addToDeadLetterQueueResourcePolicy(rule, this.props.deadLetterQueue); + } + return { + ...bindBaseTargetConfig(this.props), arn: this.queue.queueArn, input: this.props.message, targetResource: this.queue, diff --git a/packages/@aws-cdk/aws-events-targets/test/sqs/integ.sqs-event-rule-target.expected.json b/packages/@aws-cdk/aws-events-targets/test/sqs/integ.sqs-event-rule-target.expected.json index eb2a7dd26ef5f..f35a7a93b9e42 100644 --- a/packages/@aws-cdk/aws-events-targets/test/sqs/integ.sqs-event-rule-target.expected.json +++ b/packages/@aws-cdk/aws-events-targets/test/sqs/integ.sqs-event-rule-target.expected.json @@ -61,6 +61,14 @@ "Arn" ] }, + "DeadLetterConfig": { + "Arn": { + "Fn::GetAtt": [ + "MyDeadLetterQueueD997968A", + "Arn" + ] + } + }, "Id": "Target0" } ] @@ -110,6 +118,50 @@ } ] } + }, + "MyDeadLetterQueueD997968A": { + "Type": "AWS::SQS::Queue", + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "MyDeadLetterQueuePolicyCC35D52C": { + "Type": "AWS::SQS::QueuePolicy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "sqs:SendMessage", + "Condition": { + "ArnEquals": { + "aws:SourceArn": { + "Fn::GetAtt": [ + "MyRuleA44AB831", + "Arn" + ] + } + } + }, + "Effect": "Allow", + "Principal": { + "Service": "events.amazonaws.com" + }, + "Resource": { + "Fn::GetAtt": [ + "MyDeadLetterQueueD997968A", + "Arn" + ] + }, + "Sid": "AllowEventRuleawscdksqseventtargetMyRule0027A8F4" + } + ], + "Version": "2012-10-17" + }, + "Queues": [ + { + "Ref": "MyDeadLetterQueueD997968A" + } + ] + } } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-events-targets/test/sqs/integ.sqs-event-rule-target.ts b/packages/@aws-cdk/aws-events-targets/test/sqs/integ.sqs-event-rule-target.ts index b2b8fb334bff6..f2375dd7c2a37 100644 --- a/packages/@aws-cdk/aws-events-targets/test/sqs/integ.sqs-event-rule-target.ts +++ b/packages/@aws-cdk/aws-events-targets/test/sqs/integ.sqs-event-rule-target.ts @@ -24,6 +24,10 @@ const queue = new sqs.Queue(stack, 'MyQueue', { encryptionMasterKey: key, }); -event.addTarget(new targets.SqsQueue(queue)); +const deadLetterQueue = new sqs.Queue(stack, 'MyDeadLetterQueue'); + +event.addTarget(new targets.SqsQueue(queue, { + deadLetterQueue, +})); app.synth(); diff --git a/packages/@aws-cdk/aws-events-targets/test/sqs/sqs.test.ts b/packages/@aws-cdk/aws-events-targets/test/sqs/sqs.test.ts index 8893a8820f37e..ad2a5296714e6 100644 --- a/packages/@aws-cdk/aws-events-targets/test/sqs/sqs.test.ts +++ b/packages/@aws-cdk/aws-events-targets/test/sqs/sqs.test.ts @@ -180,3 +180,75 @@ test('fifo queues are synthesized correctly', () => { ], })); }); + +test('dead letter queue is configured correctly', () => { + const stack = new Stack(); + const queue = new sqs.Queue(stack, 'MyQueue', { fifo: true }); + const deadLetterQueue = new sqs.Queue(stack, 'MyDeadLetterQueue'); + const rule = new events.Rule(stack, 'MyRule', { + schedule: events.Schedule.rate(Duration.hours(1)), + }); + + // WHEN + rule.addTarget(new targets.SqsQueue(queue, { + deadLetterQueue, + })); + + cdkExpect(stack).to(haveResource('AWS::Events::Rule', { + ScheduleExpression: 'rate(1 hour)', + State: 'ENABLED', + Targets: [ + { + Arn: { + 'Fn::GetAtt': [ + 'MyQueueE6CA6235', + 'Arn', + ], + }, + Id: 'Target0', + DeadLetterConfig: { + Arn: { + 'Fn::GetAtt': [ + 'MyDeadLetterQueueD997968A', + 'Arn', + ], + }, + }, + }, + ], + })); +}); + +test('specifying retry policy', () => { + const stack = new Stack(); + const queue = new sqs.Queue(stack, 'MyQueue', { fifo: true }); + const rule = new events.Rule(stack, 'MyRule', { + schedule: events.Schedule.rate(Duration.hours(1)), + }); + + // WHEN + rule.addTarget(new targets.SqsQueue(queue, { + retryAttempts: 2, + maxEventAge: Duration.hours(2), + })); + + cdkExpect(stack).to(haveResource('AWS::Events::Rule', { + ScheduleExpression: 'rate(1 hour)', + State: 'ENABLED', + Targets: [ + { + Arn: { + 'Fn::GetAtt': [ + 'MyQueueE6CA6235', + 'Arn', + ], + }, + Id: 'Target0', + RetryPolicy: { + MaximumEventAgeInSeconds: 7200, + MaximumRetryAttempts: 2, + }, + }, + ], + })); +}); From f681f29714254df1b72e05acb3a8d50f7a834e51 Mon Sep 17 00:00:00 2001 From: kaizen3031593 <36202692+kaizen3031593@users.noreply.github.com> Date: Tue, 19 Oct 2021 13:47:42 -0400 Subject: [PATCH 16/89] docs(appsync): make examples compile (#17045) ---- *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-appsync/README.md | 260 ++++++++++-------- .../@aws-cdk/aws-appsync/lib/graphqlapi.ts | 2 +- .../aws-appsync/rosetta/default.ts-fixture | 15 + .../rosetta/with-objects.ts-fixture | 49 ++++ 4 files changed, 205 insertions(+), 121 deletions(-) create mode 100644 packages/@aws-cdk/aws-appsync/rosetta/default.ts-fixture create mode 100644 packages/@aws-cdk/aws-appsync/rosetta/with-objects.ts-fixture diff --git a/packages/@aws-cdk/aws-appsync/README.md b/packages/@aws-cdk/aws-appsync/README.md index a191b51a86483..8e78c92bd4b7b 100644 --- a/packages/@aws-cdk/aws-appsync/README.md +++ b/packages/@aws-cdk/aws-appsync/README.md @@ -24,6 +24,10 @@ The `@aws-cdk/aws-appsync` package contains constructs for building flexible APIs that use GraphQL. +```ts nofixture +import * as appsync from '@aws-cdk/aws-appsync'; +``` + ## Example ### DynamoDB @@ -52,24 +56,21 @@ type Mutation { CDK stack file `app-stack.ts`: ```ts -import * as appsync from '@aws-cdk/aws-appsync'; -import * as db from '@aws-cdk/aws-dynamodb'; - -const api = new appsync.GraphqlApi(stack, 'Api', { +const api = new appsync.GraphqlApi(this, 'Api', { name: 'demo', - schema: appsync.Schema.fromAsset(join(__dirname, 'schema.graphql')), + schema: appsync.Schema.fromAsset(path.join(__dirname, 'schema.graphql')), authorizationConfig: { defaultAuthorization: { - authorizationType: appsync.AuthorizationType.IAM + authorizationType: appsync.AuthorizationType.IAM, }, }, xrayEnabled: true, }); -const demoTable = new db.Table(stack, 'DemoTable', { +const demoTable = new dynamodb.Table(this, 'DemoTable', { partitionKey: { name: 'id', - type: db.AttributeType.STRING, + type: dynamodb.AttributeType.STRING, }, }); @@ -89,7 +90,7 @@ demoDS.createResolver({ fieldName: 'addDemo', requestMappingTemplate: appsync.MappingTemplate.dynamoDbPutItem( appsync.PrimaryKey.partition('id').auto(), - appsync.Values.projecting('input') + appsync.Values.projecting('input'), ), responseMappingTemplate: appsync.MappingTemplate.dynamoDbResultItem(), }); @@ -103,15 +104,15 @@ against the Data API with GraphQL queries, mutations, and subscriptions. ```ts // Create username and password secret for DB Cluster -const secret = new rds.DatabaseSecret(stack, 'AuroraSecret', { +const secret = new rds.DatabaseSecret(this, 'AuroraSecret', { username: 'clusteradmin', }); // The VPC to place the cluster in -const vpc = new ec2.Vpc(stack, 'AuroraVpc'); +const vpc = new ec2.Vpc(this, 'AuroraVpc'); // Create the serverless cluster, provide all values needed to customise the database. -const cluster = new rds.ServerlessCluster(stack, 'AuroraCluster', { +const cluster = new rds.ServerlessCluster(this, 'AuroraCluster', { engine: rds.DatabaseClusterEngine.AURORA_MYSQL, vpc, credentials: { username: 'clusteradmin' }, @@ -120,13 +121,14 @@ const cluster = new rds.ServerlessCluster(stack, 'AuroraCluster', { }); // Build a data source for AppSync to access the database. +declare const api: appsync.GraphqlApi; const rdsDS = api.addRdsDataSource('rds', cluster, secret, 'demos'); // Set up a resolver for an RDS query. rdsDS.createResolver({ typeName: 'Query', fieldName: 'getDemosRds', - requestMappingTemplate: MappingTemplate.fromString(` + requestMappingTemplate: appsync.MappingTemplate.fromString(` { "version": "2018-05-29", "statements": [ @@ -134,7 +136,7 @@ rdsDS.createResolver({ ] } `), - responseMappingTemplate: MappingTemplate.fromString(` + responseMappingTemplate: appsync.MappingTemplate.fromString(` $utils.toJson($utils.rds.toJsonObject($ctx.result)[0]) `), }); @@ -143,7 +145,7 @@ rdsDS.createResolver({ rdsDS.createResolver({ typeName: 'Mutation', fieldName: 'addDemoRds', - requestMappingTemplate: MappingTemplate.fromString(` + requestMappingTemplate: appsync.MappingTemplate.fromString(` { "version": "2018-05-29", "statements": [ @@ -156,7 +158,7 @@ rdsDS.createResolver({ } } `), - responseMappingTemplate: MappingTemplate.fromString(` + responseMappingTemplate: appsync.MappingTemplate.fromString(` $utils.toJson($utils.rds.toJsonObject($ctx.result)[1][0]) `), }); @@ -212,11 +214,9 @@ GraphQL response mapping template `response.vtl`: CDK stack file `app-stack.ts`: ```ts -import * as appsync from '@aws-cdk/aws-appsync'; - -const api = new appsync.GraphqlApi(scope, 'api', { +const api = new appsync.GraphqlApi(this, 'api', { name: 'api', - schema: appsync.Schema.fromFile(join(__dirname, 'schema.graphql')), + schema: appsync.Schema.fromAsset(path.join(__dirname, 'schema.graphql')), }); const httpDs = api.addHttpDataSource( @@ -227,7 +227,7 @@ const httpDs = api.addHttpDataSource( description: 'from appsync to StepFunctions Workflow', authorizationConfig: { signingRegion: 'us-east-1', - signingServiceName: 'states' + signingServiceName: 'states', } } ); @@ -235,8 +235,8 @@ const httpDs = api.addHttpDataSource( httpDs.createResolver({ typeName: 'Mutation', fieldName: 'callStepFunction', - requestMappingTemplate: MappingTemplate.fromFile('request.vtl'), - responseMappingTemplate: MappingTemplate.fromFile('response.vtl') + requestMappingTemplate: appsync.MappingTemplate.fromFile('request.vtl'), + responseMappingTemplate: appsync.MappingTemplate.fromFile('response.vtl'), }); ``` @@ -247,16 +247,19 @@ through your AWS account. You can use AppSync resolvers to perform GraphQL opera such as queries, mutations, and subscriptions. ```ts -const user = new User(stack, 'User'); -const domain = new es.Domain(stack, 'Domain', { +import * as es from '@aws-cdk/aws-elasticsearch'; + +const user = new iam.User(this, 'User'); +const domain = new es.Domain(this, 'Domain', { version: es.ElasticsearchVersion.V7_1, - removalPolicy: cdk.RemovalPolicy.DESTROY, + removalPolicy: RemovalPolicy.DESTROY, fineGrainedAccessControl: { masterUserArn: user.userArn }, encryptionAtRest: { enabled: true }, nodeToNodeEncryption: true, enforceHttps: true, }); +declare const api: appsync.GraphqlApi; const ds = api.addElasticsearchDataSource('ds', domain); ds.createResolver({ @@ -293,23 +296,23 @@ When declaring your GraphQL Api, CDK defaults to a code-first approach if the `schema` property is not configured. ```ts -const api = new appsync.GraphqlApi(stack, 'api', { name: 'myApi' }); +const api = new appsync.GraphqlApi(this, 'api', { name: 'myApi' }); ``` CDK will declare a `Schema` class that will give your Api access functions to -define your schema code-first: `addType`, `addObjectType`, `addToSchema`, etc. +define your schema code-first: `addType`, `addToSchema`, etc. You can also declare your `Schema` class outside of your CDK stack, to define your schema externally. ```ts const schema = new appsync.Schema(); -schema.addObjectType('demo', { +schema.addType(new appsync.ObjectType('demo', { definition: { id: appsync.GraphqlType.id() }, -}); -const api = new appsync.GraphqlApi(stack, 'api', { +})); +const api = new appsync.GraphqlApi(this, 'api', { name: 'myApi', - schema + schema, }); ``` @@ -321,9 +324,9 @@ You can define your GraphQL Schema from a file on disk. For convenience, use the `appsync.Schema.fromAsset` to specify the file representing your schema. ```ts -const api = appsync.GraphqlApi(stack, 'api', { +const api = new appsync.GraphqlApi(this, 'api', { name: 'myApi', - schema: appsync.Schema.fromAsset(join(__dirname, 'schema.graphl')), + schema: appsync.Schema.fromAsset(path.join(__dirname, 'schema.graphl')), }); ``` @@ -334,9 +337,11 @@ another stack into your CDK app. Utilizing the `fromXxx` function, you have the ability to add data sources and resolvers through a `IGraphqlApi` interface. ```ts -const importedApi = appsync.GraphqlApi.fromGraphqlApiAttributes(stack, 'IApi', { +declare const api: appsync.GraphqlApi; +declare const table: dynamodb.Table; +const importedApi = appsync.GraphqlApi.fromGraphqlApiAttributes(this, 'IApi', { graphqlApiId: api.apiId, - graphqlArn: api.arn, + graphqlApiArn: api.arn, }); importedApi.addDynamoDbDataSource('TableDataSource', table); ``` @@ -362,9 +367,10 @@ authorization mode to finish defining your authorization. For example, this is a with AWS Lambda Authorization. ```ts -authFunction = new lambda.Function(stack, 'auth-function', {}); +import * as lambda from '@aws-cdk/aws-lambda'; +declare const authFunction: lambda.Function; -new appsync.GraphqlApi(stack, 'api', { +new appsync.GraphqlApi(this, 'api', { name: 'api', schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), authorizationConfig: { @@ -390,7 +396,7 @@ for `IAM` authorized access you would configure the following. In `schema.graphql`: -```ts +```gql type Mutation { updateExample(...): ... @aws_iam @@ -401,18 +407,18 @@ In `IAM`: ```json { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": [ - "appsync:GraphQL" - ], - "Resource": [ - "arn:aws:appsync:REGION:ACCOUNT_ID:apis/GRAPHQL_ID/types/Mutation/fields/updateExample" - ] - } - ] + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "appsync:GraphQL" + ], + "Resource": [ + "arn:aws:appsync:REGION:ACCOUNT_ID:apis/GRAPHQL_ID/types/Mutation/fields/updateExample" + ] + } + ] } ``` @@ -423,14 +429,12 @@ To make this easier, CDK provides `grant` API. Use the `grant` function for more granular authorization. ```ts -const role = new iam.Role(stack, 'Role', { +const role = new iam.Role(this, 'Role', { assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'), }); -const api = new appsync.GraphqlApi(stack, 'API', { - definition -}); +declare const api: appsync.GraphqlApi; -api.grant(role, appsync.IamResource.custom('types/Mutation/fields/updateExample'), 'appsync:GraphQL') +api.grant(role, appsync.IamResource.custom('types/Mutation/fields/updateExample'), 'appsync:GraphQL'); ``` ### IamResource @@ -454,6 +458,9 @@ These include: - grantSubscription (use to grant access to Subscription fields) ```ts +declare const api: appsync.GraphqlApi; +declare const role: iam.Role; + // For generic types api.grantMutation(role, 'updateExample'); @@ -468,10 +475,12 @@ backend data source. Developers can compose operations (Functions) and execute them in sequence with Pipeline Resolvers. ```ts -const appsyncFunction = new appsync.AppsyncFunction(stack, 'function', { +declare const api: appsync.GraphqlApi; + +const appsyncFunction = new appsync.AppsyncFunction(this, 'function', { name: 'appsync_function', - api: api, - dataSource: apiDataSource, + api, + dataSource: api.addNoneDataSource('none'), requestMappingTemplate: appsync.MappingTemplate.fromFile('request.vtl'), responseMappingTemplate: appsync.MappingTemplate.fromFile('response.vtl'), }); @@ -481,10 +490,14 @@ AppSync Functions are used in tandem with pipeline resolvers to compose multiple operations. ```ts -const pipelineResolver = new appsync.Resolver(stack, 'pipeline', { - name: 'pipeline_resolver', - api: api, - dataSource: apiDataSource, +declare const api: appsync.GraphqlApi; +declare const appsyncFunction: appsync.AppsyncFunction; + +const pipelineResolver = new appsync.Resolver(this, 'pipeline', { + api, + dataSource: api.addNoneDataSource('none'), + typeName: 'typeName', + fieldName: 'fieldName', requestMappingTemplate: appsync.MappingTemplate.fromFile('beforeRequest.vtl'), pipelineConfig: [appsyncFunction], responseMappingTemplate: appsync.MappingTemplate.fromFile('afterResponse.vtl'), @@ -537,48 +550,38 @@ Above we see a schema that allows for generating paginated responses. For exampl we can query `allFilms(first: 100)` since `FilmConnection` acts as an intermediary for holding `FilmEdges` we can write a resolver to return the first 100 films. -In a separate file, we can declare our scalar types: `scalar-types.ts`. - -```ts -import { GraphqlType } from '@aws-cdk/aws-appsync'; - -export const string = appsync.GraphqlType.string(); -export const int = appsync.GraphqlType.int(); -``` - -In another separate file, we can declare our object types and related functions. +In a separate file, we can declare our object types and related functions. We will call this file `object-types.ts` and we will have created it in a way that allows us to generate other `XxxConnection` and `XxxEdges` in the future. -```ts -const pluralize = require('pluralize'); -import * as scalar from './scalar-types.ts'; +```ts nofixture import * as appsync from '@aws-cdk/aws-appsync'; +const pluralize = require('pluralize'); export const args = { - after: scalar.string, - first: scalar.int, - before: scalar.string, - last: scalar.int, + after: appsync.GraphqlType.string(), + first: appsync.GraphqlType.int(), + before: appsync.GraphqlType.string(), + last: appsync.GraphqlType.int(), }; export const Node = new appsync.InterfaceType('Node', { - definition: { id: scalar.string } + definition: { id: appsync.GraphqlType.string() } }); -export const FilmNode = new appsync.ObjectType.implementInterface('FilmNode', { +export const FilmNode = new appsync.ObjectType('FilmNode', { interfaceTypes: [Node], - definition: { filmName: scalar.string } + definition: { filmName: appsync.GraphqlType.string() } }); export function generateEdgeAndConnection(base: appsync.ObjectType) { const edge = new appsync.ObjectType(`${base.name}Edge`, { - definition: { node: base.attribute(), cursor: scalar.string } + definition: { node: base.attribute(), cursor: appsync.GraphqlType.string() } }); const connection = new appsync.ObjectType(`${base.name}Connection`, { definition: { - edges: edges.attribute({ isList: true }), + edges: edge.attribute({ isList: true }), [pluralize(base.name)]: base.attribute({ isList: true }), - totalCount: scalar.int, + totalCount: appsync.GraphqlType.int(), } }); return { edge: edge, connection: connection }; @@ -588,29 +591,30 @@ export function generateEdgeAndConnection(base: appsync.ObjectType) { Finally, we will go to our `cdk-stack` and combine everything together to generate our schema. -```ts -import * as appsync from '@aws-cdk/aws-appsync'; -import * as schema from './object-types'; +```ts fixture=with-objects +declare const dummyRequest: appsync.MappingTemplate; +declare const dummyResponse: appsync.MappingTemplate; -const api = new appsync.GraphqlApi(stack, 'Api', { +const api = new appsync.GraphqlApi(this, 'Api', { name: 'demo', }); -this.objectTypes = [ schema.Node, schema.Film ]; +const objectTypes = [ Node, FilmNode ]; -const filmConnections = schema.generateEdgeAndConnection(schema.Film); +const filmConnections = generateEdgeAndConnection(FilmNode); api.addQuery('allFilms', new appsync.ResolvableField({ - returnType: filmConnections.connection.attribute(), - args: schema.args, - dataSource: dummyDataSource, - requestMappingTemplate: dummyRequest, - responseMappingTemplate: dummyResponse, - }), -}); + returnType: filmConnections.connection.attribute(), + args: args, + dataSource: api.addNoneDataSource('none'), + requestMappingTemplate: dummyRequest, + responseMappingTemplate: dummyResponse, +})); -this.objectTypes.map((t) => api.addType(t)); -Object.keys(filmConnections).forEach((key) => api.addType(filmConnections[key])); +api.addType(Node); +api.addType(FilmNode); +api.addType(filmConnections.edge); +api.addType(filmConnections.connection); ``` Notice how we can utilize the `generateEdgeAndConnection` function to generate @@ -701,6 +705,9 @@ type Info { The CDK code required would be: ```ts +declare const api: appsync.GraphqlApi; +declare const dummyRequest: appsync.MappingTemplate; +declare const dummyResponse: appsync.MappingTemplate; const info = new appsync.ObjectType('Info', { definition: { node: new appsync.ResolvableField({ @@ -729,6 +736,9 @@ type Query { The CDK code required would be: ```ts +declare const api: appsync.GraphqlApi; +declare const dummyRequest: appsync.MappingTemplate; +declare const dummyResponse: appsync.MappingTemplate; const query = new appsync.ObjectType('Query', { definition: { get: new appsync.ResolvableField({ @@ -784,12 +794,12 @@ To learn more about **Interface Types**, read the docs [here](https://graphql.or the `demo` variable is an **Object Type**. **Object Types** are defined by GraphQL Types and are only usable when linked to a GraphQL Api. -You can create Object Types in three ways: +You can create Object Types in two ways: 1. Object Types can be created ***externally***. ```ts - const api = new appsync.GraphqlApi(stack, 'Api', { + const api = new appsync.GraphqlApi(this, 'Api', { name: 'demo', }); const demo = new appsync.ObjectType('Demo', { @@ -799,34 +809,28 @@ You can create Object Types in three ways: }, }); - api.addType(object); + api.addType(demo); ``` > This method allows for reusability and modularity, ideal for larger projects. For example, imagine moving all Object Type definition outside the stack. - `scalar-types.ts` - a file for scalar type definitions - - ```ts - export const required_string = appsync.GraphqlType.string({ isRequired: true }); - ``` - `object-types.ts` - a file for object type definitions - ```ts - import { required_string } from './scalar-types'; + ```ts nofixture + import * as appsync from '@aws-cdk/aws-appsync'; export const demo = new appsync.ObjectType('Demo', { definition: { - id: required_string, - version: required_string, + id: appsync.GraphqlType.string({ isRequired: true }), + version: appsync.GraphqlType.string({ isRequired: true }), }, }); ``` `cdk-stack.ts` - a file containing our cdk stack - ```ts - import { demo } from './object-types'; + ```ts fixture=with-objects + declare const api: appsync.GraphqlApi; api.addType(demo); ``` @@ -869,6 +873,7 @@ enum Episode { The above GraphQL Enumeration Type can be expressed in CDK as the following: ```ts +declare const api: appsync.GraphqlApi; const episode = new appsync.EnumType('Episode', { definition: [ 'NEWHOPE', @@ -896,10 +901,11 @@ input Review { The above GraphQL Input Type can be expressed in CDK as the following: ```ts +declare const api: appsync.GraphqlApi; const review = new appsync.InputType('Review', { definition: { - stars: GraphqlType.int({ isRequired: true }), - commentary: GraphqlType.string(), + stars: appsync.GraphqlType.int({ isRequired: true }), + commentary: appsync.GraphqlType.string(), }, }); api.addType(review); @@ -923,6 +929,7 @@ The above GraphQL Union Type encompasses the Object Types of Human, Droid and St can be expressed in CDK as the following: ```ts +declare const api: appsync.GraphqlApi; const string = appsync.GraphqlType.string(); const human = new appsync.ObjectType('Human', { definition: { name: string } }); const droid = new appsync.ObjectType('Droid', { definition: { name: string } }); @@ -945,6 +952,11 @@ To add fields for these queries, we can simply run the `addQuery` function to ad to the schema's `Query` type. ```ts +declare const api: appsync.GraphqlApi; +declare const filmConnection: appsync.InterfaceType; +declare const dummyRequest: appsync.MappingTemplate; +declare const dummyResponse: appsync.MappingTemplate; + const string = appsync.GraphqlType.string(); const int = appsync.GraphqlType.int(); api.addQuery('allFilms', new appsync.ResolvableField({ @@ -968,10 +980,15 @@ To add fields for these mutations, we can simply run the `addMutation` function to the schema's `Mutation` type. ```ts +declare const api: appsync.GraphqlApi; +declare const filmNode: appsync.ObjectType; +declare const dummyRequest: appsync.MappingTemplate; +declare const dummyResponse: appsync.MappingTemplate; + const string = appsync.GraphqlType.string(); const int = appsync.GraphqlType.int(); api.addMutation('addFilm', new appsync.ResolvableField({ - returnType: film.attribute(), + returnType: filmNode.attribute(), args: { name: string, film_number: int }, dataSource: api.addNoneDataSource('none'), requestMappingTemplate: dummyRequest, @@ -994,10 +1011,13 @@ To add fields for these subscriptions, we can simply run the `addSubscription` f to the schema's `Subscription` type. ```ts +declare const api: appsync.GraphqlApi; +declare const film: appsync.InterfaceType; + api.addSubscription('addedFilm', new appsync.Field({ returnType: film.attribute(), args: { id: appsync.GraphqlType.id({ isRequired: true }) }, - directive: [appsync.Directive.subscribe('addFilm')], + directives: [appsync.Directive.subscribe('addFilm')], })); ``` diff --git a/packages/@aws-cdk/aws-appsync/lib/graphqlapi.ts b/packages/@aws-cdk/aws-appsync/lib/graphqlapi.ts index 93c9078e32358..71cd6e32060c1 100644 --- a/packages/@aws-cdk/aws-appsync/lib/graphqlapi.ts +++ b/packages/@aws-cdk/aws-appsync/lib/graphqlapi.ts @@ -150,7 +150,7 @@ export interface OpenIdConnectConfig { /** * The client identifier of the Relying party at the OpenID identity provider. * A regular expression can be specified so AppSync can validate against multiple client identifiers at a time. - * @example - 'ABCD|CDEF' where ABCD and CDEF are two different clientId + * @example - 'ABCD|CDEF' // where ABCD and CDEF are two different clientId * @default - * (All) */ readonly clientId?: string; diff --git a/packages/@aws-cdk/aws-appsync/rosetta/default.ts-fixture b/packages/@aws-cdk/aws-appsync/rosetta/default.ts-fixture new file mode 100644 index 0000000000000..2b84336958cc7 --- /dev/null +++ b/packages/@aws-cdk/aws-appsync/rosetta/default.ts-fixture @@ -0,0 +1,15 @@ +// Fixture with packages imported, but nothing else +import { Construct, RemovalPolicy, Stack } from '@aws-cdk/core'; +import appsync = require('@aws-cdk/aws-appsync'); +import ec2 = require('@aws-cdk/aws-ec2'); +import dynamodb = require('@aws-cdk/aws-dynamodb'); +import iam = require('@aws-cdk/aws-iam'); +import rds = require('@aws-cdk/aws-rds'); +import path = require('path'); + +class Fixture extends Stack { + constructor(scope: Construct, id: string) { + super(scope, id); + /// here + } +} diff --git a/packages/@aws-cdk/aws-appsync/rosetta/with-objects.ts-fixture b/packages/@aws-cdk/aws-appsync/rosetta/with-objects.ts-fixture new file mode 100644 index 0000000000000..1251aad728423 --- /dev/null +++ b/packages/@aws-cdk/aws-appsync/rosetta/with-objects.ts-fixture @@ -0,0 +1,49 @@ +// Fixture with packages imported, but nothing else +import { Construct, Stack } from '@aws-cdk/core'; +import appsync = require('@aws-cdk/aws-appsync'); +const pluralize = require('pluralize'); + +const args = { + after: appsync.GraphqlType.string(), + first: appsync.GraphqlType.int(), + before: appsync.GraphqlType.string(), + last: appsync.GraphqlType.int(), +}; + +const Node = new appsync.InterfaceType('Node', { + definition: { id: appsync.GraphqlType.string() } +}); + +const FilmNode = new appsync.ObjectType('FilmNode', { + interfaceTypes: [Node], + definition: { filmName: appsync.GraphqlType.string() } +}); + +function generateEdgeAndConnection(base: appsync.ObjectType) { + const edge = new appsync.ObjectType(`${base.name}Edge`, { + definition: { node: base.attribute(), cursor: appsync.GraphqlType.string() } + }); + const connection = new appsync.ObjectType(`${base.name}Connection`, { + definition: { + edges: edge.attribute({ isList: true }), + [pluralize(base.name)]: base.attribute({ isList: true }), + totalCount: appsync.GraphqlType.int(), + } + }); + return { edge: edge, connection: connection }; +} + +const demo = new appsync.ObjectType('Demo', { + definition: { + id: appsync.GraphqlType.string({ isRequired: true }), + version: appsync.GraphqlType.string({ isRequired: true }), + }, +}); + +class Fixture extends Stack { + constructor(scope: Construct, id: string) { + super(scope, id); + + /// here + } +} From 3ec683283e96159d588797bd46d33c82ff3076f1 Mon Sep 17 00:00:00 2001 From: nom3ad <19239479+nom3ad@users.noreply.github.com> Date: Wed, 20 Oct 2021 00:17:46 +0530 Subject: [PATCH 17/89] fix(opensearch): add validation to domainName property (#17017) Add validation to domainName property as per https://docs.aws.amazon.com/opensearch-service/latest/developerguide/configuration-api.html#configuration-api-datatypes-domainname Fixes #17016 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../@aws-cdk/aws-elasticsearch/lib/domain.ts | 22 +++++++++++++++---- .../aws-elasticsearch/test/domain.test.ts | 15 +++++++++++++ .../aws-opensearchservice/lib/domain.ts | 22 +++++++++++++++---- .../aws-opensearchservice/test/domain.test.ts | 15 +++++++++++++ 4 files changed, 66 insertions(+), 8 deletions(-) diff --git a/packages/@aws-cdk/aws-elasticsearch/lib/domain.ts b/packages/@aws-cdk/aws-elasticsearch/lib/domain.ts index 842071fa0ec68..173b13834d233 100644 --- a/packages/@aws-cdk/aws-elasticsearch/lib/domain.ts +++ b/packages/@aws-cdk/aws-elasticsearch/lib/domain.ts @@ -1540,9 +1540,9 @@ export class Domain extends DomainBase implements IDomain, ec2.IConnectable { if (props.logging?.auditLogEnabled) { this.auditLogGroup = props.logging.auditLogGroup ?? - new logs.LogGroup(this, 'AuditLogs', { - retention: logs.RetentionDays.ONE_MONTH, - }); + new logs.LogGroup(this, 'AuditLogs', { + retention: logs.RetentionDays.ONE_MONTH, + }); logGroups.push(this.auditLogGroup); }; @@ -1692,7 +1692,21 @@ export class Domain extends DomainBase implements IDomain, ec2.IConnectable { if (logGroupResourcePolicy) { this.domain.node.addDependency(logGroupResourcePolicy); } - if (props.domainName) { this.node.addMetadata('aws:cdk:hasPhysicalName', props.domainName); } + if (props.domainName) { + if (!cdk.Token.isUnresolved(props.domainName)) { + // https://docs.aws.amazon.com/opensearch-service/latest/developerguide/configuration-api.html#configuration-api-datatypes-domainname + if (!props.domainName.match(/^[a-z0-9\-]+$/)) { + throw new Error(`Invalid domainName '${props.domainName}'. Valid characters are a-z (lowercase only), 0-9, and – (hyphen).`); + } + if (props.domainName.length < 3 || props.domainName.length > 28) { + throw new Error(`Invalid domainName '${props.domainName}'. It must be between 3 and 28 characters`); + } + if (props.domainName[0] < 'a' || props.domainName[0] > 'z') { + throw new Error(`Invalid domainName '${props.domainName}'. It must start with a lowercase letter`); + } + } + this.node.addMetadata('aws:cdk:hasPhysicalName', props.domainName); + } this.domainName = this.getResourceNameAttribute(this.domain.ref); diff --git a/packages/@aws-cdk/aws-elasticsearch/test/domain.test.ts b/packages/@aws-cdk/aws-elasticsearch/test/domain.test.ts index 6966882c55549..f1de6b640898b 100644 --- a/packages/@aws-cdk/aws-elasticsearch/test/domain.test.ts +++ b/packages/@aws-cdk/aws-elasticsearch/test/domain.test.ts @@ -1317,6 +1317,21 @@ describe('custom error responses', () => { })).toThrow(/Unknown Elasticsearch version: 5\.4/); }); + test('error when invalid domain name is given', () => { + expect(() => new Domain(stack, 'Domain1', { + version: ElasticsearchVersion.V7_4, + domainName: 'InvalidName', + })).toThrow(/Valid characters are a-z/); + expect(() => new Domain(stack, 'Domain2', { + version: ElasticsearchVersion.V7_4, + domainName: 'a'.repeat(29), + })).toThrow(/It must be between 3 and 28 characters/); + expect(() => new Domain(stack, 'Domain3', { + version: ElasticsearchVersion.V7_4, + domainName: '123domain', + })).toThrow(/It must start with a lowercase letter/); + }); + test('error when error log publishing is enabled for elasticsearch version < 5.1', () => { const error = /Error logs publishing requires Elasticsearch version 5.1 or later/; expect(() => new Domain(stack, 'Domain1', { diff --git a/packages/@aws-cdk/aws-opensearchservice/lib/domain.ts b/packages/@aws-cdk/aws-opensearchservice/lib/domain.ts index 1279d9525f831..600e1bee8f49a 100644 --- a/packages/@aws-cdk/aws-opensearchservice/lib/domain.ts +++ b/packages/@aws-cdk/aws-opensearchservice/lib/domain.ts @@ -1472,9 +1472,9 @@ export class Domain extends DomainBase implements IDomain, ec2.IConnectable { if (props.logging?.auditLogEnabled) { this.auditLogGroup = props.logging.auditLogGroup ?? - new logs.LogGroup(this, 'AuditLogs', { - retention: logs.RetentionDays.ONE_MONTH, - }); + new logs.LogGroup(this, 'AuditLogs', { + retention: logs.RetentionDays.ONE_MONTH, + }); logGroups.push(this.auditLogGroup); }; @@ -1624,7 +1624,21 @@ export class Domain extends DomainBase implements IDomain, ec2.IConnectable { if (logGroupResourcePolicy) { this.domain.node.addDependency(logGroupResourcePolicy); } - if (props.domainName) { this.node.addMetadata('aws:cdk:hasPhysicalName', props.domainName); } + if (props.domainName) { + if (!cdk.Token.isUnresolved(props.domainName)) { + // https://docs.aws.amazon.com/opensearch-service/latest/developerguide/configuration-api.html#configuration-api-datatypes-domainname + if (!props.domainName.match(/^[a-z0-9\-]+$/)) { + throw new Error(`Invalid domainName '${props.domainName}'. Valid characters are a-z (lowercase only), 0-9, and – (hyphen).`); + } + if (props.domainName.length < 3 || props.domainName.length > 28) { + throw new Error(`Invalid domainName '${props.domainName}'. It must be between 3 and 28 characters`); + } + if (props.domainName[0] < 'a' || props.domainName[0] > 'z') { + throw new Error(`Invalid domainName '${props.domainName}'. It must start with a lowercase letter`); + } + } + this.node.addMetadata('aws:cdk:hasPhysicalName', props.domainName); + } this.domainName = this.getResourceNameAttribute(this.domain.ref); diff --git a/packages/@aws-cdk/aws-opensearchservice/test/domain.test.ts b/packages/@aws-cdk/aws-opensearchservice/test/domain.test.ts index 4ad11ac372f97..80cc7a1473b40 100644 --- a/packages/@aws-cdk/aws-opensearchservice/test/domain.test.ts +++ b/packages/@aws-cdk/aws-opensearchservice/test/domain.test.ts @@ -1319,6 +1319,21 @@ describe('custom error responses', () => { })).toThrow('Unknown Elasticsearch version: 5.4'); }); + test('error when invalid domain name is given', () => { + expect(() => new Domain(stack, 'Domain1', { + version: EngineVersion.OPENSEARCH_1_0, + domainName: 'InvalidName', + })).toThrow(/Valid characters are a-z/); + expect(() => new Domain(stack, 'Domain2', { + version: EngineVersion.OPENSEARCH_1_0, + domainName: 'a'.repeat(29), + })).toThrow(/It must be between 3 and 28 characters/); + expect(() => new Domain(stack, 'Domain3', { + version: EngineVersion.OPENSEARCH_1_0, + domainName: '123domain', + })).toThrow(/It must start with a lowercase letter/); + }); + test('error when error log publishing is enabled for Elasticsearch version < 5.1', () => { const error = /Error logs publishing requires Elasticsearch version 5.1 or later or OpenSearch version 1.0 or later/; expect(() => new Domain(stack, 'Domain1', { From 13def19c66c7c82fadb8ad4c0b148ab4ec62700f Mon Sep 17 00:00:00 2001 From: Peter Woodworth <44349620+peterwoodworth@users.noreply.github.com> Date: Tue, 19 Oct 2021 15:56:27 -0700 Subject: [PATCH 18/89] chore: assign PRs on submission (#17063) ---- *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 | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/issue-label-assign.yml b/.github/workflows/issue-label-assign.yml index 1c9c5997781bd..b82a4040658d8 100644 --- a/.github/workflows/issue-label-assign.yml +++ b/.github/workflows/issue-label-assign.yml @@ -11,6 +11,7 @@ jobs: test: permissions: issues: write + pull-requests: write runs-on: ubuntu-latest steps: - uses: peterwoodworth/issue-action@main From 583813c623bbf17be4b51a6ea0adbe451a6027cc Mon Sep 17 00:00:00 2001 From: Shweta Sahu <34386180+shwetasahuit@users.noreply.github.com> Date: Wed, 20 Oct 2021 01:25:49 -0700 Subject: [PATCH 19/89] refactor(region-info): AppMesh ECR accounts for cn-north-1 and cn-northwest-1 (#16836) ---- AppMesh is launched in 'cn-noth-1' and 'cn-northwest-1' regions. These regions have separate accounts for storing Envoy images in ECR. Added the ECR account information. These regions belong to new partition 'aws-cn', removed the harcoded 'aws' partition and modified it to work for all partitions. *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .gitallowed | 2 ++ .../lib/extensions/appmesh.ts | 5 ++- .../integ.all-service-addons.expected.json | 36 +++++++++++++++++-- .../integ.multiple-environments.expected.json | 24 +++++++++++-- 4 files changed, 61 insertions(+), 6 deletions(-) diff --git a/.gitallowed b/.gitallowed index 43827f7ad99b7..abe8ccb913ca4 100644 --- a/.gitallowed +++ b/.gitallowed @@ -23,6 +23,8 @@ account: '856666278305' account: '840364872350' account: '422531588944' account: '924023996002' +account: '919366029133' #cn-north-1 +account: '919830735681' #cn-northwest-1 # The account IDs of password rotation applications of Serverless Application Repository # https://docs.aws.amazon.com/secretsmanager/latest/userguide/enable-rotation-rds.html diff --git a/packages/@aws-cdk-containers/ecs-service-extensions/lib/extensions/appmesh.ts b/packages/@aws-cdk-containers/ecs-service-extensions/lib/extensions/appmesh.ts index ccd9a2ece2bc2..14cd5aaecfdac 100644 --- a/packages/@aws-cdk-containers/ecs-service-extensions/lib/extensions/appmesh.ts +++ b/packages/@aws-cdk-containers/ecs-service-extensions/lib/extensions/appmesh.ts @@ -138,6 +138,7 @@ export class AppMeshExtension extends ServiceExtension { public useTaskDefinition(taskDefinition: ecs.TaskDefinition) { var region = cdk.Stack.of(this.scope).region; + var partition = cdk.Stack.of(this.scope).partition; var appMeshRepo; // This is currently necessary because App Mesh has different images in each region, @@ -151,6 +152,8 @@ export class AppMeshExtension extends ServiceExtension { 'ap-southeast-1': this.accountIdForRegion('ap-southeast-1'), 'ap-southeast-2': this.accountIdForRegion('ap-southeast-1'), 'ca-central-1': this.accountIdForRegion('ca-central-1'), + 'cn-north-1': this.accountIdForRegion('cn-north-1'), + 'cn-northwest-1': this.accountIdForRegion('cn-northwest-1'), 'eu-central-1': this.accountIdForRegion('eu-central-1'), 'eu-north-1': this.accountIdForRegion('eu-north-1'), 'eu-south-1': this.accountIdForRegion('eu-south-1'), @@ -177,7 +180,7 @@ export class AppMeshExtension extends ServiceExtension { `${this.parentService.id}-envoy-repo`, { repositoryName: 'aws-appmesh-envoy', - repositoryArn: `arn:aws:ecr:${region}:${ownerAccount}:repository/aws-appmesh-envoy`, + repositoryArn: `arn:${partition}:ecr:${region}:${ownerAccount}:repository/aws-appmesh-envoy`, }, ); 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 47ba97c3ee10d..afdf0319a819a 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 @@ -949,7 +949,11 @@ "Fn::Join": [ "", [ - "arn:aws:ecr:", + "arn:", + { + "Ref": "AWS::Partition" + }, + ":ecr:", { "Ref": "AWS::Region" }, @@ -1818,7 +1822,11 @@ "Fn::Join": [ "", [ - "arn:aws:ecr:", + "arn:", + { + "Ref": "AWS::Partition" + }, + ":ecr:", { "Ref": "AWS::Region" }, @@ -2806,7 +2814,11 @@ "Fn::Join": [ "", [ - "arn:aws:ecr:", + "arn:", + { + "Ref": "AWS::Partition" + }, + ":ecr:", { "Ref": "AWS::Region" }, @@ -3316,6 +3328,12 @@ "ca-central-1": { "ecrRepo": "840364872350" }, + "cn-north-1": { + "ecrRepo": "919366029133" + }, + "cn-northwest-1": { + "ecrRepo": "919830735681" + }, "eu-central-1": { "ecrRepo": "840364872350" }, @@ -3378,6 +3396,12 @@ "ca-central-1": { "ecrRepo": "840364872350" }, + "cn-north-1": { + "ecrRepo": "919366029133" + }, + "cn-northwest-1": { + "ecrRepo": "919830735681" + }, "eu-central-1": { "ecrRepo": "840364872350" }, @@ -3440,6 +3464,12 @@ "ca-central-1": { "ecrRepo": "840364872350" }, + "cn-north-1": { + "ecrRepo": "919366029133" + }, + "cn-northwest-1": { + "ecrRepo": "919830735681" + }, "eu-central-1": { "ecrRepo": "840364872350" }, diff --git a/packages/@aws-cdk-containers/ecs-service-extensions/test/integ.multiple-environments.expected.json b/packages/@aws-cdk-containers/ecs-service-extensions/test/integ.multiple-environments.expected.json index 3a3aaddac6fce..d5f00cb5708c7 100644 --- a/packages/@aws-cdk-containers/ecs-service-extensions/test/integ.multiple-environments.expected.json +++ b/packages/@aws-cdk-containers/ecs-service-extensions/test/integ.multiple-environments.expected.json @@ -1304,7 +1304,11 @@ "Fn::Join": [ "", [ - "arn:aws:ecr:", + "arn:", + { + "Ref": "AWS::Partition" + }, + ":ecr:", { "Ref": "AWS::Region" }, @@ -1828,7 +1832,11 @@ "Fn::Join": [ "", [ - "arn:aws:ecr:", + "arn:", + { + "Ref": "AWS::Partition" + }, + ":ecr:", { "Ref": "AWS::Region" }, @@ -2135,6 +2143,12 @@ "ca-central-1": { "ecrRepo": "840364872350" }, + "cn-north-1": { + "ecrRepo": "919366029133" + }, + "cn-northwest-1": { + "ecrRepo": "919830735681" + }, "eu-central-1": { "ecrRepo": "840364872350" }, @@ -2197,6 +2211,12 @@ "ca-central-1": { "ecrRepo": "840364872350" }, + "cn-north-1": { + "ecrRepo": "919366029133" + }, + "cn-northwest-1": { + "ecrRepo": "919830735681" + }, "eu-central-1": { "ecrRepo": "840364872350" }, From 0947b21c1e3186042324820ec5ab433237246f58 Mon Sep 17 00:00:00 2001 From: Jericho Tolentino <68654047+jericht@users.noreply.github.com> Date: Wed, 20 Oct 2021 04:17:58 -0500 Subject: [PATCH 20/89] feat(ec2): add aspect to require imdsv2 (#16051) Partially fixes: https://github.com/aws/aws-cdk/issues/5137 Related PR: https://github.com/aws/aws-cdk/pull/16052 **Note:** This PR and the above related PR have common code that has been duplicated across these two PRs because I decided it made more sense for these Aspects to be in the same package with the constructs they work with. However, it means I had to duplicate some of the base class code across the two PRs. Looking for an opinion on what's better here: - Should we keep it as is (2 PRs) so these Aspects are cleanly separated? or, - Does it make sense to either combine them in some way (e.g. a new package `@aws-cdk/aspects`) or have one reference the other (maybe the AutoScalingGroup aspect can reference the code in this PR since it already depends on this package). ### Changes Adds an aspect that can enable/disable IMDSv1 on Instances and Launch Templates. ### Testing Added unit tests ---- *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 | 27 +++ .../@aws-cdk/aws-ec2/lib/aspects/index.ts | 1 + .../lib/aspects/require-imdsv2-aspect.ts | 150 +++++++++++++ packages/@aws-cdk/aws-ec2/lib/index.ts | 1 + packages/@aws-cdk/aws-ec2/lib/instance.ts | 14 +- .../@aws-cdk/aws-ec2/lib/launch-template.ts | 13 ++ .../aspects/require-imdsv2-aspect.test.ts | 205 ++++++++++++++++++ .../@aws-cdk/aws-ec2/test/instance.test.ts | 32 ++- .../aws-ec2/test/launch-template.test.ts | 16 ++ 9 files changed, 457 insertions(+), 2 deletions(-) create mode 100644 packages/@aws-cdk/aws-ec2/lib/aspects/index.ts create mode 100644 packages/@aws-cdk/aws-ec2/lib/aspects/require-imdsv2-aspect.ts create mode 100644 packages/@aws-cdk/aws-ec2/test/aspects/require-imdsv2-aspect.test.ts diff --git a/packages/@aws-cdk/aws-ec2/README.md b/packages/@aws-cdk/aws-ec2/README.md index a9ac3794580b4..eecc6f3857da4 100644 --- a/packages/@aws-cdk/aws-ec2/README.md +++ b/packages/@aws-cdk/aws-ec2/README.md @@ -994,6 +994,33 @@ instance.userData.addCommands( ); ``` +### Configuring Instance Metadata Service (IMDS) + +#### Toggling IMDSv1 + +You can configure [EC2 Instance Metadata Service](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html) options to either +allow both IMDSv1 and IMDSv2 or enforce IMDSv2 when interacting with the IMDS. + +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 +new ec2.Instance(this, 'Instance', { + requireImdsv2: true, + // ... +}); +``` + +You can also use the either the `InstanceRequireImdsv2Aspect` for EC2 instances or the `LaunchTemplateRequireImdsv2Aspect` for EC2 launch templates +to apply the operation to multiple instances or launch templates, respectively. + +The following example demonstrates how to use the `InstanceRequireImdsv2Aspect` to require IMDSv2 for all EC2 instances in a stack: + +```ts +const aspect = new ec2.InstanceRequireImdsv2Aspect(); +Aspects.of(stack).add(aspect); +``` + ## VPC Flow Logs VPC Flow Logs is a feature that enables you to capture information about the IP traffic going to and from network interfaces in your VPC. Flow log data can be published to Amazon CloudWatch Logs and Amazon S3. After you've created a flow log, you can retrieve and view its data in the chosen destination. (). diff --git a/packages/@aws-cdk/aws-ec2/lib/aspects/index.ts b/packages/@aws-cdk/aws-ec2/lib/aspects/index.ts new file mode 100644 index 0000000000000..5685e9b46d036 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2/lib/aspects/index.ts @@ -0,0 +1 @@ +export * from './require-imdsv2-aspect'; diff --git a/packages/@aws-cdk/aws-ec2/lib/aspects/require-imdsv2-aspect.ts b/packages/@aws-cdk/aws-ec2/lib/aspects/require-imdsv2-aspect.ts new file mode 100644 index 0000000000000..f1a5270f1fb08 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2/lib/aspects/require-imdsv2-aspect.ts @@ -0,0 +1,150 @@ +import * as cdk from '@aws-cdk/core'; +import { CfnLaunchTemplate } from '../ec2.generated'; +import { Instance } from '../instance'; +import { LaunchTemplate } from '../launch-template'; + +/** + * Properties for `RequireImdsv2Aspect`. + */ +interface RequireImdsv2AspectProps { + /** + * Whether warning annotations from this Aspect should be suppressed or not. + * + * @default - false + */ + readonly suppressWarnings?: boolean; +} + +/** + * Base class for Aspect that makes IMDSv2 required. + */ +abstract class RequireImdsv2Aspect implements cdk.IAspect { + protected readonly suppressWarnings: boolean; + + constructor(props?: RequireImdsv2AspectProps) { + this.suppressWarnings = props?.suppressWarnings ?? false; + } + + abstract visit(node: cdk.IConstruct): void; + + /** + * Adds a warning annotation to a node, unless `suppressWarnings` is true. + * + * @param node The scope to add the warning to. + * @param message The warning message. + */ + protected warn(node: cdk.IConstruct, message: string) { + if (this.suppressWarnings !== true) { + cdk.Annotations.of(node).addWarning(`${RequireImdsv2Aspect.name} failed on node ${node.node.id}: ${message}`); + } + } +} + +/** + * Properties for `InstanceRequireImdsv2Aspect`. + */ +export interface InstanceRequireImdsv2AspectProps extends RequireImdsv2AspectProps { + /** + * Whether warnings that would be raised when an Instance is associated with an existing Launch Template + * should be suppressed or not. + * + * You can set this to `true` if `LaunchTemplateImdsAspect` is being used alongside this Aspect to + * suppress false-positive warnings because any Launch Templates associated with Instances will still be covered. + * + * @default - false + */ + readonly suppressLaunchTemplateWarning?: boolean; +} + +/** + * Aspect that applies IMDS configuration on EC2 Instance constructs. + * + * This aspect configures IMDS on an EC2 instance by creating a Launch Template with the + * IMDS configuration and associating that Launch Template with the instance. If an Instance + * is already associated with a Launch Template, a warning will (optionally) be added to the + * construct node and it will be skipped. + * + * To cover Instances already associated with Launch Templates, use `LaunchTemplateImdsAspect`. + */ +export class InstanceRequireImdsv2Aspect extends RequireImdsv2Aspect { + private readonly suppressLaunchTemplateWarning: boolean; + + constructor(props?: InstanceRequireImdsv2AspectProps) { + super(props); + this.suppressLaunchTemplateWarning = props?.suppressLaunchTemplateWarning ?? false; + } + + visit(node: cdk.IConstruct): void { + if (!(node instanceof Instance)) { + return; + } + if (node.instance.launchTemplate !== undefined) { + this.warn(node, 'Cannot toggle IMDSv1 because this Instance is associated with an existing Launch Template.'); + return; + } + + const name = `${node.node.id}LaunchTemplate`; + const launchTemplate = new CfnLaunchTemplate(node, 'LaunchTemplate', { + launchTemplateData: { + metadataOptions: { + httpTokens: 'required', + }, + }, + launchTemplateName: name, + }); + node.instance.launchTemplate = { + launchTemplateName: name, + version: launchTemplate.getAtt('LatestVersionNumber').toString(), + }; + } + + protected warn(node: cdk.IConstruct, message: string) { + if (this.suppressLaunchTemplateWarning !== true) { + super.warn(node, message); + } + } +} + +/** + * Properties for `LaunchTemplateRequireImdsv2Aspect`. + */ +export interface LaunchTemplateRequireImdsv2AspectProps extends RequireImdsv2AspectProps {} + +/** + * Aspect that applies IMDS configuration on EC2 Launch Template constructs. + * + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-launchtemplatedata-metadataoptions.html + */ +export class LaunchTemplateRequireImdsv2Aspect extends RequireImdsv2Aspect { + constructor(props?: LaunchTemplateRequireImdsv2AspectProps) { + super(props); + } + + visit(node: cdk.IConstruct): void { + if (!(node instanceof LaunchTemplate)) { + return; + } + + const launchTemplate = node.node.tryFindChild('Resource') as CfnLaunchTemplate; + const data = launchTemplate.launchTemplateData; + if (cdk.isResolvableObject(data)) { + this.warn(node, 'LaunchTemplateData is a CDK token.'); + return; + } + + const metadataOptions = (data as CfnLaunchTemplate.LaunchTemplateDataProperty).metadataOptions; + if (cdk.isResolvableObject(metadataOptions)) { + this.warn(node, 'LaunchTemplateData.MetadataOptions is a CDK token.'); + return; + } + + const newData: CfnLaunchTemplate.LaunchTemplateDataProperty = { + ...data, + metadataOptions: { + ...metadataOptions, + httpTokens: 'required', + }, + }; + launchTemplate.launchTemplateData = newData; + } +} diff --git a/packages/@aws-cdk/aws-ec2/lib/index.ts b/packages/@aws-cdk/aws-ec2/lib/index.ts index 1b10e6fa1d566..4b0741044e4dd 100644 --- a/packages/@aws-cdk/aws-ec2/lib/index.ts +++ b/packages/@aws-cdk/aws-ec2/lib/index.ts @@ -1,3 +1,4 @@ +export * from './aspects'; export * from './bastion-host'; export * from './connections'; export * from './cfn-init'; diff --git a/packages/@aws-cdk/aws-ec2/lib/instance.ts b/packages/@aws-cdk/aws-ec2/lib/instance.ts index 813d4d5f43880..85b05fc71734b 100644 --- a/packages/@aws-cdk/aws-ec2/lib/instance.ts +++ b/packages/@aws-cdk/aws-ec2/lib/instance.ts @@ -1,8 +1,9 @@ import * as crypto from 'crypto'; import * as iam from '@aws-cdk/aws-iam'; -import { Annotations, Duration, Fn, IResource, Lazy, Resource, Stack, Tags } from '@aws-cdk/core'; +import { Annotations, Aspects, Duration, Fn, IResource, Lazy, Resource, Stack, Tags } from '@aws-cdk/core'; import { Construct } from 'constructs'; +import { InstanceRequireImdsv2Aspect } from './aspects'; import { CloudFormationInit } from './cfn-init'; import { Connections, IConnectable } from './connections'; import { CfnInstance } from './ec2.generated'; @@ -230,6 +231,13 @@ export interface InstanceProps { * @default - default options */ readonly initOptions?: ApplyCloudFormationInitOptions; + + /** + * Whether IMDSv2 should be required on this instance. + * + * @default - false + */ + readonly requireImdsv2?: boolean; } /** @@ -408,6 +416,10 @@ export class Instance extends Resource implements IInstance { return `${originalLogicalId}${digest}`; }, })); + + if (props.requireImdsv2) { + Aspects.of(this).add(new InstanceRequireImdsv2Aspect()); + } } /** diff --git a/packages/@aws-cdk/aws-ec2/lib/launch-template.ts b/packages/@aws-cdk/aws-ec2/lib/launch-template.ts index fdc03755c0268..ae7f5316c01af 100644 --- a/packages/@aws-cdk/aws-ec2/lib/launch-template.ts +++ b/packages/@aws-cdk/aws-ec2/lib/launch-template.ts @@ -12,8 +12,10 @@ import { TagType, Tags, Token, + Aspects, } from '@aws-cdk/core'; import { Construct } from 'constructs'; +import { LaunchTemplateRequireImdsv2Aspect } from '.'; import { Connections, IConnectable } from './connections'; import { CfnLaunchTemplate } from './ec2.generated'; import { InstanceType } from './instance-types'; @@ -332,6 +334,13 @@ export interface LaunchTemplateProps { * @default No security group is assigned. */ readonly securityGroup?: ISecurityGroup; + + /** + * Whether IMDSv2 should be required on launched instances. + * + * @default - false + */ + readonly requireImdsv2?: boolean; } /** @@ -637,6 +646,10 @@ export class LaunchTemplate extends Resource implements ILaunchTemplate, iam.IGr this.latestVersionNumber = resource.attrLatestVersionNumber; this.launchTemplateId = resource.ref; this.versionNumber = Token.asString(resource.getAtt('LatestVersionNumber')); + + if (props.requireImdsv2) { + Aspects.of(this).add(new LaunchTemplateRequireImdsv2Aspect()); + } } /** diff --git a/packages/@aws-cdk/aws-ec2/test/aspects/require-imdsv2-aspect.test.ts b/packages/@aws-cdk/aws-ec2/test/aspects/require-imdsv2-aspect.test.ts new file mode 100644 index 0000000000000..ade2eaeab1f1d --- /dev/null +++ b/packages/@aws-cdk/aws-ec2/test/aspects/require-imdsv2-aspect.test.ts @@ -0,0 +1,205 @@ +import { + countResources, + expect as expectCDK, + haveResourceLike, +} from '@aws-cdk/assert-internal'; +import '@aws-cdk/assert-internal/jest'; +import * as cdk from '@aws-cdk/core'; +import { + CfnLaunchTemplate, + Instance, + InstanceRequireImdsv2Aspect, + InstanceType, + LaunchTemplate, + LaunchTemplateRequireImdsv2Aspect, + MachineImage, + Vpc, +} from '../../lib'; + +describe('RequireImdsv2Aspect', () => { + let app: cdk.App; + let stack: cdk.Stack; + let vpc: Vpc; + + beforeEach(() => { + app = new cdk.App(); + stack = new cdk.Stack(app, 'Stack'); + vpc = new Vpc(stack, 'Vpc'); + }); + + test('suppresses warnings', () => { + // GIVEN + const aspect = new LaunchTemplateRequireImdsv2Aspect({ + suppressWarnings: true, + }); + const errmsg = 'ERROR'; + const visitMock = jest.spyOn(aspect, 'visit').mockImplementation((node) => { + // @ts-ignore + aspect.warn(node, errmsg); + }); + const construct = new cdk.Construct(stack, 'Construct'); + + // WHEN + aspect.visit(construct); + + // THEN + expect(visitMock).toHaveBeenCalled(); + expect(construct.node.metadataEntry).not.toContainEqual({ + data: expect.stringContaining(errmsg), + type: 'aws:cdk:warning', + trace: undefined, + }); + }); + + describe('InstanceRequireImdsv2Aspect', () => { + test('requires IMDSv2', () => { + // GIVEN + const instance = new Instance(stack, 'Instance', { + vpc, + instanceType: new InstanceType('t2.micro'), + machineImage: MachineImage.latestAmazonLinux(), + }); + const aspect = new InstanceRequireImdsv2Aspect(); + + // WHEN + cdk.Aspects.of(stack).add(aspect); + app.synth(); + + // THEN + const launchTemplate = instance.node.tryFindChild('LaunchTemplate') as LaunchTemplate; + expect(launchTemplate).toBeDefined(); + expectCDK(stack).to(haveResourceLike('AWS::EC2::LaunchTemplate', { + LaunchTemplateName: stack.resolve(launchTemplate.launchTemplateName), + LaunchTemplateData: { + MetadataOptions: { + HttpTokens: 'required', + }, + }, + })); + expectCDK(stack).to(haveResourceLike('AWS::EC2::Instance', { + LaunchTemplate: { + LaunchTemplateName: stack.resolve(launchTemplate.launchTemplateName), + }, + })); + }); + + test('does not toggle when Instance has a LaunchTemplate', () => { + // GIVEN + const instance = new Instance(stack, 'Instance', { + vpc, + instanceType: new InstanceType('t2.micro'), + machineImage: MachineImage.latestAmazonLinux(), + }); + instance.instance.launchTemplate = { + launchTemplateName: 'name', + version: 'version', + }; + const aspect = new InstanceRequireImdsv2Aspect(); + + // WHEN + cdk.Aspects.of(stack).add(aspect); + + // THEN + // Aspect normally creates a LaunchTemplate for the Instance to toggle IMDSv1, + // so we can assert that one was not created + expectCDK(stack).to(countResources('AWS::EC2::LaunchTemplate', 0)); + expect(instance.node.metadataEntry).toContainEqual({ + data: expect.stringContaining('Cannot toggle IMDSv1 because this Instance is associated with an existing Launch Template.'), + type: 'aws:cdk:warning', + trace: undefined, + }); + }); + + test('suppresses Launch Template warnings', () => { + // GIVEN + const instance = new Instance(stack, 'Instance', { + vpc, + instanceType: new InstanceType('t2.micro'), + machineImage: MachineImage.latestAmazonLinux(), + }); + instance.instance.launchTemplate = { + launchTemplateName: 'name', + version: 'version', + }; + const aspect = new InstanceRequireImdsv2Aspect({ + suppressLaunchTemplateWarning: true, + }); + + // WHEN + aspect.visit(instance); + + // THEN + expect(instance.node.metadataEntry).not.toContainEqual({ + data: expect.stringContaining('Cannot toggle IMDSv1 because this Instance is associated with an existing Launch Template.'), + type: 'aws:cdk:warning', + trace: undefined, + }); + }); + }); + + describe('LaunchTemplateRequireImdsv2Aspect', () => { + test('warns when LaunchTemplateData is a CDK token', () => { + // GIVEN + const launchTemplate = new LaunchTemplate(stack, 'LaunchTemplate'); + const cfnLaunchTemplate = launchTemplate.node.tryFindChild('Resource') as CfnLaunchTemplate; + cfnLaunchTemplate.launchTemplateData = fakeToken(); + const aspect = new LaunchTemplateRequireImdsv2Aspect(); + + // WHEN + aspect.visit(launchTemplate); + + // THEN + expect(launchTemplate.node.metadataEntry).toContainEqual({ + data: expect.stringContaining('LaunchTemplateData is a CDK token.'), + type: 'aws:cdk:warning', + trace: undefined, + }); + }); + + test('warns when MetadataOptions is a CDK token', () => { + // GIVEN + const launchTemplate = new LaunchTemplate(stack, 'LaunchTemplate'); + const cfnLaunchTemplate = launchTemplate.node.tryFindChild('Resource') as CfnLaunchTemplate; + cfnLaunchTemplate.launchTemplateData = { + metadataOptions: fakeToken(), + } as CfnLaunchTemplate.LaunchTemplateDataProperty; + const aspect = new LaunchTemplateRequireImdsv2Aspect(); + + // WHEN + aspect.visit(launchTemplate); + + // THEN + expect(launchTemplate.node.metadataEntry).toContainEqual({ + data: expect.stringContaining('LaunchTemplateData.MetadataOptions is a CDK token.'), + type: 'aws:cdk:warning', + trace: undefined, + }); + }); + + test('requires IMDSv2', () => { + // GIVEN + new LaunchTemplate(stack, 'LaunchTemplate'); + const aspect = new LaunchTemplateRequireImdsv2Aspect(); + + // WHEN + cdk.Aspects.of(stack).add(aspect); + + // THEN + expectCDK(stack).to(haveResourceLike('AWS::EC2::LaunchTemplate', { + LaunchTemplateData: { + MetadataOptions: { + HttpTokens: 'required', + }, + }, + })); + }); + }); +}); + +function fakeToken(): cdk.IResolvable { + return { + creationStack: [], + resolve: (_c) => {}, + toString: () => '', + }; +} diff --git a/packages/@aws-cdk/aws-ec2/test/instance.test.ts b/packages/@aws-cdk/aws-ec2/test/instance.test.ts index 884021f518a84..a3a389d94aa9d 100644 --- a/packages/@aws-cdk/aws-ec2/test/instance.test.ts +++ b/packages/@aws-cdk/aws-ec2/test/instance.test.ts @@ -7,7 +7,7 @@ import * as cxschema from '@aws-cdk/cloud-assembly-schema'; import { Stack } from '@aws-cdk/core'; import { AmazonLinuxImage, BlockDeviceVolume, CloudFormationInit, - EbsDeviceVolumeType, InitCommand, Instance, InstanceArchitecture, InstanceClass, InstanceSize, InstanceType, UserData, Vpc, + EbsDeviceVolumeType, InitCommand, Instance, InstanceArchitecture, InstanceClass, InstanceSize, InstanceType, LaunchTemplate, UserData, Vpc, } from '../lib'; @@ -361,6 +361,36 @@ describe('instance', () => { }); + + test('instance requires IMDSv2', () => { + // WHEN + const instance = new Instance(stack, 'Instance', { + vpc, + machineImage: new AmazonLinuxImage(), + instanceType: new InstanceType('t2.micro'), + requireImdsv2: true, + }); + + // Force stack synth so the InstanceRequireImdsv2Aspect is applied + SynthUtils.synthesize(stack); + + // THEN + const launchTemplate = instance.node.tryFindChild('LaunchTemplate') as LaunchTemplate; + expect(launchTemplate).toBeDefined(); + expect(stack).toHaveResourceLike('AWS::EC2::LaunchTemplate', { + LaunchTemplateName: stack.resolve(launchTemplate.launchTemplateName), + LaunchTemplateData: { + MetadataOptions: { + HttpTokens: 'required', + }, + }, + }); + expect(stack).toHaveResourceLike('AWS::EC2::Instance', { + LaunchTemplate: { + LaunchTemplateName: stack.resolve(launchTemplate.launchTemplateName), + }, + }); + }); }); diff --git a/packages/@aws-cdk/aws-ec2/test/launch-template.test.ts b/packages/@aws-cdk/aws-ec2/test/launch-template.test.ts index 27399affe8149..6243a409bc007 100644 --- a/packages/@aws-cdk/aws-ec2/test/launch-template.test.ts +++ b/packages/@aws-cdk/aws-ec2/test/launch-template.test.ts @@ -509,6 +509,22 @@ describe('LaunchTemplate', () => { }, }); }); + + test('Requires IMDSv2', () => { + // WHEN + new LaunchTemplate(stack, 'Template', { + requireImdsv2: true, + }); + + // THEN + expect(stack).toHaveResourceLike('AWS::EC2::LaunchTemplate', { + LaunchTemplateData: { + MetadataOptions: { + HttpTokens: 'required', + }, + }, + }); + }); }); describe('LaunchTemplate marketOptions', () => { From 4f392a1e1ccb8ce3cb19802932746c7f8d97831a Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Wed, 20 Oct 2021 12:10:53 +0200 Subject: [PATCH 21/89] chore: improve yarn lock error checking (#17001) The yarn lock checking script was always wrong: it would assume a package was local if its version number was `0.0.0`... but this is no longer true after running `align-version.sh`. I don't understand why this doesn't fail on the build server, but it definitely fails for me on my machine when trying to do a full build "as if" I was the build server. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- scripts/check-yarn-lock.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/check-yarn-lock.js b/scripts/check-yarn-lock.js index 8fd59b5a60bc8..1941ad074ece6 100755 --- a/scripts/check-yarn-lock.js +++ b/scripts/check-yarn-lock.js @@ -36,9 +36,11 @@ async function main() { const yarnPackages = yarnLockPackages(); const projects = await new Project(repoRoot()).getPackages(); + const localPackageNames = new Set(projects.map(p => p.name)); + function errorIfNotInYarnLock(package, dependencyName, dependencyVersion) { const dependencyId = `${dependencyName}@${dependencyVersion}`; - const isLocalDependency = dependencyVersion === '0.0.0' || dependencyVersion === '^0.0.0'; + const isLocalDependency = localPackageNames.has(dependencyName); if (!isLocalDependency && !yarnPackages.has(dependencyId)) { throw new Error(`ERROR! Dependency ${dependencyId} from ${package.name} not present in yarn.lock. Please run 'yarn install' and try again!`); } From ac54842ba15991b2359181a27d2530158622d9f9 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Wed, 20 Oct 2021 13:48:58 +0200 Subject: [PATCH 22/89] chore(assertions): remove `rosetta:extract` from build command (#17072) This form of executing Rosetta is not mocked by the jsii integ tests (which try executing a CDK build using a new version of the jsii tools). The jsii integ tests rely on passing environment variables `$CDK_BUILD_JSII`, `$PACMAK` and `$ROSETTA` (instead of replacing symlinks in the Node module farm). This leads to the generation of `.jsii.tabl.json` during build using the NPM-installed version of `jsii-rosetta`, which subsequently interferes with the run of `$PACMAK` which *is* the new version (since Rosetta tablets are supposed to be short-lived, there is no backwards compatibility guarantee between different versions). There will be a supported mechanism to achieve what this single post-build command is trying to achieve, so remove it. ---- *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 | 5 ----- 1 file changed, 5 deletions(-) diff --git a/packages/@aws-cdk/assertions/package.json b/packages/@aws-cdk/assertions/package.json index e87d1c9526302..ac9a08ae297d6 100644 --- a/packages/@aws-cdk/assertions/package.json +++ b/packages/@aws-cdk/assertions/package.json @@ -55,11 +55,6 @@ } } }, - "cdk-build": { - "post": [ - "yarn rosetta:extract" - ] - }, "author": { "name": "Amazon Web Services", "url": "https://aws.amazon.com", From 403d3ce3bc0f4e30e9694e5c20743f0032009464 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Wed, 20 Oct 2021 16:03:10 +0200 Subject: [PATCH 23/89] fix(pipelines): `additionalInputs` fails for deep directory (#17074) If the directory is nested deeper than one level underneath `.` or `..`, the wrong directory gets created. Also add in protection against the directory already existing, in which case the same behavior would happen. Fixes #16936. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../lib/codepipeline/_codebuild-factory.ts | 7 ++- .../test/codepipeline/codebuild-step.test.ts | 44 +++++++++++++++++++ .../pipelines/test/compliance/synths.test.ts | 4 +- 3 files changed, 51 insertions(+), 4 deletions(-) create mode 100644 packages/@aws-cdk/pipelines/test/codepipeline/codebuild-step.test.ts diff --git a/packages/@aws-cdk/pipelines/lib/codepipeline/_codebuild-factory.ts b/packages/@aws-cdk/pipelines/lib/codepipeline/_codebuild-factory.ts index 59abcbe8e287d..fb523cf7d6818 100644 --- a/packages/@aws-cdk/pipelines/lib/codepipeline/_codebuild-factory.ts +++ b/packages/@aws-cdk/pipelines/lib/codepipeline/_codebuild-factory.ts @@ -333,8 +333,11 @@ function generateInputArtifactLinkCommands(artifacts: ArtifactMap, inputs: FileS return inputs.map(input => { const fragments = []; - if (!['.', '..'].includes(path.dirname(input.directory))) { - fragments.push(`mkdir -p -- "${input.directory}"`); + fragments.push(`[[ ! -d "${input.directory}" ]] || { echo 'additionalInputs: "${input.directory}" must not exist yet. If you want to merge multiple artifacts, use a "cp" command.'; exit 1; }`); + + const parentDirectory = path.dirname(input.directory); + if (!['.', '..'].includes(parentDirectory)) { + fragments.push(`mkdir -p -- "${parentDirectory}"`); } const artifact = artifacts.toCodePipeline(input.fileSet); diff --git a/packages/@aws-cdk/pipelines/test/codepipeline/codebuild-step.test.ts b/packages/@aws-cdk/pipelines/test/codepipeline/codebuild-step.test.ts new file mode 100644 index 0000000000000..78f1e0f471655 --- /dev/null +++ b/packages/@aws-cdk/pipelines/test/codepipeline/codebuild-step.test.ts @@ -0,0 +1,44 @@ +import { Template, Match } from '@aws-cdk/assertions'; +import { Stack } from '@aws-cdk/core'; +import * as cdkp from '../../lib'; +import { PIPELINE_ENV, TestApp } from '../testhelpers'; + +let app: TestApp; +let pipelineStack: Stack; + +beforeEach(() => { + app = new TestApp(); + pipelineStack = new Stack(app, 'PipelineStack', { env: PIPELINE_ENV }); +}); + +afterEach(() => { + app.cleanup(); +}); + +test('additionalinputs creates the right commands', () => { + // WHEN + new cdkp.CodePipeline(pipelineStack, 'Pipeline', { + synth: new cdkp.CodeBuildStep('Synth', { + commands: ['/bin/true'], + input: cdkp.CodePipelineSource.gitHub('test/test', 'main'), + additionalInputs: { + 'some/deep/directory': cdkp.CodePipelineSource.gitHub('test2/test2', 'main'), + }, + }), + }); + + // THEN + Template.fromStack(pipelineStack).hasResourceProperties('AWS::CodeBuild::Project', { + Source: { + BuildSpec: Match.serializedJson(Match.objectLike({ + phases: { + install: { + commands: [ + '[[ ! -d "some/deep/directory" ]] || { echo \'additionalInputs: "some/deep/directory" must not exist yet. If you want to merge multiple artifacts, use a "cp" command.\'; exit 1; } && mkdir -p -- "some/deep" && ln -s -- "$CODEBUILD_SRC_DIR_test2_test2_Source" "some/deep/directory"', + ], + }, + }, + })), + }, + }); +}); \ No newline at end of file diff --git a/packages/@aws-cdk/pipelines/test/compliance/synths.test.ts b/packages/@aws-cdk/pipelines/test/compliance/synths.test.ts index f8e39a536309f..4b5a072099469 100644 --- a/packages/@aws-cdk/pipelines/test/compliance/synths.test.ts +++ b/packages/@aws-cdk/pipelines/test/compliance/synths.test.ts @@ -947,8 +947,8 @@ behavior('Multiple input sources in side-by-side directories', (suite) => { phases: { install: { commands: [ - 'ln -s -- "$CODEBUILD_SRC_DIR_foo_bar_Source" "../sibling"', - 'ln -s -- "$CODEBUILD_SRC_DIR_Prebuild_Output" "sub"', + '[[ ! -d "../sibling" ]] || { echo \'additionalInputs: "../sibling" must not exist yet. If you want to merge multiple artifacts, use a "cp" command.\'; exit 1; } && ln -s -- "$CODEBUILD_SRC_DIR_foo_bar_Source" "../sibling"', + '[[ ! -d "sub" ]] || { echo \'additionalInputs: "sub" must not exist yet. If you want to merge multiple artifacts, use a "cp" command.\'; exit 1; } && ln -s -- "$CODEBUILD_SRC_DIR_Prebuild_Output" "sub"', ], }, build: { From 7a63b92a37ae2f142af51e6e73ca5896d59a4591 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Wed, 20 Oct 2021 13:48:58 +0200 Subject: [PATCH 24/89] chore(assertions): remove `rosetta:extract` from build command (#17072) This form of executing Rosetta is not mocked by the jsii integ tests (which try executing a CDK build using a new version of the jsii tools). The jsii integ tests rely on passing environment variables `$CDK_BUILD_JSII`, `$PACMAK` and `$ROSETTA` (instead of replacing symlinks in the Node module farm). This leads to the generation of `.jsii.tabl.json` during build using the NPM-installed version of `jsii-rosetta`, which subsequently interferes with the run of `$PACMAK` which *is* the new version (since Rosetta tablets are supposed to be short-lived, there is no backwards compatibility guarantee between different versions). There will be a supported mechanism to achieve what this single post-build command is trying to achieve, so remove it. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* (cherry picked from commit ac54842ba15991b2359181a27d2530158622d9f9) --- packages/@aws-cdk/assertions/package.json | 5 ----- 1 file changed, 5 deletions(-) diff --git a/packages/@aws-cdk/assertions/package.json b/packages/@aws-cdk/assertions/package.json index e87d1c9526302..ac9a08ae297d6 100644 --- a/packages/@aws-cdk/assertions/package.json +++ b/packages/@aws-cdk/assertions/package.json @@ -55,11 +55,6 @@ } } }, - "cdk-build": { - "post": [ - "yarn rosetta:extract" - ] - }, "author": { "name": "Amazon Web Services", "url": "https://aws.amazon.com", From 1fa1876e65b5124a4348d71ae6c1f8b153d34eb2 Mon Sep 17 00:00:00 2001 From: Otavio Macedo Date: Wed, 20 Oct 2021 16:27:30 +0100 Subject: [PATCH 25/89] chore: replaced merge action with a queue action (#17052) Co-authored-by: Otavio Macedo --- .mergify.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.mergify.yml b/.mergify.yml index 97f3ce42a91be..be30275403f3e 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -1,4 +1,8 @@ # See https://doc.mergify.io +queue_rules: + - name: default + conditions: + - status-success~=AWS CodeBuild us-east-1 pull_request_rules: - name: label core @@ -12,10 +16,9 @@ pull_request_rules: actions: comment: message: Thank you for contributing! Your pull request will be updated from master and then merged automatically (do not update manually, and be sure to [allow changes to be pushed to your fork](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/allowing-changes-to-a-pull-request-branch-created-from-a-fork)). - merge: - strict: smart + queue: + name: default method: squash - strict_method: merge commit_message: title+body conditions: - base!=release From a129046495a926561f94f5ce1f41c34b1df3afde Mon Sep 17 00:00:00 2001 From: Ryan Parker Date: Wed, 20 Oct 2021 14:49:13 -0700 Subject: [PATCH 26/89] fix(lambda-layer-node-proxy-agent): Replace use of package.json with Dockerfile command `npm install [package]@[version]` (#17078) ## Summary This PR fixes an issue where the package.json file used in `lambda-layer-node-proxy-agent` was not being bundled into monocdk / CDK v2. This is due to limitations of Ubergen. Ubergen only copies .ts files, README.md files and some special .json files. This PR: - Removes the package.json from `packages/@aws-cdk/lambda-layer-node-proxy-agent/layer` - Adds a step in the layer's Dockerfile to install a specific version of `proxy-agent` i.e. `npm install [package]@[version]`. This is so that we can do without the `package.json` file while still managing which version we bundle with the layer. Fixes: https://github.com/aws/aws-cdk/issues/17061 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../lambda-layer-node-proxy-agent/layer/.dockerignore | 1 - .../layer/.no-packagejson-validator | 0 .../lambda-layer-node-proxy-agent/layer/Dockerfile | 5 +++-- .../lambda-layer-node-proxy-agent/layer/package.json | 9 --------- .../lib/node-proxy-agent-layer.ts | 4 ++-- 5 files changed, 5 insertions(+), 14 deletions(-) delete mode 100644 packages/@aws-cdk/lambda-layer-node-proxy-agent/layer/.no-packagejson-validator delete mode 100644 packages/@aws-cdk/lambda-layer-node-proxy-agent/layer/package.json diff --git a/packages/@aws-cdk/lambda-layer-node-proxy-agent/layer/.dockerignore b/packages/@aws-cdk/lambda-layer-node-proxy-agent/layer/.dockerignore index 69b73f61d249a..88a84e55aa43b 100644 --- a/packages/@aws-cdk/lambda-layer-node-proxy-agent/layer/.dockerignore +++ b/packages/@aws-cdk/lambda-layer-node-proxy-agent/layer/.dockerignore @@ -1,2 +1 @@ build.sh -.no-packagejson-validator diff --git a/packages/@aws-cdk/lambda-layer-node-proxy-agent/layer/.no-packagejson-validator b/packages/@aws-cdk/lambda-layer-node-proxy-agent/layer/.no-packagejson-validator deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/packages/@aws-cdk/lambda-layer-node-proxy-agent/layer/Dockerfile b/packages/@aws-cdk/lambda-layer-node-proxy-agent/layer/Dockerfile index 8c747a0e2b95f..2e3f644258652 100644 --- a/packages/@aws-cdk/lambda-layer-node-proxy-agent/layer/Dockerfile +++ b/packages/@aws-cdk/lambda-layer-node-proxy-agent/layer/Dockerfile @@ -1,6 +1,8 @@ # base lambda image FROM public.ecr.aws/lambda/nodejs:latest +ARG PROXY_AGENT_VERSION=5.0.0 + USER root RUN mkdir -p /opt WORKDIR /tmp @@ -17,8 +19,7 @@ RUN yum update -y \ # RUN mkdir -p /opt/nodejs -COPY package.json /opt/nodejs -RUN cd /opt/nodejs && npm install +RUN cd /opt/nodejs && npm install proxy-agent@${PROXY_AGENT_VERSION} # # create the bundle diff --git a/packages/@aws-cdk/lambda-layer-node-proxy-agent/layer/package.json b/packages/@aws-cdk/lambda-layer-node-proxy-agent/layer/package.json deleted file mode 100644 index 102dd83c99391..0000000000000 --- a/packages/@aws-cdk/lambda-layer-node-proxy-agent/layer/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "node-proxy-agent-layer", - "private": true, - "version": "0.0.1", - "license": "Apache-2.0", - "devDependencies": { - "proxy-agent": "^5.0.0" - } -} diff --git a/packages/@aws-cdk/lambda-layer-node-proxy-agent/lib/node-proxy-agent-layer.ts b/packages/@aws-cdk/lambda-layer-node-proxy-agent/lib/node-proxy-agent-layer.ts index 9e6471a2da2c6..60b8c8697dea7 100644 --- a/packages/@aws-cdk/lambda-layer-node-proxy-agent/lib/node-proxy-agent-layer.ts +++ b/packages/@aws-cdk/lambda-layer-node-proxy-agent/lib/node-proxy-agent-layer.ts @@ -11,8 +11,8 @@ export class NodeProxyAgentLayer extends lambda.LayerVersion { constructor(scope: Construct, id: string) { super(scope, id, { code: lambda.Code.fromAsset(path.join(__dirname, 'layer.zip'), { - // we hash the package.json (it contains the tools versions) because hashing the zip is non-deterministic - assetHash: hashFile(path.join(__dirname, '..', 'layer', 'package.json')), + // we hash the Dockerfile (it contains the tools versions) because hashing the zip is non-deterministic + assetHash: hashFile(path.join(__dirname, '..', 'layer', 'Dockerfile')), }), description: '/opt/nodejs/node_modules/proxy-agent', }); From 74066ca5c19509b60d95fc35ac7f732f44c6d8ae Mon Sep 17 00:00:00 2001 From: Otavio Macedo Date: Thu, 21 Oct 2021 10:15:39 +0100 Subject: [PATCH 27/89] chore: bumped jsii dependencies to 1.40.0 (#17087) ---- *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/aws-cdk/package.json | 2 +- packages/awslint/package.json | 4 +- packages/decdk/package.json | 4 +- tools/@aws-cdk/cdk-build-tools/package.json | 6 +- yarn.lock | 103 +++++++++++--------- 6 files changed, 68 insertions(+), 59 deletions(-) diff --git a/package.json b/package.json index 97612d72cea6f..7db1f7c20c0ad 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.39.0", - "jsii-pacmak": "^1.39.0", - "jsii-reflect": "^1.39.0", - "jsii-rosetta": "^1.39.0", + "jsii-diff": "^1.40.0", + "jsii-pacmak": "^1.40.0", + "jsii-reflect": "^1.40.0", + "jsii-rosetta": "^1.40.0", "lerna": "^4.0.0", "patch-package": "^6.4.7", "standard-version": "^9.3.1", diff --git a/packages/aws-cdk/package.json b/packages/aws-cdk/package.json index 1e6f3b7bef7fe..4492f92549b45 100644 --- a/packages/aws-cdk/package.json +++ b/packages/aws-cdk/package.json @@ -71,7 +71,7 @@ "@aws-cdk/cloudformation-diff": "0.0.0", "@aws-cdk/cx-api": "0.0.0", "@aws-cdk/region-info": "0.0.0", - "@jsii/check-node": "1.39.0", + "@jsii/check-node": "1.40.0", "archiver": "^5.3.0", "aws-sdk": "^2.979.0", "camelcase": "^6.2.0", diff --git a/packages/awslint/package.json b/packages/awslint/package.json index f035267fc9292..1bae6a09ba6cb 100644 --- a/packages/awslint/package.json +++ b/packages/awslint/package.json @@ -18,11 +18,11 @@ "awslint": "bin/awslint" }, "dependencies": { - "@jsii/spec": "^1.39.0", + "@jsii/spec": "^1.40.0", "camelcase": "^6.2.0", "colors": "^1.4.0", "fs-extra": "^9.1.0", - "jsii-reflect": "^1.39.0", + "jsii-reflect": "^1.40.0", "yargs": "^16.2.0" }, "devDependencies": { diff --git a/packages/decdk/package.json b/packages/decdk/package.json index 6ee38d4e401a4..8a87b4a7001f8 100644 --- a/packages/decdk/package.json +++ b/packages/decdk/package.json @@ -243,7 +243,7 @@ "@aws-cdk/region-info": "0.0.0", "constructs": "^3.3.69", "fs-extra": "^9.1.0", - "jsii-reflect": "^1.39.0", + "jsii-reflect": "^1.40.0", "jsonschema": "^1.4.0", "yaml": "1.10.2", "yargs": "^16.2.0" @@ -254,7 +254,7 @@ "@types/yaml": "1.9.7", "@types/yargs": "^15.0.14", "jest": "^26.6.3", - "jsii": "^1.39.0" + "jsii": "^1.40.0" }, "keywords": [ "aws", diff --git a/tools/@aws-cdk/cdk-build-tools/package.json b/tools/@aws-cdk/cdk-build-tools/package.json index d2b03befabebb..84005357a2458 100644 --- a/tools/@aws-cdk/cdk-build-tools/package.json +++ b/tools/@aws-cdk/cdk-build-tools/package.json @@ -55,9 +55,9 @@ "fs-extra": "^9.1.0", "jest": "^26.6.3", "jest-junit": "^11.1.0", - "jsii": "^1.39.0", - "jsii-pacmak": "^1.39.0", - "jsii-reflect": "^1.39.0", + "jsii": "^1.40.0", + "jsii-pacmak": "^1.40.0", + "jsii-reflect": "^1.40.0", "markdownlint-cli": "^0.29.0", "nyc": "^15.1.0", "semver": "^7.3.5", diff --git a/yarn.lock b/yarn.lock index 3fc7477ad872b..442e61841ae13 100644 --- a/yarn.lock +++ b/yarn.lock @@ -576,18 +576,18 @@ "@types/yargs" "^15.0.0" chalk "^4.0.0" -"@jsii/check-node@1.39.0": - version "1.39.0" - resolved "https://registry.npmjs.org/@jsii/check-node/-/check-node-1.39.0.tgz#31a22f6270c790b5f2bb0f7d2950511e6d7c0c9e" - integrity sha512-tqx5o0Zw6WrVKmB9S1X0E8AajfXjWu9yoOUtUdYVCR6NAdi8mY/NQ3uYJ8II0AF1MtC0PdASOjb/6i3h02komw== +"@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" + integrity sha512-rk0hFXxFQR8rDGUfsZT9ua6OufOpnLQWsNFyFU86AvpoKQ0ciw2KlGdWs7OYFnzPq8sQGhSS+iuBrUboaHW3jg== dependencies: chalk "^4.1.2" semver "^7.3.5" -"@jsii/spec@^1.39.0": - version "1.39.0" - resolved "https://registry.npmjs.org/@jsii/spec/-/spec-1.39.0.tgz#17b2d55f8261da3ed4a670e9a4c5dfa18a7e050a" - integrity sha512-NbCmAYOB938uyWHwXj6fhdeIzznhHbxLmvl4Jtwe08Nrz5Gs4n79snV29XWIQulDMa4HYkNh1yqhBXOHkd+GAg== +"@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== dependencies: jsonschema "^1.4.0" @@ -2845,6 +2845,15 @@ 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== + dependencies: + camelcase "^6.2.0" + decamelize "^5.0.1" + fs-extra "^9.1.0" + collect-v8-coverage@^1.0.0: version "1.0.1" resolved "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" @@ -6011,70 +6020,70 @@ jsesc@^2.5.1: resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== -jsii-diff@^1.39.0: - version "1.39.0" - resolved "https://registry.npmjs.org/jsii-diff/-/jsii-diff-1.39.0.tgz#e6dc9ffc5689bfcfa2bcd9532829054003547470" - integrity sha512-O49YB3IElNIyP7zbBXLTYmLPwxxJY4Zs4rcZ4zpO73Yv373edT+TmoKkZV05DhKNcU79nFPB+axr6sKP6ElzFw== +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== dependencies: - "@jsii/check-node" "1.39.0" - "@jsii/spec" "^1.39.0" + "@jsii/check-node" "1.40.0" + "@jsii/spec" "^1.40.0" fs-extra "^9.1.0" - jsii-reflect "^1.39.0" + jsii-reflect "^1.40.0" log4js "^6.3.0" typescript "~3.9.10" yargs "^16.2.0" -jsii-pacmak@^1.39.0: - version "1.39.0" - resolved "https://registry.npmjs.org/jsii-pacmak/-/jsii-pacmak-1.39.0.tgz#b5c66eb32a62390e02c0273f6edca3871600cc74" - integrity sha512-+B2Z62v/MQ8fQcvd1nhKUWv+ZoNEArwa6OiTSvAuMsRoZpZ7Uvabscu71Uu3zq1XzJ6WQStw90ENHkw40l/o7w== +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== dependencies: - "@jsii/check-node" "1.39.0" - "@jsii/spec" "^1.39.0" + "@jsii/check-node" "1.40.0" + "@jsii/spec" "^1.40.0" clone "^2.1.2" - codemaker "^1.39.0" + codemaker "^1.40.0" commonmark "^0.30.0" escape-string-regexp "^4.0.0" fs-extra "^9.1.0" - jsii-reflect "^1.39.0" - jsii-rosetta "^1.39.0" + jsii-reflect "^1.40.0" + jsii-rosetta "^1.40.0" semver "^7.3.5" spdx-license-list "^6.4.0" xmlbuilder "^15.1.1" yargs "^16.2.0" -jsii-reflect@^1.39.0: - version "1.39.0" - resolved "https://registry.npmjs.org/jsii-reflect/-/jsii-reflect-1.39.0.tgz#c35a395b7ec14c4e94aef8bf195a0ff329311534" - integrity sha512-HEMpGHJBDtUbhdnfYUH0M/NTrYxaXrb0B2DXglzN/EYzKJsdp4FAmDPzpKEwnGVK3ReJLZ68YRogTq3msyuQDQ== +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== dependencies: - "@jsii/check-node" "1.39.0" - "@jsii/spec" "^1.39.0" + "@jsii/check-node" "1.40.0" + "@jsii/spec" "^1.40.0" colors "^1.4.0" fs-extra "^9.1.0" - oo-ascii-tree "^1.39.0" + oo-ascii-tree "^1.40.0" yargs "^16.2.0" -jsii-rosetta@^1.39.0: - version "1.39.0" - resolved "https://registry.npmjs.org/jsii-rosetta/-/jsii-rosetta-1.39.0.tgz#b4251bb9b0295d2a8c2c7a7d8b1d8d744f432305" - integrity sha512-Fx+kQ+IDEMILQvTESW9TMXLxzQa7h/nm4EKXuDKAeglr5RNhzvTvhsgJy+WshJoMsNcT9ImCV8gmvqAqdSBrWA== +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== dependencies: - "@jsii/check-node" "1.39.0" - "@jsii/spec" "^1.39.0" + "@jsii/check-node" "1.40.0" + "@jsii/spec" "^1.40.0" "@xmldom/xmldom" "^0.7.5" commonmark "^0.30.0" fs-extra "^9.1.0" typescript "~3.9.10" yargs "^16.2.0" -jsii@^1.39.0: - version "1.39.0" - resolved "https://registry.npmjs.org/jsii/-/jsii-1.39.0.tgz#68554dd5c20ac4b7da118f748d5297e5f9e58384" - integrity sha512-2ReD7t6rGhT+c41xovFoAMc4XU5/O2VqGRh3Ud/wN+Nn1ISjZFQa4doQ1xtZLFb1065Vxyv5VCqWp80t6Xw2iA== +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== dependencies: - "@jsii/check-node" "1.39.0" - "@jsii/spec" "^1.39.0" + "@jsii/check-node" "1.40.0" + "@jsii/spec" "^1.40.0" case "^1.6.3" colors "^1.4.0" deep-equal "^2.0.5" @@ -7413,10 +7422,10 @@ onetime@^5.1.0, onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" -oo-ascii-tree@^1.39.0: - version "1.39.0" - resolved "https://registry.npmjs.org/oo-ascii-tree/-/oo-ascii-tree-1.39.0.tgz#7dfc1fc11e0c7c7bf34d0b91591db9bfe0406cbb" - integrity sha512-a0g33GTdCizt5jnQzY9j6cRNyx5xITmZb+b3C21+KNweaERltcR1BQO/tLUuuVEFRVWvZcUqrFDVa8f8nqOafA== +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== open@^7.4.2: version "7.4.2" From 76b9efadbf85cedd88838616f556f99c0dda4979 Mon Sep 17 00:00:00 2001 From: AWS CDK Team Date: Thu, 21 Oct 2021 12:40:24 +0000 Subject: [PATCH 28/89] chore(release): 1.129.0 --- CHANGELOG.md | 26 ++++++++++++++++++++++++++ version.v1.json | 2 +- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f254623e858c1..8c9fd17ee41a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,32 @@ 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.129.0](https://github.com/aws/aws-cdk/compare/v1.128.0...v1.129.0) (2021-10-21) + + +### Features + +* **aws-autoscaling:** add flag and aspect to require imdsv2 ([#16052](https://github.com/aws/aws-cdk/issues/16052)) ([ef7e20d](https://github.com/aws/aws-cdk/commit/ef7e20df08b4321f210bfc050afa42d7b4901931)) +* **codebuild:** add support for small ARM machine type ([#16635](https://github.com/aws/aws-cdk/issues/16635)) ([55fbc86](https://github.com/aws/aws-cdk/commit/55fbc866ef0195fdfc722206e4d69a1f4469cd40)), closes [#16633](https://github.com/aws/aws-cdk/issues/16633) +* **dynamodb:** add option to skip waiting for global replication to finish ([#16983](https://github.com/aws/aws-cdk/issues/16983)) ([254601f](https://github.com/aws/aws-cdk/commit/254601f477a4da309e81f5384140427f1b958bfd)), closes [#16611](https://github.com/aws/aws-cdk/issues/16611) +* **ec2:** add aspect to require imdsv2 ([#16051](https://github.com/aws/aws-cdk/issues/16051)) ([0947b21](https://github.com/aws/aws-cdk/commit/0947b21c1e3186042324820ec5ab433237246f58)) +* **eks:** configure serviceIpv4Cidr on the cluster ([#16957](https://github.com/aws/aws-cdk/issues/16957)) ([72102c7](https://github.com/aws/aws-cdk/commit/72102c750bfd6564cd51c1a5d8abc79b1ba1d3ce)), closes [/docs.aws.amazon.com/eks/latest/APIReference/API_KubernetesNetworkConfigRequest.html#AmazonEKS-Type-KubernetesNetworkConfigRequest-serviceIpv4](https://github.com/aws//docs.aws.amazon.com/eks/latest/APIReference/API_KubernetesNetworkConfigRequest.html/issues/AmazonEKS-Type-KubernetesNetworkConfigRequest-serviceIpv4) [#16541](https://github.com/aws/aws-cdk/issues/16541) +* **events:** Add DLQ support for SQS target ([#16916](https://github.com/aws/aws-cdk/issues/16916)) ([7fda903](https://github.com/aws/aws-cdk/commit/7fda90318e18b3a5d126b040e35a0146634d5f2d)), closes [#16417](https://github.com/aws/aws-cdk/issues/16417) +* **msk:** add Kafka version 2.8.1 ([#16881](https://github.com/aws/aws-cdk/issues/16881)) ([7db5c8c](https://github.com/aws/aws-cdk/commit/7db5c8cdafe7b9b22b6b40cb25ed8bd1946301f4)) +* **stepfunctions-tasks:** add `enableNetworkIsolation` property to `SageMakerCreateTrainingJobProps` ([#16792](https://github.com/aws/aws-cdk/issues/16792)) ([69ac520](https://github.com/aws/aws-cdk/commit/69ac520452b219bf242f2fbb4740f6b1b8b8790f)), closes [#16779](https://github.com/aws/aws-cdk/issues/16779) + + +### Bug Fixes + +* **apigatewayv2:** unable to retrieve domain url for default stage ([#16854](https://github.com/aws/aws-cdk/issues/16854)) ([c6db91e](https://github.com/aws/aws-cdk/commit/c6db91eee2cb658ce347c7ac6d6e3c95bc5977dc)), closes [#16638](https://github.com/aws/aws-cdk/issues/16638) +* **cfn-diff:** correctly handle Date strings in diff ([#16591](https://github.com/aws/aws-cdk/issues/16591)) ([86f2714](https://github.com/aws/aws-cdk/commit/86f2714613f06aaf2bcee27da2f66066c8e863d0)), closes [#16444](https://github.com/aws/aws-cdk/issues/16444) +* **ecs:** imported services don't have account & region set correctly ([#16997](https://github.com/aws/aws-cdk/issues/16997)) ([dc6f743](https://github.com/aws/aws-cdk/commit/dc6f7433f01b9bc2c8206fb03d72ab8404fe4f6a)), closes [#11199](https://github.com/aws/aws-cdk/issues/11199) [#11199](https://github.com/aws/aws-cdk/issues/11199) [#15944](https://github.com/aws/aws-cdk/issues/15944) +* **events:** PhysicalName.GENERATE_IF_NEEDED does not work for EventBus ([#17008](https://github.com/aws/aws-cdk/issues/17008)) ([707fa00](https://github.com/aws/aws-cdk/commit/707fa003a458039878a1ae5173b6665a84c1170b)), closes [#14337](https://github.com/aws/aws-cdk/issues/14337) +* **lambda:** docker image function fails when insightsVersion is specified ([#16781](https://github.com/aws/aws-cdk/issues/16781)) ([d0e15cc](https://github.com/aws/aws-cdk/commit/d0e15ccaca22c5e05b9186aa1a241e744d67c96a)), closes [#16642](https://github.com/aws/aws-cdk/issues/16642) +* **lambda-layer-node-proxy-agent:** Replace use of package.json with Dockerfile command `npm install [package]@[version]` ([#17078](https://github.com/aws/aws-cdk/issues/17078)) ([a129046](https://github.com/aws/aws-cdk/commit/a129046495a926561f94f5ce1f41c34b1df3afde)) +* **opensearch:** add validation to domainName property ([#17017](https://github.com/aws/aws-cdk/issues/17017)) ([3ec6832](https://github.com/aws/aws-cdk/commit/3ec683283e96159d588797bd46d33c82ff3076f1)), closes [#17016](https://github.com/aws/aws-cdk/issues/17016) +* **pipelines:** `additionalInputs` fails for deep directory ([#17074](https://github.com/aws/aws-cdk/issues/17074)) ([403d3ce](https://github.com/aws/aws-cdk/commit/403d3ce3bc0f4e30e9694e5c20743f0032009464)), closes [#16936](https://github.com/aws/aws-cdk/issues/16936) + ## [1.128.0](https://github.com/aws/aws-cdk/compare/v1.127.0...v1.128.0) (2021-10-14) diff --git a/version.v1.json b/version.v1.json index c24ba0065c588..cdb974a76d7f9 100644 --- a/version.v1.json +++ b/version.v1.json @@ -1,3 +1,3 @@ { - "version": "1.128.0" + "version": "1.129.0" } \ No newline at end of file From 3987808d16dbb37b6d5c16ad7a23d07bc6c2e9ec Mon Sep 17 00:00:00 2001 From: Otavio Macedo Date: Thu, 21 Oct 2021 13:45:13 +0100 Subject: [PATCH 29/89] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c9fd17ee41a3..511ed1a25dabd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ All notable changes to this project will be documented in this file. See [standa * **codebuild:** add support for small ARM machine type ([#16635](https://github.com/aws/aws-cdk/issues/16635)) ([55fbc86](https://github.com/aws/aws-cdk/commit/55fbc866ef0195fdfc722206e4d69a1f4469cd40)), closes [#16633](https://github.com/aws/aws-cdk/issues/16633) * **dynamodb:** add option to skip waiting for global replication to finish ([#16983](https://github.com/aws/aws-cdk/issues/16983)) ([254601f](https://github.com/aws/aws-cdk/commit/254601f477a4da309e81f5384140427f1b958bfd)), closes [#16611](https://github.com/aws/aws-cdk/issues/16611) * **ec2:** add aspect to require imdsv2 ([#16051](https://github.com/aws/aws-cdk/issues/16051)) ([0947b21](https://github.com/aws/aws-cdk/commit/0947b21c1e3186042324820ec5ab433237246f58)) -* **eks:** configure serviceIpv4Cidr on the cluster ([#16957](https://github.com/aws/aws-cdk/issues/16957)) ([72102c7](https://github.com/aws/aws-cdk/commit/72102c750bfd6564cd51c1a5d8abc79b1ba1d3ce)), closes [/docs.aws.amazon.com/eks/latest/APIReference/API_KubernetesNetworkConfigRequest.html#AmazonEKS-Type-KubernetesNetworkConfigRequest-serviceIpv4](https://github.com/aws//docs.aws.amazon.com/eks/latest/APIReference/API_KubernetesNetworkConfigRequest.html/issues/AmazonEKS-Type-KubernetesNetworkConfigRequest-serviceIpv4) [#16541](https://github.com/aws/aws-cdk/issues/16541) +* **eks:** configure serviceIpv4Cidr on the cluster ([#16957](https://github.com/aws/aws-cdk/issues/16957)) ([72102c7](https://github.com/aws/aws-cdk/commit/72102c750bfd6564cd51c1a5d8abc79b1ba1d3ce)), closes [#16541](https://github.com/aws/aws-cdk/issues/16541) * **events:** Add DLQ support for SQS target ([#16916](https://github.com/aws/aws-cdk/issues/16916)) ([7fda903](https://github.com/aws/aws-cdk/commit/7fda90318e18b3a5d126b040e35a0146634d5f2d)), closes [#16417](https://github.com/aws/aws-cdk/issues/16417) * **msk:** add Kafka version 2.8.1 ([#16881](https://github.com/aws/aws-cdk/issues/16881)) ([7db5c8c](https://github.com/aws/aws-cdk/commit/7db5c8cdafe7b9b22b6b40cb25ed8bd1946301f4)) * **stepfunctions-tasks:** add `enableNetworkIsolation` property to `SageMakerCreateTrainingJobProps` ([#16792](https://github.com/aws/aws-cdk/issues/16792)) ([69ac520](https://github.com/aws/aws-cdk/commit/69ac520452b219bf242f2fbb4740f6b1b8b8790f)), closes [#16779](https://github.com/aws/aws-cdk/issues/16779) From ee24046466f42efca4bf2b14ce9f344f174afa78 Mon Sep 17 00:00:00 2001 From: Nick Lynch Date: Thu, 21 Oct 2021 16:15:43 +0100 Subject: [PATCH 30/89] 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 31/89] 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 32/89] 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 33/89] 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 34/89] 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 35/89] 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 36/89] 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 37/89] 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 38/89] 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 39/89] 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 40/89] 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 41/89] 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 42/89] 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 43/89] 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 44/89] 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 45/89] 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 46/89] 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 47/89] 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 48/89] 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 49/89] 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 50/89] 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 51/89] 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 52/89] 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 53/89] 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 54/89] 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 55/89] 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 56/89] 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 57/89] 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 58/89] 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 59/89] 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 60/89] 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 61/89] 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 62/89] 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 63/89] 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 64/89] 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 65/89] 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 66/89] 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 67/89] 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 68/89] 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 69/89] 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 70/89] 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 71/89] 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 72/89] 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 73/89] 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 74/89] 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 75/89] 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 76/89] 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 77/89] 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 78/89] 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 79/89] 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 80/89] 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 81/89] 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 82/89] 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 83/89] 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 84/89] 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 85/89] 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 86/89] 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 87/89] 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 88/89] 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 89/89] 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', {