From f58cf3c95eb32e9a4dc797665160e1b508ace2e1 Mon Sep 17 00:00:00 2001 From: Artem Butusov Date: Mon, 2 Aug 2021 10:31:30 -0400 Subject: [PATCH 01/99] feat(s3-deployment): control object access (#15730) Add support for BucketDeployment accessControl property to aws-s3-deployment package. This is needed to run, for example, `aws s3 sync` with `--acl bucket-owner-full-control`. Without this feature there is no easy way (without hacking cdk nodes) to sync assets to bucket located in another account. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- package.json | 2 + packages/@aws-cdk/aws-s3-deployment/NOTICE | 30 +++++++++++++++ packages/@aws-cdk/aws-s3-deployment/README.md | 30 +++++++++------ .../lib/bucket-deployment.ts | 8 ++++ .../@aws-cdk/aws-s3-deployment/package.json | 4 ++ .../test/bucket-deployment.test.ts | 38 +++++++++++++++++++ 6 files changed, 100 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index 66025c149aa84..a18d46e63c20d 100644 --- a/package.json +++ b/package.json @@ -93,6 +93,8 @@ "@aws-cdk/aws-eks/yaml/**", "@aws-cdk/aws-events-targets/aws-sdk", "@aws-cdk/aws-events-targets/aws-sdk/**", + "@aws-cdk/aws-s3-deployment/case", + "@aws-cdk/aws-s3-deployment/case/**", "@aws-cdk/cloud-assembly-schema/jsonschema", "@aws-cdk/cloud-assembly-schema/jsonschema/**", "@aws-cdk/cloud-assembly-schema/semver", diff --git a/packages/@aws-cdk/aws-s3-deployment/NOTICE b/packages/@aws-cdk/aws-s3-deployment/NOTICE index 5fc3826926b5b..39cd25bf899ae 100644 --- a/packages/@aws-cdk/aws-s3-deployment/NOTICE +++ b/packages/@aws-cdk/aws-s3-deployment/NOTICE @@ -1,2 +1,32 @@ 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: + +** case - https://www.npmjs.com/package/case +Copyright (c) 2013 Nathan Bubna + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +---------------- diff --git a/packages/@aws-cdk/aws-s3-deployment/README.md b/packages/@aws-cdk/aws-s3-deployment/README.md index 3818a8e469cf5..a896d55cfc575 100644 --- a/packages/@aws-cdk/aws-s3-deployment/README.md +++ b/packages/@aws-cdk/aws-s3-deployment/README.md @@ -147,17 +147,22 @@ User-defined metadata are not used by S3 and keys always begin with `x-amz-meta- System defined metadata keys include the following: -- cache-control -- content-disposition -- content-encoding -- content-language -- content-type -- expires -- server-side-encryption -- storage-class -- website-redirect-location -- ssekms-key-id -- sse-customer-algorithm +- cache-control (`--cache-control` in `aws s3 sync`) +- content-disposition (`--content-disposition` in `aws s3 sync`) +- content-encoding (`--content-encoding` in `aws s3 sync`) +- content-language (`--content-language` in `aws s3 sync`) +- content-type (`--content-type` in `aws s3 sync`) +- expires (`--expires` in `aws s3 sync`) +- x-amz-storage-class (`--storage-class` in `aws s3 sync`) +- x-amz-website-redirect-location (`--website-redirect` in `aws s3 sync`) +- x-amz-server-side-encryption (`--sse` in `aws s3 sync`) +- x-amz-server-side-encryption-aws-kms-key-id (`--sse-kms-key-id` in `aws s3 sync`) +- x-amz-server-side-encryption-customer-algorithm (`--sse-c-copy-source` in `aws s3 sync`) +- x-amz-acl (`--acl` in `aws s3 sync`) + +You can find more information about system defined metadata keys in +[S3 PutObject documentation](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html) +and [`aws s3 sync` documentation](https://docs.aws.amazon.com/cli/latest/reference/s3/sync.html). ```ts const websiteBucket = new s3.Bucket(this, 'WebsiteBucket', { @@ -177,6 +182,7 @@ new s3deploy.BucketDeployment(this, 'DeployWebsite', { storageClass: StorageClass.INTELLIGENT_TIERING, serverSideEncryption: ServerSideEncryption.AES_256, cacheControl: [CacheControl.setPublic(), CacheControl.maxAge(cdk.Duration.hours(1))], + accessControl: s3.BucketAccessControl.BUCKET_OWNER_FULL_CONTROL, }); ``` @@ -230,7 +236,7 @@ size of the AWS Lambda resource handler. ## Development The custom resource is implemented in Python 3.6 in order to be able to leverage -the AWS CLI for "aws sync". The code is under [`lib/lambda`](https://github.com/aws/aws-cdk/tree/master/packages/%40aws-cdk/aws-s3-deployment/lib/lambda) and +the AWS CLI for "aws s3 sync". The code is under [`lib/lambda`](https://github.com/aws/aws-cdk/tree/master/packages/%40aws-cdk/aws-s3-deployment/lib/lambda) and unit tests are under [`test/lambda`](https://github.com/aws/aws-cdk/tree/master/packages/%40aws-cdk/aws-s3-deployment/test/lambda). This package requires Python 3.6 during build time in order to create the custom diff --git a/packages/@aws-cdk/aws-s3-deployment/lib/bucket-deployment.ts b/packages/@aws-cdk/aws-s3-deployment/lib/bucket-deployment.ts index ca91f036dc5ed..3a73b950792bf 100644 --- a/packages/@aws-cdk/aws-s3-deployment/lib/bucket-deployment.ts +++ b/packages/@aws-cdk/aws-s3-deployment/lib/bucket-deployment.ts @@ -6,6 +6,7 @@ import * as lambda from '@aws-cdk/aws-lambda'; import * as s3 from '@aws-cdk/aws-s3'; import * as cdk from '@aws-cdk/core'; import { AwsCliLayer } from '@aws-cdk/lambda-layer-awscli'; +import { kebab as toKebabCase } from 'case'; import { Construct } from 'constructs'; import { ISource, SourceConfig } from './source'; @@ -164,6 +165,12 @@ export interface BucketDeploymentProps { * @see https://docs.aws.amazon.com/AmazonS3/latest/dev/ServerSideEncryptionCustomerKeys.html#sse-c-how-to-programmatically-intro */ readonly serverSideEncryptionCustomerAlgorithm?: string; + /** + * System-defined x-amz-acl metadata to be set on all objects in the deployment. + * @default - Not set. + * @see https://docs.aws.amazon.com/AmazonS3/latest/userguide/acl-overview.html#canned-acl + */ + readonly accessControl?: s3.BucketAccessControl; /** * The VPC network to place the deployment lambda handler in. @@ -282,6 +289,7 @@ function mapSystemMetadata(metadata: BucketDeploymentProps) { if (metadata.websiteRedirectLocation) { res['website-redirect'] = metadata.websiteRedirectLocation; } if (metadata.serverSideEncryptionAwsKmsKeyId) { res['sse-kms-key-id'] = metadata.serverSideEncryptionAwsKmsKeyId; } if (metadata.serverSideEncryptionCustomerAlgorithm) { res['sse-c-copy-source'] = metadata.serverSideEncryptionCustomerAlgorithm; } + if (metadata.accessControl) { res.acl = toKebabCase(metadata.accessControl.toString()); } return Object.keys(res).length === 0 ? undefined : res; } diff --git a/packages/@aws-cdk/aws-s3-deployment/package.json b/packages/@aws-cdk/aws-s3-deployment/package.json index c5ae455fc2928..f7c6225d64233 100644 --- a/packages/@aws-cdk/aws-s3-deployment/package.json +++ b/packages/@aws-cdk/aws-s3-deployment/package.json @@ -96,6 +96,7 @@ "@aws-cdk/aws-s3-assets": "0.0.0", "@aws-cdk/lambda-layer-awscli": "0.0.0", "@aws-cdk/core": "0.0.0", + "case": "1.6.3", "constructs": "^3.3.69" }, "homepage": "https://github.com/aws/aws-cdk", @@ -110,6 +111,9 @@ "@aws-cdk/core": "0.0.0", "constructs": "^3.3.69" }, + "bundledDependencies": [ + "case" + ], "engines": { "node": ">= 10.13.0 <13 || >=13.7.0" }, diff --git a/packages/@aws-cdk/aws-s3-deployment/test/bucket-deployment.test.ts b/packages/@aws-cdk/aws-s3-deployment/test/bucket-deployment.test.ts index c111629e46769..2bbe5e34a41a6 100644 --- a/packages/@aws-cdk/aws-s3-deployment/test/bucket-deployment.test.ts +++ b/packages/@aws-cdk/aws-s3-deployment/test/bucket-deployment.test.ts @@ -325,6 +325,7 @@ test('system metadata is correctly transformed', () => { websiteRedirectLocation: 'example', cacheControl: [s3deploy.CacheControl.setPublic(), s3deploy.CacheControl.maxAge(cdk.Duration.hours(1))], expires: expiration, + accessControl: s3.BucketAccessControl.BUCKET_OWNER_FULL_CONTROL, }); // THEN @@ -340,10 +341,47 @@ test('system metadata is correctly transformed', () => { 'expires': expiration.date.toUTCString(), 'sse-c-copy-source': 'rot13', 'website-redirect': 'example', + 'acl': 'bucket-owner-full-control', }, }); }); +// type checking structure that forces to update it if BucketAccessControl changes +// see `--acl` here: https://docs.aws.amazon.com/cli/latest/reference/s3/sync.html +const accessControlMap: Record = { + [s3.BucketAccessControl.PRIVATE]: 'private', + [s3.BucketAccessControl.PUBLIC_READ]: 'public-read', + [s3.BucketAccessControl.PUBLIC_READ_WRITE]: 'public-read-write', + [s3.BucketAccessControl.AUTHENTICATED_READ]: 'authenticated-read', + [s3.BucketAccessControl.AWS_EXEC_READ]: 'aws-exec-read', + [s3.BucketAccessControl.BUCKET_OWNER_READ]: 'bucket-owner-read', + [s3.BucketAccessControl.BUCKET_OWNER_FULL_CONTROL]: 'bucket-owner-full-control', + [s3.BucketAccessControl.LOG_DELIVERY_WRITE]: 'log-delivery-write', +}; + +test.each(Object.entries(accessControlMap) as [s3.BucketAccessControl, string][])( + 'system metadata acl %s is correctly transformed', + (accessControl, systemMetadataKeyword) => { + // GIVEN + const stack = new cdk.Stack(); + const bucket = new s3.Bucket(stack, 'Dest'); + + // WHEN + new s3deploy.BucketDeployment(stack, 'Deploy', { + sources: [s3deploy.Source.asset(path.join(__dirname, 'my-website.zip'))], + destinationBucket: bucket, + accessControl: accessControl, + }); + + // THEN + expect(stack).toHaveResource('Custom::CDKBucketDeployment', { + SystemMetadata: { + acl: systemMetadataKeyword, + }, + }); + }, +); + test('expires type has correct values', () => { expect(cdk.Expiration.atDate(new Date('Sun, 26 Jan 2020 00:53:20 GMT')).date.toUTCString()).toEqual('Sun, 26 Jan 2020 00:53:20 GMT'); expect(cdk.Expiration.atTimestamp(1580000000000).date.toUTCString()).toEqual('Sun, 26 Jan 2020 00:53:20 GMT'); From 440ca35cf0f0e9f6f86bef445bd9aa6ef05ff9be Mon Sep 17 00:00:00 2001 From: Julian Michel Date: Mon, 2 Aug 2021 18:47:32 +0200 Subject: [PATCH 02/99] fix(chatbot): ARN validation in fromSlackChannelConfigurationArn fails for tokenized values (#15849) A SlackChannelConfiguration can be imported using `fromSlackChannelConfigurationArn`. In this method, the given ARN will be validated. However, the validation failed for tokenized values. The validation was enhanced. The ARN validation will be only executed if the ARN can be resolved. For unresolved tokens, the validation will be skipped. Closes #15842. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../lib/slack-channel-configuration.ts | 14 +++++++++++--- .../test/slack-channel-configuration.test.ts | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk/aws-chatbot/lib/slack-channel-configuration.ts b/packages/@aws-cdk/aws-chatbot/lib/slack-channel-configuration.ts index 69646e783ebd7..690bb95c9bffd 100644 --- a/packages/@aws-cdk/aws-chatbot/lib/slack-channel-configuration.ts +++ b/packages/@aws-cdk/aws-chatbot/lib/slack-channel-configuration.ts @@ -204,9 +204,9 @@ export class SlackChannelConfiguration extends SlackChannelConfigurationBase { */ public static fromSlackChannelConfigurationArn(scope: Construct, id: string, slackChannelConfigurationArn: string): ISlackChannelConfiguration { const re = /^slack-channel\//; - const resourceName = cdk.Stack.of(scope).parseArn(slackChannelConfigurationArn).resourceName as string; + const resourceName = cdk.Arn.extractResourceName(slackChannelConfigurationArn, 'chat-configuration'); - if (!re.test(resourceName)) { + if (!cdk.Token.isUnresolved(slackChannelConfigurationArn) && !re.test(resourceName)) { throw new Error('The ARN of a Slack integration must be in the form: arn:aws:chatbot:{region}:{account}:chat-configuration/slack-channel/{slackChannelName}'); } @@ -227,11 +227,19 @@ export class SlackChannelConfiguration extends SlackChannelConfigurationBase { * The ArnComponents API will return `slack-channel/my-slack` * It need to handle that to gets a correct name.`my-slack` */ - readonly slackChannelConfigurationName = resourceName.substring('slack-channel/'.length); + readonly slackChannelConfigurationName: string; constructor(s: Construct, i: string) { super(s, i); this.grantPrincipal = new iam.UnknownPrincipal({ resource: this }); + + // handle slackChannelConfigurationName as specified above + if (cdk.Token.isUnresolved(slackChannelConfigurationArn)) { + this.slackChannelConfigurationName = cdk.Fn.select(1, cdk.Fn.split('slack-channel/', resourceName)); + } else { + this.slackChannelConfigurationName = resourceName.substring('slack-channel/'.length); + } + } } diff --git a/packages/@aws-cdk/aws-chatbot/test/slack-channel-configuration.test.ts b/packages/@aws-cdk/aws-chatbot/test/slack-channel-configuration.test.ts index 21d530bfd839a..63bf61b46d21c 100644 --- a/packages/@aws-cdk/aws-chatbot/test/slack-channel-configuration.test.ts +++ b/packages/@aws-cdk/aws-chatbot/test/slack-channel-configuration.test.ts @@ -245,4 +245,22 @@ describe('SlackChannelConfiguration', () => { expect(imported.slackChannelConfigurationName).toEqual('my-slack'); expect(imported.slackChannelConfigurationArn).toEqual('arn:aws:chatbot::1234567890:chat-configuration/slack-channel/my-slack'); }); + + test('skip validation for tokenized values', () => { + // invalid ARN because of underscores, no error because tokenized value + expect(() => chatbot.SlackChannelConfiguration.fromSlackChannelConfigurationArn(stack, 'MySlackChannel', + cdk.Lazy.string({ produce: () => 'arn:aws:chatbot::1234567890:chat-configuration/slack_channel/my_slack' }))).not.toThrow(); + }); + + test('test name and ARN from slack channel configuration ARN', () => { + const imported = chatbot.SlackChannelConfiguration.fromSlackChannelConfigurationArn(stack, 'MySlackChannel', cdk.Token.asString({ Ref: 'ARN' })); + + // THEN + expect(stack.resolve(imported.slackChannelConfigurationName)).toStrictEqual({ + 'Fn::Select': [1, { 'Fn::Split': ['slack-channel/', { 'Fn::Select': [1, { 'Fn::Split': [':chat-configuration/', { Ref: 'ARN' }] }] }] }], + }); + expect(stack.resolve(imported.slackChannelConfigurationArn)).toStrictEqual({ + Ref: 'ARN', + }); + }); }); \ No newline at end of file From d77e9dc927e193a8f8fcecb92ae3af9498509086 Mon Sep 17 00:00:00 2001 From: Otavio Macedo Date: Tue, 3 Aug 2021 15:06:13 +0100 Subject: [PATCH 03/99] chore(lambda): lambda insights incorrectly accesses non-exported files (#15870) ---- *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/lib/lambda-insights.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts b/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts index 7a95dc18ea15c..2d2b88511786e 100644 --- a/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts +++ b/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts @@ -1,6 +1,5 @@ import { Aws, CfnMapping, Fn, IResolveContext, Lazy, Stack, Token } from '@aws-cdk/core'; import { FactName, RegionInfo } from '@aws-cdk/region-info'; -import { CLOUDWATCH_LAMBDA_INSIGHTS_ARNS } from '@aws-cdk/region-info/build-tools/fact-tables'; // This is the name of the mapping that will be added to the CloudFormation template, if a stack is region agnostic const DEFAULT_MAPPING_PREFIX = 'LambdaInsightsVersions'; @@ -49,8 +48,9 @@ export abstract class LambdaInsightsVersion { private static fromInsightsVersion(insightsVersion: string): LambdaInsightsVersion { // Check if insights version is valid. This should only happen if one of the public static readonly versions are set incorrectly - if (!(insightsVersion in CLOUDWATCH_LAMBDA_INSIGHTS_ARNS)) { - throw new Error(`Insights version ${insightsVersion} does not exist. Available versions are ${CLOUDWATCH_LAMBDA_INSIGHTS_ARNS.keys()}`); + const versionExists = RegionInfo.regions.some(regionInfo => regionInfo.cloudwatchLambdaInsightsArn(insightsVersion)); + if (!versionExists) { + throw new Error(`Insights version ${insightsVersion} does not exist.`); } class InsightsVersion extends LambdaInsightsVersion { From 45b484cdff115a0893f7eed2b0c1d6424c2751e4 Mon Sep 17 00:00:00 2001 From: Niranjan Jayakar Date: Tue, 3 Aug 2021 16:25:10 +0100 Subject: [PATCH 04/99] chore(assertions): migrate more modules to use assertions (#15857) Added a method `Template.toJSON()` to get the object representation of the CloudFormation template. This is most useful for snapshot testing. BREAKING CHANGE: `Template.fromTemplate()` is now renamed to `Template.fromJSON()` to provide clarity. ---- *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 | 11 ++ packages/@aws-cdk/assertions/lib/template.ts | 20 +- .../@aws-cdk/assertions/test/template.test.ts | 42 +++++ packages/@aws-cdk/aws-amplify/package.json | 4 +- .../@aws-cdk/aws-amplify/test/app.test.ts | 30 +-- .../@aws-cdk/aws-amplify/test/branch.test.ts | 10 +- .../@aws-cdk/aws-amplify/test/domain.test.ts | 12 +- .../aws-apigatewayv2-authorizers/package.json | 4 +- .../test/http/jwt.test.ts | 6 +- .../test/http/lambda.test.ts | 17 +- .../test/http/user-pool.test.ts | 6 +- .../package.json | 4 +- .../test/http/alb.test.ts | 10 +- .../test/http/http-proxy.test.ts | 10 +- .../test/http/lambda.test.ts | 6 +- .../test/http/nlb.test.ts | 10 +- .../test/http/private/integration.test.ts | 1 - .../test/http/service-discovery.test.ts | 8 +- .../test/websocket/lambda.test.ts | 4 +- .../@aws-cdk/aws-apigatewayv2/package.json | 4 +- .../test/common/api-mapping.test.ts | 6 +- .../aws-apigatewayv2/test/http/api.test.ts | 71 ++++---- .../test/http/authorizer.test.ts | 10 +- .../test/http/domain-name.test.ts | 13 +- .../aws-apigatewayv2/test/http/route.test.ts | 30 +-- .../aws-apigatewayv2/test/http/stage.test.ts | 4 +- .../test/http/vpc-link.test.ts | 12 +- .../test/websocket/api.test.ts | 18 +- .../test/websocket/route.test.ts | 6 +- .../test/websocket/stage.test.ts | 4 +- packages/@aws-cdk/aws-appsync/package.json | 6 +- .../aws-appsync/test/appsync-auth.test.ts | 40 ++-- .../test/appsync-code-first.test.ts | 26 +-- .../test/appsync-directives.test.ts | 6 +- .../aws-appsync/test/appsync-dynamodb.test.ts | 12 +- .../test/appsync-elasticsearch.test.ts | 16 +- .../test/appsync-enum-type.test.ts | 10 +- .../aws-appsync/test/appsync-grant.test.ts | 47 +++-- .../aws-appsync/test/appsync-http.test.ts | 16 +- .../test/appsync-input-types.test.ts | 10 +- .../test/appsync-interface-type.test.ts | 18 +- .../aws-appsync/test/appsync-lambda.test.ts | 14 +- .../test/appsync-mapping-template.test.ts | 6 +- .../aws-appsync/test/appsync-none.test.ts | 12 +- .../test/appsync-object-type.test.ts | 24 +-- .../aws-appsync/test/appsync-rds.test.ts | 18 +- .../test/appsync-scalar-type.test.ts | 30 +-- .../aws-appsync/test/appsync-schema.test.ts | 22 +-- .../test/appsync-union-types.test.ts | 10 +- .../@aws-cdk/aws-appsync/test/appsync.test.ts | 14 +- packages/@aws-cdk/aws-batch/package.json | 4 +- .../@aws-cdk/aws-batch/test/batch.test.ts | 6 - .../test/compute-environment.test.ts | 35 ++-- .../aws-batch/test/job-definition.test.ts | 19 +- .../@aws-cdk/aws-batch/test/job-queue.test.ts | 11 +- packages/@aws-cdk/aws-cloud9/package.json | 6 +- .../test/cloud9.environment.test.ts | 12 +- .../@aws-cdk/aws-cloud9/test/cloud9.test.ts | 6 - packages/@aws-cdk/aws-codestar/package.json | 4 +- .../aws-codestar/test/codestar.test.ts | 6 +- packages/@aws-cdk/aws-glue/package.json | 4 +- .../@aws-cdk/aws-glue/test/connection.test.ts | 27 ++- .../@aws-cdk/aws-glue/test/database.test.ts | 24 ++- .../@aws-cdk/aws-glue/test/schema.test.ts | 146 ++++++++------- .../test/security-configuration.test.ts | 19 +- packages/@aws-cdk/aws-glue/test/table.test.ts | 172 +++++++++--------- packages/@aws-cdk/aws-ivs/package.json | 4 +- packages/@aws-cdk/aws-ivs/test/ivs.test.ts | 23 ++- .../aws-kinesisanalytics-flink/package.json | 4 +- .../test/application.test.ts | 77 ++++---- .../package.json | 2 +- .../test/s3-bucket.test.ts | 116 ++++++------ packages/@aws-cdk/aws-lambda-go/package.json | 2 +- .../aws-lambda-go/test/function.test.ts | 12 +- .../@aws-cdk/aws-lambda-python/package.json | 4 +- .../aws-lambda-python/test/function.test.ts | 12 +- .../aws-lambda-python/test/layer.test.ts | 1 - packages/@aws-cdk/aws-msk/package.json | 4 +- .../@aws-cdk/aws-msk/test/cluster.test.ts | 42 ++--- packages/@aws-cdk/aws-redshift/package.json | 4 +- .../aws-redshift/test/cluster.test.ts | 67 ++++--- .../aws-redshift/test/parameter-group.test.ts | 6 +- .../aws-redshift/test/subnet-group.test.ts | 8 +- packages/@aws-cdk/aws-sam/package.json | 2 +- packages/@aws-cdk/aws-sam/test/api.test.ts | 6 +- .../@aws-cdk/aws-sam/test/application.test.ts | 4 +- .../@aws-cdk/aws-sam/test/function.test.ts | 4 +- .../@aws-cdk/aws-servicecatalog/package.json | 4 +- .../aws-servicecatalog/test/portfolio.test.ts | 68 +++---- .../aws-servicecatalog/test/product.test.ts | 16 +- .../package.json | 2 +- .../test/application.test.ts | 22 +-- .../test/attribute-group.test.ts | 14 +- .../test/servicecatalogappregistry.test.ts | 6 - 94 files changed, 911 insertions(+), 876 deletions(-) delete mode 100644 packages/@aws-cdk/aws-batch/test/batch.test.ts delete mode 100644 packages/@aws-cdk/aws-cloud9/test/cloud9.test.ts delete mode 100644 packages/@aws-cdk/aws-servicecatalogappregistry/test/servicecatalogappregistry.test.ts diff --git a/packages/@aws-cdk/assertions/README.md b/packages/@aws-cdk/assertions/README.md index 386accc3c8f71..bfeb893417c31 100644 --- a/packages/@aws-cdk/assertions/README.md +++ b/packages/@aws-cdk/assertions/README.md @@ -53,6 +53,17 @@ assert.templateMatches({ }); ``` +The `Template` class also supports [snapshot +testing](https://jestjs.io/docs/snapshot-testing) using jest. + +```ts +// using jest +expect(Template.fromStack(stack)).toMatchSnapshot(); +``` + +For non-javascript languages, the `toJSON()` can be called to get an in-memory object +of the template. + ## Counting Resources This module allows asserting the number of resources of a specific type found diff --git a/packages/@aws-cdk/assertions/lib/template.ts b/packages/@aws-cdk/assertions/lib/template.ts index 9631eddbe3680..480290bc45b04 100644 --- a/packages/@aws-cdk/assertions/lib/template.ts +++ b/packages/@aws-cdk/assertions/lib/template.ts @@ -20,28 +20,38 @@ export class Template { } /** - * Base your assertions from an existing CloudFormation template formatted as a - * nested set of records. + * Base your assertions from an existing CloudFormation template formatted as an in-memory + * JSON object. * @param template the CloudFormation template formatted as a nested set of records */ - public static fromTemplate(template: { [key: string] : any }): Template { + public static fromJSON(template: { [key: string] : any }): Template { return new Template(template); } /** - * Base your assertions from an existing CloudFormation template formatted as a string. + * Base your assertions from an existing CloudFormation template formatted as a + * JSON string. * @param template the CloudFormation template in */ public static fromString(template: string): Template { return new Template(JSON.parse(template)); } + private readonly template: { [key: string]: any }; private readonly inspector: assert.StackInspector; - private constructor(template: any) { + private constructor(template: { [key: string]: any }) { + this.template = template; this.inspector = new assert.StackInspector(template); } + /** + * The CloudFormation template deserialized into an object. + */ + public toJSON(): { [key: string]: any } { + return this.template; + } + /** * Assert that the given number of resources of the given type exist in the * template. diff --git a/packages/@aws-cdk/assertions/test/template.test.ts b/packages/@aws-cdk/assertions/test/template.test.ts index 00cd695cd7634..0fe308e68e5be 100644 --- a/packages/@aws-cdk/assertions/test/template.test.ts +++ b/packages/@aws-cdk/assertions/test/template.test.ts @@ -3,6 +3,48 @@ import { Construct } from 'constructs'; import { Match, Template } from '../lib'; describe('Template', () => { + describe('asObject', () => { + test('fromString', () => { + const template = Template.fromString(`{ + "Resources": { + "Foo": { + "Type": "Baz::Qux", + "Properties": { "Fred": "Waldo" } + } + } + }`); + + expect(template.toJSON()).toEqual({ + Resources: { + Foo: { + Type: 'Baz::Qux', + Properties: { Fred: 'Waldo' }, + }, + }, + }); + }); + + test('fromStack', () => { + const stack = new Stack(); + new CfnResource(stack, 'Foo', { + type: 'Foo::Bar', + properties: { + Baz: 'Qux', + }, + }); + const template = Template.fromStack(stack); + + expect(template.toJSON()).toEqual({ + Resources: { + Foo: { + Type: 'Foo::Bar', + Properties: { Baz: 'Qux' }, + }, + }, + }); + }); + }); + describe('fromString', () => { test('default', () => { const assertions = Template.fromString(`{ diff --git a/packages/@aws-cdk/aws-amplify/package.json b/packages/@aws-cdk/aws-amplify/package.json index 35a569393b9c0..dad425ea592f2 100644 --- a/packages/@aws-cdk/aws-amplify/package.json +++ b/packages/@aws-cdk/aws-amplify/package.json @@ -75,12 +75,12 @@ }, "license": "Apache-2.0", "devDependencies": { + "@aws-cdk/assertions": "0.0.0", "@types/jest": "^26.0.24", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", - "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "pkglint": "0.0.0" }, "dependencies": { "@aws-cdk/aws-iam": "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 f4e4468708a76..76b6830bec1c5 100644 --- a/packages/@aws-cdk/aws-amplify/test/app.test.ts +++ b/packages/@aws-cdk/aws-amplify/test/app.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as codebuild from '@aws-cdk/aws-codebuild'; import * as codecommit from '@aws-cdk/aws-codecommit'; import { SecretValue, Stack } from '@aws-cdk/core'; @@ -32,7 +32,7 @@ test('create an app connected to a GitHub repository', () => { }); // THEN - expect(stack).toHaveResource('AWS::Amplify::App', { + Template.fromStack(stack).hasResourceProperties('AWS::Amplify::App', { Name: 'App', BuildSpec: 'version: \"1.0\"\nfrontend:\n phases:\n build:\n commands:\n - npm run build\n', IAMServiceRole: { @@ -48,7 +48,7 @@ test('create an app connected to a GitHub repository', () => { }, }); - expect(stack).toHaveResource('AWS::IAM::Role', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Role', { AssumeRolePolicyDocument: { Statement: [ { @@ -87,7 +87,7 @@ test('create an app connected to a GitLab repository', () => { }); // THEN - expect(stack).toHaveResource('AWS::Amplify::App', { + Template.fromStack(stack).hasResourceProperties('AWS::Amplify::App', { Name: 'App', BuildSpec: '{\n \"version\": \"1.0\",\n \"frontend\": {\n \"phases\": {\n \"build\": {\n \"commands\": [\n \"npm run build\"\n ]\n }\n }\n }\n}', IAMServiceRole: { @@ -100,7 +100,7 @@ test('create an app connected to a GitLab repository', () => { Repository: 'https://gitlab.com/aws/aws-cdk', }); - expect(stack).toHaveResource('AWS::IAM::Role', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Role', { AssumeRolePolicyDocument: { Statement: [ { @@ -125,7 +125,7 @@ test('create an app connected to a CodeCommit repository', () => { }); // THEN - expect(stack).toHaveResource('AWS::Amplify::App', { + Template.fromStack(stack).hasResourceProperties('AWS::Amplify::App', { IAMServiceRole: { 'Fn::GetAtt': [ 'AppRole1AF9B530', @@ -150,7 +150,7 @@ test('create an app connected to a CodeCommit repository', () => { }, }); - expect(stack).toHaveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -200,7 +200,7 @@ test('with basic auth from credentials', () => { }); // THEN - expect(stack).toHaveResource('AWS::Amplify::App', { + Template.fromStack(stack).hasResourceProperties('AWS::Amplify::App', { BasicAuthConfig: { EnableBasicAuth: true, Password: 'password', @@ -221,7 +221,7 @@ test('with basic auth from generated password', () => { }); // THEN - expect(stack).toHaveResource('AWS::Amplify::App', { + Template.fromStack(stack).hasResourceProperties('AWS::Amplify::App', { BasicAuthConfig: { EnableBasicAuth: true, Password: { @@ -240,7 +240,7 @@ test('with basic auth from generated password', () => { }, }); - expect(stack).toHaveResource('AWS::SecretsManager::Secret', { + Template.fromStack(stack).hasResourceProperties('AWS::SecretsManager::Secret', { GenerateSecretString: { GenerateStringKey: 'password', SecretStringTemplate: '{\"username\":\"username\"}', @@ -263,7 +263,7 @@ test('with env vars', () => { app.addEnvironment('key2', 'value2'); // THEN - expect(stack).toHaveResource('AWS::Amplify::App', { + Template.fromStack(stack).hasResourceProperties('AWS::Amplify::App', { EnvironmentVariables: [ { Name: 'key1', @@ -300,7 +300,7 @@ test('with custom rules', () => { }); // THEN - expect(stack).toHaveResource('AWS::Amplify::App', { + Template.fromStack(stack).hasResourceProperties('AWS::Amplify::App', { CustomRules: [ { Source: '/source1', @@ -328,7 +328,7 @@ test('with SPA redirect', () => { }); // THEN - expect(stack).toHaveResource('AWS::Amplify::App', { + Template.fromStack(stack).hasResourceProperties('AWS::Amplify::App', { CustomRules: [ { Source: '', @@ -356,7 +356,7 @@ test('with auto branch creation', () => { app.addAutoBranchEnvironment('key2', 'value2'); // THEN - expect(stack).toHaveResource('AWS::Amplify::App', { + Template.fromStack(stack).hasResourceProperties('AWS::Amplify::App', { AutoBranchCreationConfig: { BasicAuthConfig: { EnableBasicAuth: false, @@ -390,7 +390,7 @@ test('with auto branch deletion', () => { }); // THEN - expect(stack).toHaveResource('AWS::Amplify::App', { + Template.fromStack(stack).hasResourceProperties('AWS::Amplify::App', { EnableBranchAutoDeletion: true, }); }); diff --git a/packages/@aws-cdk/aws-amplify/test/branch.test.ts b/packages/@aws-cdk/aws-amplify/test/branch.test.ts index 6844d9f952d10..1638157eb4b14 100644 --- a/packages/@aws-cdk/aws-amplify/test/branch.test.ts +++ b/packages/@aws-cdk/aws-amplify/test/branch.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import { SecretValue, Stack } from '@aws-cdk/core'; import * as amplify from '../lib'; @@ -20,7 +20,7 @@ test('create a branch', () => { app.addBranch('dev'); // THEN - expect(stack).toHaveResource('AWS::Amplify::Branch', { + Template.fromStack(stack).hasResourceProperties('AWS::Amplify::Branch', { AppId: { 'Fn::GetAtt': [ 'AppF1B96344', @@ -40,7 +40,7 @@ test('with basic auth from credentials', () => { }); // THEN - expect(stack).toHaveResource('AWS::Amplify::Branch', { + Template.fromStack(stack).hasResourceProperties('AWS::Amplify::Branch', { BasicAuthConfig: { EnableBasicAuth: true, Password: 'password', @@ -56,7 +56,7 @@ test('with basic auth from generated password', () => { }); // THEN - expect(stack).toHaveResource('AWS::Amplify::Branch', { + Template.fromStack(stack).hasResourceProperties('AWS::Amplify::Branch', { BasicAuthConfig: { EnableBasicAuth: true, Password: { @@ -86,7 +86,7 @@ test('with env vars', () => { branch.addEnvironment('key2', 'value2'); // THEN - expect(stack).toHaveResource('AWS::Amplify::Branch', { + Template.fromStack(stack).hasResourceProperties('AWS::Amplify::Branch', { EnvironmentVariables: [ { Name: 'key1', diff --git a/packages/@aws-cdk/aws-amplify/test/domain.test.ts b/packages/@aws-cdk/aws-amplify/test/domain.test.ts index 13311a93abaec..2188de34ef23d 100644 --- a/packages/@aws-cdk/aws-amplify/test/domain.test.ts +++ b/packages/@aws-cdk/aws-amplify/test/domain.test.ts @@ -1,5 +1,5 @@ +import { Template } from '@aws-cdk/assertions'; import * as iam from '@aws-cdk/aws-iam'; -import '@aws-cdk/assert-internal/jest'; import { App, SecretValue, Stack } from '@aws-cdk/core'; import * as amplify from '../lib'; @@ -28,7 +28,7 @@ test('create a domain', () => { domain.mapSubDomain(devBranch); // THEN - expect(stack).toHaveResource('AWS::Amplify::Domain', { + Template.fromStack(stack).hasResourceProperties('AWS::Amplify::Domain', { AppId: { 'Fn::GetAtt': [ 'AppF1B96344', @@ -81,7 +81,7 @@ test('map a branch to the domain root', () => { domain.mapRoot(prodBranch); // THEN - expect(stack).toHaveResource('AWS::Amplify::Domain', { + Template.fromStack(stack).hasResourceProperties('AWS::Amplify::Domain', { AppId: { 'Fn::GetAtt': [ 'AppF1B96344', @@ -141,7 +141,7 @@ test('auto subdomain all branches', () => { domain.mapRoot(prodBranch); // THEN - expect(stack).toHaveResource('AWS::Amplify::Domain', { + Template.fromStack(stack).hasResourceProperties('AWS::Amplify::Domain', { EnableAutoSubDomain: true, AutoSubDomainCreationPatterns: [ '*', @@ -176,7 +176,7 @@ test('auto subdomain some branches', () => { domain.mapRoot(prodBranch); // THEN - expect(stack).toHaveResource('AWS::Amplify::Domain', { + Template.fromStack(stack).hasResourceProperties('AWS::Amplify::Domain', { EnableAutoSubDomain: true, AutoSubDomainCreationPatterns: ['features/**'], AutoSubDomainIAMRole: { @@ -214,7 +214,7 @@ test('auto subdomain with IAM role', () => { domain.mapRoot(prodBranch); // THEN - expect(stack).toHaveResource('AWS::Amplify::Domain', { + Template.fromStack(stack).hasResourceProperties('AWS::Amplify::Domain', { EnableAutoSubDomain: true, AutoSubDomainCreationPatterns: ['features/**'], AutoSubDomainIAMRole: { diff --git a/packages/@aws-cdk/aws-apigatewayv2-authorizers/package.json b/packages/@aws-cdk/aws-apigatewayv2-authorizers/package.json index 748efa7077158..8466c95ddc9da 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-authorizers/package.json +++ b/packages/@aws-cdk/aws-apigatewayv2-authorizers/package.json @@ -73,14 +73,14 @@ }, "license": "Apache-2.0", "devDependencies": { + "@aws-cdk/assertions": "0.0.0", "@types/jest": "^26.0.24", "@types/aws-lambda": "^8.10.79", "@aws-cdk/aws-apigatewayv2-integrations": "0.0.0", "@aws-cdk/aws-lambda": "0.0.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", - "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "pkglint": "0.0.0" }, "dependencies": { "@aws-cdk/aws-apigatewayv2": "0.0.0", diff --git a/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/jwt.test.ts b/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/jwt.test.ts index 469a0d6aa4ece..f97e3d4c24d74 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/jwt.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/jwt.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import { HttpApi, HttpIntegrationType, HttpRouteIntegrationBindOptions, IHttpRouteIntegration, PayloadFormatVersion } from '@aws-cdk/aws-apigatewayv2'; import { Stack } from '@aws-cdk/core'; import { HttpJwtAuthorizer } from '../../lib'; @@ -22,7 +22,7 @@ describe('HttpJwtAuthorizer', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApiGatewayV2::Authorizer', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Authorizer', { AuthorizerType: 'JWT', IdentitySource: ['$request.header.Authorization'], JwtConfiguration: { @@ -55,7 +55,7 @@ describe('HttpJwtAuthorizer', () => { }); // THEN - expect(stack).toCountResources('AWS::ApiGatewayV2::Authorizer', 1); + Template.fromStack(stack).resourceCountIs('AWS::ApiGatewayV2::Authorizer', 1); }); }); diff --git a/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/lambda.test.ts b/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/lambda.test.ts index a9efd500e6bf1..1f62ad76867b0 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/lambda.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/lambda.test.ts @@ -1,5 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; -import { ABSENT } from '@aws-cdk/assert-internal'; +import { Match, Template } from '@aws-cdk/assertions'; import { HttpApi, HttpIntegrationType, HttpRouteIntegrationBindOptions, IHttpRouteIntegration, PayloadFormatVersion } from '@aws-cdk/aws-apigatewayv2'; import { Code, Function, Runtime } from '@aws-cdk/aws-lambda'; import { Duration, Stack } from '@aws-cdk/core'; @@ -31,7 +30,7 @@ describe('HttpLambdaAuthorizer', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApiGatewayV2::Authorizer', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Authorizer', { Name: 'default-authorizer', AuthorizerType: 'REQUEST', AuthorizerResultTtlInSeconds: 300, @@ -41,7 +40,7 @@ describe('HttpLambdaAuthorizer', () => { ], }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Route', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Route', { AuthorizationType: 'CUSTOM', }); }); @@ -71,7 +70,7 @@ describe('HttpLambdaAuthorizer', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApiGatewayV2::Authorizer', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Authorizer', { AuthorizerPayloadFormatVersion: '2.0', EnableSimpleResponses: true, }); @@ -102,9 +101,9 @@ describe('HttpLambdaAuthorizer', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApiGatewayV2::Authorizer', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Authorizer', { AuthorizerPayloadFormatVersion: '1.0', - EnableSimpleResponses: ABSENT, + EnableSimpleResponses: Match.absentProperty(), }); }); @@ -133,7 +132,7 @@ describe('HttpLambdaAuthorizer', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApiGatewayV2::Authorizer', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Authorizer', { AuthorizerPayloadFormatVersion: '2.0', EnableSimpleResponses: true, }); @@ -165,7 +164,7 @@ describe('HttpLambdaAuthorizer', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApiGatewayV2::Authorizer', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Authorizer', { AuthorizerResultTtlInSeconds: 600, }); }); diff --git a/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/user-pool.test.ts b/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/user-pool.test.ts index 33086eab5ff4a..0e3c339e7f744 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/user-pool.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/user-pool.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import { HttpApi, HttpIntegrationType, HttpRouteIntegrationBindOptions, IHttpRouteIntegration, PayloadFormatVersion } from '@aws-cdk/aws-apigatewayv2'; import { UserPool } from '@aws-cdk/aws-cognito'; import { Stack } from '@aws-cdk/core'; @@ -24,7 +24,7 @@ describe('HttpUserPoolAuthorizer', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApiGatewayV2::Authorizer', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Authorizer', { AuthorizerType: 'JWT', IdentitySource: ['$request.header.Authorization'], JwtConfiguration: { @@ -68,7 +68,7 @@ describe('HttpUserPoolAuthorizer', () => { }); // THEN - expect(stack).toCountResources('AWS::ApiGatewayV2::Authorizer', 1); + Template.fromStack(stack).resourceCountIs('AWS::ApiGatewayV2::Authorizer', 1); }); }); diff --git a/packages/@aws-cdk/aws-apigatewayv2-integrations/package.json b/packages/@aws-cdk/aws-apigatewayv2-integrations/package.json index 77e37b1fd5d0d..f857a94bc93f4 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-integrations/package.json +++ b/packages/@aws-cdk/aws-apigatewayv2-integrations/package.json @@ -71,11 +71,11 @@ }, "license": "Apache-2.0", "devDependencies": { + "@aws-cdk/assertions": "0.0.0", "@types/jest": "^26.0.24", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", - "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "pkglint": "0.0.0" }, "dependencies": { "@aws-cdk/aws-apigatewayv2": "0.0.0", diff --git a/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/alb.test.ts b/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/alb.test.ts index 95ece74cf7e93..e5871da260bc2 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/alb.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/alb.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import { HttpApi, HttpMethod, HttpRoute, HttpRouteKey, VpcLink } from '@aws-cdk/aws-apigatewayv2'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as elbv2 from '@aws-cdk/aws-elasticloadbalancingv2'; @@ -25,7 +25,7 @@ describe('HttpAlbIntegration', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApiGatewayV2::Integration', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Integration', { IntegrationType: 'HTTP_PROXY', ConnectionId: { Ref: 'HttpApiVpcLink159804837', @@ -60,7 +60,7 @@ describe('HttpAlbIntegration', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApiGatewayV2::Integration', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Integration', { IntegrationType: 'HTTP_PROXY', ConnectionId: { Ref: 'VpcLink42ED6FF0', @@ -94,7 +94,7 @@ describe('HttpAlbIntegration', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApiGatewayV2::Integration', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Integration', { IntegrationMethod: 'PATCH', }); }); @@ -137,7 +137,7 @@ describe('HttpAlbIntegration', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApiGatewayV2::Integration', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Integration', { TlsConfig: { ServerNameToVerify: 'name-to-verify', }, diff --git a/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/http-proxy.test.ts b/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/http-proxy.test.ts index 9c3b09ddcfbd6..0c76996fe7867 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/http-proxy.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/http-proxy.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import { HttpApi, HttpIntegration, HttpIntegrationType, HttpMethod, HttpRoute, HttpRouteKey, PayloadFormatVersion } from '@aws-cdk/aws-apigatewayv2'; import { Stack } from '@aws-cdk/core'; import { HttpProxyIntegration } from '../../lib'; @@ -15,7 +15,7 @@ describe('HttpProxyIntegration', () => { routeKey: HttpRouteKey.with('/pets'), }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Integration', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Integration', { IntegrationType: 'HTTP_PROXY', IntegrationUri: 'some-target-url', PayloadFormatVersion: '1.0', @@ -35,7 +35,7 @@ describe('HttpProxyIntegration', () => { routeKey: HttpRouteKey.with('/pets'), }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Integration', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Integration', { IntegrationMethod: 'PATCH', }); }); @@ -50,7 +50,7 @@ describe('HttpProxyIntegration', () => { integrationUri: 'some-target-url', }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Integration', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Integration', { IntegrationType: 'HTTP_PROXY', IntegrationUri: 'some-target-url', PayloadFormatVersion: '99.99', @@ -66,7 +66,7 @@ describe('HttpProxyIntegration', () => { integrationUri: 'some-target-url', }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Integration', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Integration', { IntegrationType: 'HTTP_PROXY', IntegrationUri: 'some-target-url', }); diff --git a/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/lambda.test.ts b/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/lambda.test.ts index 6414869f66f66..d0ead43945ec4 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/lambda.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/lambda.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import { HttpApi, HttpRoute, HttpRouteKey, PayloadFormatVersion } from '@aws-cdk/aws-apigatewayv2'; import { Code, Function, Runtime } from '@aws-cdk/aws-lambda'; import { App, Stack } from '@aws-cdk/core'; @@ -17,7 +17,7 @@ describe('LambdaProxyIntegration', () => { routeKey: HttpRouteKey.with('/pets'), }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Integration', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Integration', { IntegrationType: 'AWS_PROXY', IntegrationUri: stack.resolve(fooFn.functionArn), PayloadFormatVersion: '2.0', @@ -36,7 +36,7 @@ describe('LambdaProxyIntegration', () => { routeKey: HttpRouteKey.with('/pets'), }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Integration', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Integration', { PayloadFormatVersion: '1.0', }); }); diff --git a/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/nlb.test.ts b/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/nlb.test.ts index 2b7120ea33582..a32d448d8e448 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/nlb.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/nlb.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import { HttpApi, HttpMethod, HttpRoute, HttpRouteKey, VpcLink } from '@aws-cdk/aws-apigatewayv2'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as elbv2 from '@aws-cdk/aws-elasticloadbalancingv2'; @@ -25,7 +25,7 @@ describe('HttpNlbIntegration', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApiGatewayV2::Integration', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Integration', { IntegrationType: 'HTTP_PROXY', ConnectionId: { Ref: 'HttpApiVpcLink159804837', @@ -60,7 +60,7 @@ describe('HttpNlbIntegration', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApiGatewayV2::Integration', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Integration', { IntegrationType: 'HTTP_PROXY', ConnectionId: { Ref: 'VpcLink42ED6FF0', @@ -94,7 +94,7 @@ describe('HttpNlbIntegration', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApiGatewayV2::Integration', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Integration', { IntegrationMethod: 'PATCH', }); }); @@ -134,7 +134,7 @@ describe('HttpNlbIntegration', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApiGatewayV2::Integration', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Integration', { TlsConfig: { ServerNameToVerify: 'name-to-verify', }, diff --git a/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/private/integration.test.ts b/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/private/integration.test.ts index fb6c4ab082b53..8cda89e3d2390 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/private/integration.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/private/integration.test.ts @@ -1,4 +1,3 @@ -import '@aws-cdk/assert-internal/jest'; import { HttpApi, HttpRoute, HttpRouteIntegrationBindOptions, HttpRouteIntegrationConfig, HttpRouteKey } from '@aws-cdk/aws-apigatewayv2'; import { Stack } from '@aws-cdk/core'; import { HttpPrivateIntegration } from '../../../lib/http/private/integration'; diff --git a/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/service-discovery.test.ts b/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/service-discovery.test.ts index 83d2b47252598..4d3bef328a637 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/service-discovery.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/service-discovery.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import { HttpApi, HttpMethod, HttpRoute, HttpRouteKey, VpcLink } from '@aws-cdk/aws-apigatewayv2'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as servicediscovery from '@aws-cdk/aws-servicediscovery'; @@ -29,7 +29,7 @@ describe('HttpServiceDiscoveryIntegration', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApiGatewayV2::Integration', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Integration', { IntegrationType: 'HTTP_PROXY', ConnectionId: { Ref: 'VpcLink42ED6FF0', @@ -70,7 +70,7 @@ describe('HttpServiceDiscoveryIntegration', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApiGatewayV2::Integration', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Integration', { IntegrationMethod: 'PATCH', }); }); @@ -119,7 +119,7 @@ describe('HttpServiceDiscoveryIntegration', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApiGatewayV2::Integration', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Integration', { TlsConfig: { ServerNameToVerify: 'name-to-verify', }, diff --git a/packages/@aws-cdk/aws-apigatewayv2-integrations/test/websocket/lambda.test.ts b/packages/@aws-cdk/aws-apigatewayv2-integrations/test/websocket/lambda.test.ts index d5d7e4079db2d..e12b09f75ed50 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-integrations/test/websocket/lambda.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2-integrations/test/websocket/lambda.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import { WebSocketApi } from '@aws-cdk/aws-apigatewayv2'; import { Code, Function, Runtime } from '@aws-cdk/aws-lambda'; import { Stack } from '@aws-cdk/core'; @@ -19,7 +19,7 @@ describe('LambdaWebSocketIntegration', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApiGatewayV2::Integration', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Integration', { IntegrationType: 'AWS_PROXY', IntegrationUri: { 'Fn::Join': [ diff --git a/packages/@aws-cdk/aws-apigatewayv2/package.json b/packages/@aws-cdk/aws-apigatewayv2/package.json index 20d03097c4ae7..d0f2d3b6288c2 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/package.json +++ b/packages/@aws-cdk/aws-apigatewayv2/package.json @@ -78,12 +78,12 @@ }, "license": "Apache-2.0", "devDependencies": { + "@aws-cdk/assertions": "0.0.0", "@types/jest": "^26.0.24", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", - "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "pkglint": "0.0.0" }, "dependencies": { "@aws-cdk/aws-certificatemanager": "0.0.0", diff --git a/packages/@aws-cdk/aws-apigatewayv2/test/common/api-mapping.test.ts b/packages/@aws-cdk/aws-apigatewayv2/test/common/api-mapping.test.ts index 705f3ca6a4371..607afb5f8238f 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/test/common/api-mapping.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/test/common/api-mapping.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import { Certificate } from '@aws-cdk/aws-certificatemanager'; import { Stack } from '@aws-cdk/core'; import { DomainName, HttpApi, ApiMapping, WebSocketApi } from '../../lib'; @@ -22,7 +22,7 @@ describe('ApiMapping', () => { domainName: dn, }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::ApiMapping', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::ApiMapping', { ApiId: { Ref: 'ApiF70053CD', }, @@ -54,7 +54,7 @@ describe('ApiMapping', () => { apiMappingKey: 'beta', }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::ApiMapping', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::ApiMapping', { ApiId: { Ref: 'ApiF70053CD', }, diff --git a/packages/@aws-cdk/aws-apigatewayv2/test/http/api.test.ts b/packages/@aws-cdk/aws-apigatewayv2/test/http/api.test.ts index c2324412d3396..a4e880bac742d 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/test/http/api.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/test/http/api.test.ts @@ -1,5 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; -import { ABSENT } from '@aws-cdk/assert-internal'; +import { Match, Template } from '@aws-cdk/assertions'; import { Metric } from '@aws-cdk/aws-cloudwatch'; import * as ec2 from '@aws-cdk/aws-ec2'; import { Duration, Stack } from '@aws-cdk/core'; @@ -14,19 +13,19 @@ describe('HttpApi', () => { const stack = new Stack(); const api = new HttpApi(stack, 'api'); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Api', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Api', { Name: 'api', ProtocolType: 'HTTP', }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Stage', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Stage', { ApiId: stack.resolve(api.apiId), StageName: '$default', AutoDeploy: true, }); - expect(stack).not.toHaveResource('AWS::ApiGatewayV2::Route'); - expect(stack).not.toHaveResource('AWS::ApiGatewayV2::Integration'); + Template.fromStack(stack).resourceCountIs('AWS::ApiGatewayV2::Route', 0); + Template.fromStack(stack).resourceCountIs('AWS::ApiGatewayV2::Integration', 0); expect(api.url).toBeDefined(); }); @@ -45,7 +44,7 @@ describe('HttpApi', () => { createDefaultStage: false, }); - expect(stack).not.toHaveResource('AWS::ApiGatewayV2::Stage'); + Template.fromStack(stack).resourceCountIs('AWS::ApiGatewayV2::Stage', 0); expect(api.url).toBeUndefined(); }); @@ -55,12 +54,12 @@ describe('HttpApi', () => { defaultIntegration: new DummyRouteIntegration(), }); - expect(stack).toHaveResourceLike('AWS::ApiGatewayV2::Route', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Route', { ApiId: stack.resolve(httpApi.apiId), RouteKey: '$default', }); - expect(stack).toHaveResourceLike('AWS::ApiGatewayV2::Integration', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Integration', { ApiId: stack.resolve(httpApi.apiId), }); }); @@ -75,12 +74,12 @@ describe('HttpApi', () => { integration: new DummyRouteIntegration(), }); - expect(stack).toHaveResourceLike('AWS::ApiGatewayV2::Route', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Route', { ApiId: stack.resolve(httpApi.apiId), RouteKey: 'GET /pets', }); - expect(stack).toHaveResourceLike('AWS::ApiGatewayV2::Route', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Route', { ApiId: stack.resolve(httpApi.apiId), RouteKey: 'PATCH /pets', }); @@ -95,7 +94,7 @@ describe('HttpApi', () => { integration: new DummyRouteIntegration(), }); - expect(stack).toHaveResourceLike('AWS::ApiGatewayV2::Route', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Route', { ApiId: stack.resolve(httpApi.apiId), RouteKey: 'ANY /pets', }); @@ -113,7 +112,7 @@ describe('HttpApi', () => { }, }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Api', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Api', { CorsConfiguration: { AllowHeaders: ['Authorization'], AllowMethods: ['GET', 'HEAD', 'OPTIONS', 'POST', '*'], @@ -127,8 +126,8 @@ describe('HttpApi', () => { const stack = new Stack(); new HttpApi(stack, 'HttpApi'); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Api', { - CorsConfiguration: ABSENT, + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Api', { + CorsConfiguration: Match.absentProperty(), }); }); @@ -214,7 +213,7 @@ describe('HttpApi', () => { description: 'My Api', }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Api', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Api', { Name: 'api', ProtocolType: 'HTTP', Description: 'My Api', @@ -227,7 +226,7 @@ describe('HttpApi', () => { disableExecuteApiEndpoint: true, }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Api', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Api', { Name: 'api', ProtocolType: 'HTTP', DisableExecuteApiEndpoint: true, @@ -246,10 +245,10 @@ describe('HttpApi', () => { api.addVpcLink({ vpc: vpc2, vpcLinkName: 'Link-2' }); // THEN - expect(stack).toHaveResource('AWS::ApiGatewayV2::VpcLink', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::VpcLink', { Name: 'Link-1', }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::VpcLink', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::VpcLink', { Name: 'Link-2', }); }); @@ -265,12 +264,12 @@ describe('HttpApi', () => { api.addVpcLink({ vpc, vpcLinkName: 'Link-2' }); // THEN - expect(stack).toHaveResource('AWS::ApiGatewayV2::VpcLink', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::VpcLink', { Name: 'Link-1', }); - expect(stack).not.toHaveResource('AWS::ApiGatewayV2::VpcLink', { + expect(Template.fromStack(stack).findResources('AWS::ApiGatewayV2::VpcLink', { Name: 'Link-2', - }); + }).length).toEqual(0); }); test('apiEndpoint is exported', () => { @@ -292,12 +291,12 @@ describe('HttpApi', () => { authorizer, }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Api', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Api', { Name: 'api', ProtocolType: 'HTTP', }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Route', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Route', { AuthorizerId: 'auth-1234', AuthorizationType: 'JWT', }); @@ -327,7 +326,7 @@ describe('HttpApi', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApiGatewayV2::Route', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Route', { AuthorizerId: '12345', }); }); @@ -345,12 +344,12 @@ describe('HttpApi', () => { authorizationScopes: ['read:scopes'], }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Api', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Api', { Name: 'api', ProtocolType: 'HTTP', }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Route', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Route', { AuthorizerId: 'auth-1234', AuthorizationType: 'JWT', AuthorizationScopes: ['read:scopes'], @@ -393,7 +392,7 @@ describe('HttpApi', () => { integration: new DummyRouteIntegration(), }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Route', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Route', { AuthorizerId: 'auth-1234', AuthorizationType: 'JWT', AuthorizationScopes: ['read:pets'], @@ -411,7 +410,7 @@ describe('HttpApi', () => { defaultAuthorizationScopes: ['read:pets'], }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Route', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Route', { AuthorizerId: 'auth-1234', AuthorizationType: 'JWT', AuthorizationScopes: ['read:pets'], @@ -440,15 +439,15 @@ describe('HttpApi', () => { authorizer: new HttpNoneAuthorizer(), }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Route', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Route', { RouteKey: 'GET /pets', AuthorizerId: 'auth-1234', }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Route', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Route', { RouteKey: 'GET /chickens', AuthorizationType: 'NONE', - AuthorizerId: ABSENT, + AuthorizerId: Match.absentProperty(), }); }); @@ -469,8 +468,8 @@ describe('HttpApi', () => { authorizationScopes: [], }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Route', { - AuthorizationScopes: ABSENT, + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Route', { + AuthorizationScopes: Match.absentProperty(), }); }); @@ -497,12 +496,12 @@ describe('HttpApi', () => { authorizationScopes: ['read:chickens'], }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Route', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Route', { RouteKey: 'GET /pets', AuthorizationScopes: ['read:pets'], }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Route', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Route', { RouteKey: 'GET /chickens', AuthorizationScopes: ['read:chickens'], }); diff --git a/packages/@aws-cdk/aws-apigatewayv2/test/http/authorizer.test.ts b/packages/@aws-cdk/aws-apigatewayv2/test/http/authorizer.test.ts index 92c0ee0422c17..8cdca389cad00 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/test/http/authorizer.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/test/http/authorizer.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import { Stack } from '@aws-cdk/core'; import { HttpApi, HttpAuthorizer, HttpAuthorizerType, @@ -17,7 +17,7 @@ describe('HttpAuthorizer', () => { jwtIssuer: 'issuer', }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Authorizer', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Authorizer', { ApiId: stack.resolve(httpApi.apiId), Name: 'HttpAuthorizer', AuthorizerType: 'JWT', @@ -38,7 +38,7 @@ describe('HttpAuthorizer', () => { jwtIssuer: 'issuer', }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Authorizer', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Authorizer', { Name: 'my-authorizer', }); }); @@ -56,7 +56,7 @@ describe('HttpAuthorizer', () => { jwtIssuer: 'issuer', }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Authorizer', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Authorizer', { JwtConfiguration: { Audience: ['audience.1', 'audience.2'], Issuer: 'issuer', @@ -77,7 +77,7 @@ describe('HttpAuthorizer', () => { authorizerUri: 'arn:cool-lambda-arn', }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Authorizer', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Authorizer', { AuthorizerType: 'REQUEST', AuthorizerPayloadFormatVersion: '2.0', AuthorizerUri: 'arn:cool-lambda-arn', diff --git a/packages/@aws-cdk/aws-apigatewayv2/test/http/domain-name.test.ts b/packages/@aws-cdk/aws-apigatewayv2/test/http/domain-name.test.ts index c0074ac464d63..dc64fbf5bf7c9 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/test/http/domain-name.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/test/http/domain-name.test.ts @@ -1,5 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; -// import { expect, haveResource, haveResourceLike } from '@aws-cdk/assert-internal'; +import { Template } from '@aws-cdk/assertions'; import { Certificate } from '@aws-cdk/aws-certificatemanager'; import { Stack } from '@aws-cdk/core'; import { DomainName, HttpApi } from '../../lib'; @@ -19,7 +18,7 @@ describe('DomainName', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApiGatewayV2::DomainName', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::DomainName', { DomainName: 'example.com', DomainNameConfigurations: [ { @@ -74,7 +73,7 @@ describe('DomainName', () => { }, }); - expect(stack).toHaveResourceLike('AWS::ApiGatewayV2::DomainName', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::DomainName', { DomainName: 'example.com', DomainNameConfigurations: [ { @@ -83,7 +82,7 @@ describe('DomainName', () => { }, ], }); - expect(stack).toHaveResourceLike('AWS::ApiGatewayV2::ApiMapping', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::ApiMapping', { ApiId: { Ref: 'ApiF70053CD', }, @@ -110,7 +109,7 @@ describe('DomainName', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ApiGatewayV2::DomainName', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::DomainName', { DomainName: 'example.com', DomainNameConfigurations: [ { @@ -120,7 +119,7 @@ describe('DomainName', () => { ], }); - expect(stack).toHaveResourceLike('AWS::ApiGatewayV2::ApiMapping', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::ApiMapping', { ApiId: { Ref: 'ApiF70053CD', }, diff --git a/packages/@aws-cdk/aws-apigatewayv2/test/http/route.test.ts b/packages/@aws-cdk/aws-apigatewayv2/test/http/route.test.ts index 748ec8cb68d41..9f64cfdfbd123 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/test/http/route.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/test/http/route.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import { Stack, App } from '@aws-cdk/core'; import { HttpApi, HttpAuthorizer, HttpAuthorizerType, HttpConnectionType, HttpIntegrationType, HttpMethod, HttpRoute, HttpRouteAuthorizerBindOptions, @@ -16,7 +16,7 @@ describe('HttpRoute', () => { routeKey: HttpRouteKey.with('/books', HttpMethod.GET), }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Route', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Route', { ApiId: stack.resolve(httpApi.apiId), RouteKey: 'GET /books', Target: { @@ -33,7 +33,7 @@ describe('HttpRoute', () => { AuthorizationType: 'NONE', }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Integration', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Integration', { ApiId: stack.resolve(httpApi.apiId), }); }); @@ -48,7 +48,7 @@ describe('HttpRoute', () => { routeKey: HttpRouteKey.with('/books', HttpMethod.GET), }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Integration', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Integration', { ApiId: stack.resolve(httpApi.apiId), IntegrationType: 'HTTP_PROXY', PayloadFormatVersion: '2.0', @@ -75,7 +75,7 @@ describe('HttpRoute', () => { }); // THEN - expect(stack).toCountResources('AWS::ApiGatewayV2::Integration', 1); + Template.fromStack(stack).resourceCountIs('AWS::ApiGatewayV2::Integration', 1); }); test('integration can be used across HttpApis', () => { @@ -112,8 +112,8 @@ describe('HttpRoute', () => { }); // THEN - expect(stack1).toCountResources('AWS::ApiGatewayV2::Integration', 1); - expect(stack2).toCountResources('AWS::ApiGatewayV2::Integration', 1); + Template.fromStack(stack1).resourceCountIs('AWS::ApiGatewayV2::Integration', 1); + Template.fromStack(stack2).resourceCountIs('AWS::ApiGatewayV2::Integration', 1); }); test('route defined in a separate stack does not create cycles', () => { @@ -133,8 +133,8 @@ describe('HttpRoute', () => { }); // THEN - expect(stack1).toCountResources('AWS::ApiGatewayV2::Integration', 0); - expect(stack2).toCountResources('AWS::ApiGatewayV2::Integration', 1); + Template.fromStack(stack1).resourceCountIs('AWS::ApiGatewayV2::Integration', 0); + Template.fromStack(stack2).resourceCountIs('AWS::ApiGatewayV2::Integration', 1); }); test('throws when path not start with /', () => { @@ -186,7 +186,7 @@ describe('HttpRoute', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApiGatewayV2::Integration', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Integration', { IntegrationType: 'HTTP_PROXY', ConnectionId: 'some-connection-id', ConnectionType: 'VPC_LINK', @@ -198,7 +198,7 @@ describe('HttpRoute', () => { }, }); - expect(stack).not.toHaveResource('AWS::ApiGatewayV2::VpcLink'); + Template.fromStack(stack).resourceCountIs('AWS::ApiGatewayV2::VpcLink', 0); }); test('can create route with an authorizer attached', () => { @@ -214,16 +214,16 @@ describe('HttpRoute', () => { authorizer, }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Integration', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Integration', { ApiId: stack.resolve(httpApi.apiId), IntegrationType: 'HTTP_PROXY', PayloadFormatVersion: '2.0', IntegrationUri: 'some-uri', }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Authorizer'); + Template.fromStack(stack).resourceCountIs('AWS::ApiGatewayV2::Authorizer', 1); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Route', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Route', { AuthorizerId: stack.resolve(authorizer.bind({ scope: stack, route: route }).authorizerId), AuthorizationType: 'JWT', }); @@ -243,7 +243,7 @@ describe('HttpRoute', () => { authorizationScopes: ['read:books'], }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Route', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Route', { AuthorizationScopes: ['read:books'], }); }); diff --git a/packages/@aws-cdk/aws-apigatewayv2/test/http/stage.test.ts b/packages/@aws-cdk/aws-apigatewayv2/test/http/stage.test.ts index e3758183c68ff..c56c2ded5d48b 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/test/http/stage.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/test/http/stage.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import { Metric } from '@aws-cdk/aws-cloudwatch'; import { Stack } from '@aws-cdk/core'; import { HttpApi, HttpStage } from '../../lib'; @@ -15,7 +15,7 @@ describe('HttpStage', () => { httpApi: api, }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Stage', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Stage', { ApiId: stack.resolve(api.apiId), StageName: '$default', }); diff --git a/packages/@aws-cdk/aws-apigatewayv2/test/http/vpc-link.test.ts b/packages/@aws-cdk/aws-apigatewayv2/test/http/vpc-link.test.ts index 134c70b653ce6..99f7d480da63b 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/test/http/vpc-link.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/test/http/vpc-link.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as ec2 from '@aws-cdk/aws-ec2'; import { Stack } from '@aws-cdk/core'; import { VpcLink } from '../../lib'; @@ -16,7 +16,7 @@ describe('VpcLink', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApiGatewayV2::VpcLink', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::VpcLink', { Name: 'MyLink', SubnetIds: [ { @@ -56,7 +56,7 @@ describe('VpcLink', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApiGatewayV2::VpcLink', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::VpcLink', { Name: 'VpcLink', SubnetIds: [ { @@ -104,7 +104,7 @@ describe('VpcLink', () => { vpcLink.addSubnets(subnet); // THEN - expect(stack).toHaveResource('AWS::ApiGatewayV2::VpcLink', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::VpcLink', { Name: 'VpcLink', SubnetIds: [ { @@ -136,7 +136,7 @@ describe('VpcLink', () => { vpcLink.addSecurityGroups(sg1, sg2, sg3); // THEN - expect(stack).toHaveResource('AWS::ApiGatewayV2::VpcLink', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::VpcLink', { Name: 'VpcLink', SubnetIds: [ { @@ -183,6 +183,6 @@ describe('VpcLink', () => { }); // THEN - expect(stack).not.toHaveResource('AWS::ApiGatewayV2::VpcLink'); + Template.fromStack(stack).resourceCountIs('AWS::ApiGatewayV2::VpcLink', 0); }); }); diff --git a/packages/@aws-cdk/aws-apigatewayv2/test/websocket/api.test.ts b/packages/@aws-cdk/aws-apigatewayv2/test/websocket/api.test.ts index 8a387941cad6f..959555a5c2b7a 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/test/websocket/api.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/test/websocket/api.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import { Stack } from '@aws-cdk/core'; import { IWebSocketRouteIntegration, WebSocketApi, WebSocketIntegrationType, @@ -14,14 +14,14 @@ describe('WebSocketApi', () => { new WebSocketApi(stack, 'api'); // THEN - expect(stack).toHaveResource('AWS::ApiGatewayV2::Api', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Api', { Name: 'api', ProtocolType: 'WEBSOCKET', }); - expect(stack).not.toHaveResource('AWS::ApiGatewayV2::Stage'); - expect(stack).not.toHaveResource('AWS::ApiGatewayV2::Route'); - expect(stack).not.toHaveResource('AWS::ApiGatewayV2::Integration'); + Template.fromStack(stack).resourceCountIs('AWS::ApiGatewayV2::Stage', 0); + Template.fromStack(stack).resourceCountIs('AWS::ApiGatewayV2::Route', 0); + Template.fromStack(stack).resourceCountIs('AWS::ApiGatewayV2::Integration', 0); }); test('addRoute: adds a route with passed key', () => { @@ -33,7 +33,7 @@ describe('WebSocketApi', () => { api.addRoute('myroute', { integration: new DummyIntegration() }); // THEN - expect(stack).toHaveResource('AWS::ApiGatewayV2::Route', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Route', { ApiId: stack.resolve(api.apiId), RouteKey: 'myroute', }); @@ -47,7 +47,7 @@ describe('WebSocketApi', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApiGatewayV2::Route', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Route', { ApiId: stack.resolve(api.apiId), RouteKey: '$connect', }); @@ -61,7 +61,7 @@ describe('WebSocketApi', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApiGatewayV2::Route', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Route', { ApiId: stack.resolve(api.apiId), RouteKey: '$disconnect', }); @@ -75,7 +75,7 @@ describe('WebSocketApi', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApiGatewayV2::Route', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Route', { ApiId: stack.resolve(api.apiId), RouteKey: '$default', }); diff --git a/packages/@aws-cdk/aws-apigatewayv2/test/websocket/route.test.ts b/packages/@aws-cdk/aws-apigatewayv2/test/websocket/route.test.ts index ae73fd7e6cba0..07eadc5300a85 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/test/websocket/route.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/test/websocket/route.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import { Stack } from '@aws-cdk/core'; import { IWebSocketRouteIntegration, WebSocketApi, WebSocketIntegrationType, @@ -19,7 +19,7 @@ describe('WebSocketRoute', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApiGatewayV2::Route', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Route', { ApiId: stack.resolve(webSocketApi.apiId), RouteKey: 'message', Target: { @@ -35,7 +35,7 @@ describe('WebSocketRoute', () => { }, }); - expect(stack).toHaveResource('AWS::ApiGatewayV2::Integration', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Integration', { ApiId: stack.resolve(webSocketApi.apiId), IntegrationType: 'AWS_PROXY', IntegrationUri: 'some-uri', diff --git a/packages/@aws-cdk/aws-apigatewayv2/test/websocket/stage.test.ts b/packages/@aws-cdk/aws-apigatewayv2/test/websocket/stage.test.ts index bec3e34e5d4fb..d942eb6dc7a4e 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/test/websocket/stage.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/test/websocket/stage.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import { Stack } from '@aws-cdk/core'; import { WebSocketApi, WebSocketStage } from '../../lib'; @@ -15,7 +15,7 @@ describe('WebSocketStage', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApiGatewayV2::Stage', { + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Stage', { ApiId: stack.resolve(api.apiId), StageName: 'dev', }); diff --git a/packages/@aws-cdk/aws-appsync/package.json b/packages/@aws-cdk/aws-appsync/package.json index 13267c04844cc..bc2dc7796af93 100644 --- a/packages/@aws-cdk/aws-appsync/package.json +++ b/packages/@aws-cdk/aws-appsync/package.json @@ -73,14 +73,14 @@ }, "license": "Apache-2.0", "devDependencies": { + "@aws-cdk/assertions": "0.0.0", + "@aws-cdk/aws-stepfunctions": "0.0.0", "@types/jest": "^26.0.24", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", "jest": "^26.6.3", - "pkglint": "0.0.0", - "@aws-cdk/aws-stepfunctions": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "pkglint": "0.0.0" }, "dependencies": { "@aws-cdk/aws-cognito": "0.0.0", diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-auth.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-auth.test.ts index c0d7ce0ac8796..a137e54b0423f 100644 --- a/packages/@aws-cdk/aws-appsync/test/appsync-auth.test.ts +++ b/packages/@aws-cdk/aws-appsync/test/appsync-auth.test.ts @@ -1,5 +1,5 @@ -import '@aws-cdk/assert-internal/jest'; import * as path from 'path'; +import { Template } from '@aws-cdk/assertions'; import * as cognito from '@aws-cdk/aws-cognito'; import * as cdk from '@aws-cdk/core'; import * as appsync from '../lib'; @@ -19,7 +19,7 @@ describe('AppSync API Key Authorization', () => { }); // THEN - expect(stack).toHaveResource('AWS::AppSync::ApiKey'); + Template.fromStack(stack).resourceCountIs('AWS::AppSync::ApiKey', 1); }); test('AppSync creates api key from additionalAuthorizationModes', () => { @@ -36,7 +36,7 @@ describe('AppSync API Key Authorization', () => { }); // THEN - expect(stack).toHaveResource('AWS::AppSync::ApiKey'); + Template.fromStack(stack).resourceCountIs('AWS::AppSync::ApiKey', 1); }); test('AppSync does not create unspecified api key from additionalAuthorizationModes', () => { @@ -50,7 +50,7 @@ describe('AppSync API Key Authorization', () => { }); // THEN - expect(stack).not.toHaveResource('AWS::AppSync::ApiKey'); + Template.fromStack(stack).resourceCountIs('AWS::AppSync::ApiKey', 0); }); test('appsync does not create unspecified api key with empty additionalAuthorizationModes', () => { @@ -65,7 +65,7 @@ describe('AppSync API Key Authorization', () => { }); // THEN - expect(stack).not.toHaveResource('AWS::AppSync::ApiKey'); + Template.fromStack(stack).resourceCountIs('AWS::AppSync::ApiKey', 0); }); test('appsync creates configured api key with additionalAuthorizationModes', () => { @@ -83,7 +83,7 @@ describe('AppSync API Key Authorization', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::ApiKey', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::ApiKey', { Description: 'Custom Description', }); }); @@ -105,7 +105,7 @@ describe('AppSync API Key Authorization', () => { }, }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::ApiKey', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::ApiKey', { ApiId: { 'Fn::GetAtt': ['API62EA1CFF', 'ApiId'] }, Expires: expirationDate, }); @@ -174,7 +174,7 @@ describe('AppSync API Key Authorization', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::ApiKey', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::ApiKey', { Description: 'Custom Description', }); }); @@ -240,7 +240,7 @@ describe('AppSync IAM Authorization', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLApi', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLApi', { AuthenticationType: 'AWS_IAM', }); }); @@ -256,7 +256,7 @@ describe('AppSync IAM Authorization', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLApi', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLApi', { AdditionalAuthenticationProviders: [{ AuthenticationType: 'AWS_IAM' }], }); }); @@ -311,7 +311,7 @@ describe('AppSync User Pool Authorization', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLApi', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLApi', { AuthenticationType: 'AMAZON_COGNITO_USER_POOLS', UserPoolConfig: { AwsRegion: { Ref: 'AWS::Region' }, @@ -339,7 +339,7 @@ describe('AppSync User Pool Authorization', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLApi', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLApi', { AuthenticationType: 'AMAZON_COGNITO_USER_POOLS', UserPoolConfig: { AwsRegion: { Ref: 'AWS::Region' }, @@ -364,7 +364,7 @@ describe('AppSync User Pool Authorization', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLApi', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLApi', { AdditionalAuthenticationProviders: [{ AuthenticationType: 'AMAZON_COGNITO_USER_POOLS', UserPoolConfig: { @@ -393,7 +393,7 @@ describe('AppSync User Pool Authorization', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLApi', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLApi', { AdditionalAuthenticationProviders: [{ AuthenticationType: 'AMAZON_COGNITO_USER_POOLS', UserPoolConfig: { @@ -433,7 +433,7 @@ describe('AppSync User Pool Authorization', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLApi', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLApi', { AuthenticationType: 'AMAZON_COGNITO_USER_POOLS', UserPoolConfig: { AwsRegion: { Ref: 'AWS::Region' }, @@ -476,7 +476,7 @@ describe('AppSync OIDC Authorization', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLApi', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLApi', { AuthenticationType: 'OPENID_CONNECT', OpenIDConnectConfig: { Issuer: 'test', @@ -503,7 +503,7 @@ describe('AppSync OIDC Authorization', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLApi', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLApi', { AuthenticationType: 'OPENID_CONNECT', OpenIDConnectConfig: { AuthTTL: 1, @@ -528,7 +528,7 @@ describe('AppSync OIDC Authorization', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLApi', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLApi', { AdditionalAuthenticationProviders: [{ AuthenticationType: 'OPENID_CONNECT', OpenIDConnectConfig: { @@ -557,7 +557,7 @@ describe('AppSync OIDC Authorization', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLApi', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLApi', { AdditionalAuthenticationProviders: [{ AuthenticationType: 'OPENID_CONNECT', OpenIDConnectConfig: { @@ -604,7 +604,7 @@ describe('AppSync OIDC Authorization', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLApi', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLApi', { AuthenticationType: 'OPENID_CONNECT', OpenIDConnectConfig: { Issuer: 'test' }, AdditionalAuthenticationProviders: [ diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-code-first.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-code-first.test.ts index 5abe04434496a..d904186f4f07b 100644 --- a/packages/@aws-cdk/aws-appsync/test/appsync-code-first.test.ts +++ b/packages/@aws-cdk/aws-appsync/test/appsync-code-first.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as cdk from '@aws-cdk/core'; import * as appsync from '../lib'; import * as t from './scalar-type-defintions'; @@ -34,7 +34,7 @@ describe('code-first implementation through GraphQL Api functions`', () => { const out = 'interface Test {\n id: ID\n lid: [ID]\n rid: ID!\n rlid: [ID]!\n rlrid: [ID!]!\n dupid: [ID!]!\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -55,7 +55,7 @@ describe('code-first implementation through GraphQL Api functions`', () => { const out = 'type Test {\n id: ID\n lid: [ID]\n rid: ID!\n rlid: [ID]!\n rlrid: [ID!]!\n dupid: [ID!]!\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -75,7 +75,7 @@ describe('code-first implementation through GraphQL Api functions`', () => { const out = 'type Test {\n id: ID\n lid: [ID]\n rid: ID!\n rlid: [ID]!\n rlrid: [ID!]!\n dupid: [ID!]!\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -96,7 +96,7 @@ describe('code-first implementation through GraphQL Api functions`', () => { const out = 'type Test {\n id: ID\n lid: [ID]\n rid: ID!\n rlid: [ID]!\n rlrid: [ID!]!\n dupid: [ID!]!\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -116,7 +116,7 @@ describe('code-first implementation through GraphQL Api functions`', () => { const out = 'interface Test {\n id: ID\n lid: [ID]\n rid: ID!\n rlid: [ID]!\n rlrid: [ID!]!\n dupid: [ID!]!\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -137,7 +137,7 @@ describe('code-first implementation through GraphQL Api functions`', () => { const out = 'interface Test {\n id: ID\n lid: [ID]\n rid: ID!\n rlid: [ID]!\n rlrid: [ID!]!\n dupid: [ID!]!\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -171,7 +171,7 @@ describe('code-first implementation through Schema functions`', () => { const out = 'interface Test {\n id: ID\n lid: [ID]\n rid: ID!\n rlid: [ID]!\n rlrid: [ID!]!\n dupid: [ID!]!\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -197,7 +197,7 @@ describe('code-first implementation through Schema functions`', () => { const out = 'type Test {\n id: ID\n lid: [ID]\n rid: ID!\n rlid: [ID]!\n rlrid: [ID!]!\n dupid: [ID!]!\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -223,7 +223,7 @@ describe('code-first implementation through Schema functions`', () => { const out = 'type Test {\n id: ID\n lid: [ID]\n rid: ID!\n rlid: [ID]!\n rlrid: [ID!]!\n dupid: [ID!]!\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -248,7 +248,7 @@ describe('code-first implementation through Schema functions`', () => { const out = 'type Test {\n id: ID\n lid: [ID]\n rid: ID!\n rlid: [ID]!\n rlrid: [ID!]!\n dupid: [ID!]!\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -272,7 +272,7 @@ describe('code-first implementation through Schema functions`', () => { const out = 'interface Test {\n id: ID\n lid: [ID]\n rid: ID!\n rlid: [ID]!\n rlrid: [ID!]!\n dupid: [ID!]!\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -297,7 +297,7 @@ describe('code-first implementation through Schema functions`', () => { const out = 'interface Test {\n id: ID\n lid: [ID]\n rid: ID!\n rlid: [ID]!\n rlrid: [ID!]!\n dupid: [ID!]!\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-directives.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-directives.test.ts index 1d4d211ac8289..de2ce5d864813 100644 --- a/packages/@aws-cdk/aws-appsync/test/appsync-directives.test.ts +++ b/packages/@aws-cdk/aws-appsync/test/appsync-directives.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as cognito from '@aws-cdk/aws-cognito'; import * as cdk from '@aws-cdk/core'; import * as appsync from '../lib'; @@ -85,7 +85,7 @@ const testObjectType = (IApi: appsync.GraphqlApi, directives: appsync.Directive[ directives: directives, })); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `type Test ${tag} {\n field: String\n ${tag}\n rfield: String\n ${tag}\n}\n`, }); }; @@ -100,7 +100,7 @@ const testInterfaceType = (IApi: appsync.GraphqlApi, directives: appsync.Directi directives: directives, })); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `interface Test ${tag} {\n field: String\n ${tag}\n rfield: String\n ${tag}\n}\n`, }); }; diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-dynamodb.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-dynamodb.test.ts index ffc36ddabd276..657eecd9f9064 100644 --- a/packages/@aws-cdk/aws-appsync/test/appsync-dynamodb.test.ts +++ b/packages/@aws-cdk/aws-appsync/test/appsync-dynamodb.test.ts @@ -1,5 +1,5 @@ -import '@aws-cdk/assert-internal/jest'; import * as path from 'path'; +import { Template } from '@aws-cdk/assertions'; import * as db from '@aws-cdk/aws-dynamodb'; import * as cdk from '@aws-cdk/core'; import * as appsync from '../lib'; @@ -36,7 +36,7 @@ describe('DynamoDb Data Source configuration', () => { api.addDynamoDbDataSource('ds', table); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::DataSource', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::DataSource', { Type: 'AMAZON_DYNAMODB', Name: 'ds', }); @@ -49,7 +49,7 @@ describe('DynamoDb Data Source configuration', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::DataSource', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::DataSource', { Type: 'AMAZON_DYNAMODB', Name: 'custom', }); @@ -63,7 +63,7 @@ describe('DynamoDb Data Source configuration', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::DataSource', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::DataSource', { Type: 'AMAZON_DYNAMODB', Name: 'custom', Description: 'custom description', @@ -166,7 +166,7 @@ describe('adding DynamoDb data source from imported api', () => { importedApi.addDynamoDbDataSource('ds', table); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::DataSource', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::DataSource', { Type: 'AMAZON_DYNAMODB', ApiId: { 'Fn::GetAtt': ['baseApiCDA4D43A', 'ApiId'] }, }); @@ -181,7 +181,7 @@ describe('adding DynamoDb data source from imported api', () => { importedApi.addDynamoDbDataSource('ds', table); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::DataSource', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::DataSource', { Type: 'AMAZON_DYNAMODB', ApiId: { 'Fn::GetAtt': ['baseApiCDA4D43A', 'ApiId'] }, }); diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-elasticsearch.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-elasticsearch.test.ts index 1a974f982b61f..89199d65ca629 100644 --- a/packages/@aws-cdk/aws-appsync/test/appsync-elasticsearch.test.ts +++ b/packages/@aws-cdk/aws-appsync/test/appsync-elasticsearch.test.ts @@ -1,5 +1,5 @@ -import '@aws-cdk/assert-internal/jest'; import * as path from 'path'; +import { Template } from '@aws-cdk/assertions'; import * as es from '@aws-cdk/aws-elasticsearch'; import * as cdk from '@aws-cdk/core'; import * as appsync from '../lib'; @@ -25,7 +25,7 @@ describe('Elasticsearch Data Source Configuration', () => { api.addElasticsearchDataSource('ds', domain); // THEN - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Version: '2012-10-17', Statement: [{ @@ -56,7 +56,7 @@ describe('Elasticsearch Data Source Configuration', () => { api.addElasticsearchDataSource('ds', domain); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::DataSource', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::DataSource', { ElasticsearchConfig: { Endpoint: { 'Fn::Join': ['', ['https://', { @@ -72,7 +72,7 @@ describe('Elasticsearch Data Source Configuration', () => { api.addElasticsearchDataSource('ds', domain); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::DataSource', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::DataSource', { Type: 'AMAZON_ELASTICSEARCH', Name: 'ds', }); @@ -85,7 +85,7 @@ describe('Elasticsearch Data Source Configuration', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::DataSource', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::DataSource', { Type: 'AMAZON_ELASTICSEARCH', Name: 'custom', }); @@ -99,7 +99,7 @@ describe('Elasticsearch Data Source Configuration', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::DataSource', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::DataSource', { Type: 'AMAZON_ELASTICSEARCH', Name: 'custom', Description: 'custom description', @@ -127,7 +127,7 @@ describe('adding elasticsearch data source from imported api', () => { importedApi.addElasticsearchDataSource('ds', domain); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::DataSource', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::DataSource', { Type: 'AMAZON_ELASTICSEARCH', ApiId: { 'Fn::GetAtt': ['baseApiCDA4D43A', 'ApiId'] }, }); @@ -142,7 +142,7 @@ describe('adding elasticsearch data source from imported api', () => { importedApi.addElasticsearchDataSource('ds', domain); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::DataSource', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::DataSource', { Type: 'AMAZON_ELASTICSEARCH', ApiId: { 'Fn::GetAtt': ['baseApiCDA4D43A', 'ApiId'] }, }); diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-enum-type.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-enum-type.test.ts index 82551e354d1a0..a04e9a5c89d82 100644 --- a/packages/@aws-cdk/aws-appsync/test/appsync-enum-type.test.ts +++ b/packages/@aws-cdk/aws-appsync/test/appsync-enum-type.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as cdk from '@aws-cdk/core'; import * as appsync from '../lib'; import * as t from './scalar-type-defintions'; @@ -23,10 +23,10 @@ describe('testing Enum Type properties', () => { api.addType(test); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); - expect(stack).not.toHaveResource('AWS::AppSync::Resolver'); + Template.fromStack(stack).resourceCountIs('AWS::AppSync::Resolver', 0); }); test('EnumType can addField', () => { @@ -38,7 +38,7 @@ describe('testing Enum Type properties', () => { test.addField({ fieldName: 'test3' }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -57,7 +57,7 @@ describe('testing Enum Type properties', () => { const obj = 'type Test2 {\n enum: Test\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}${obj}`, }); }); diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-grant.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-grant.test.ts index 904c19b7dafd6..fb23df6e8ec74 100644 --- a/packages/@aws-cdk/aws-appsync/test/appsync-grant.test.ts +++ b/packages/@aws-cdk/aws-appsync/test/appsync-grant.test.ts @@ -1,5 +1,5 @@ import { join } from 'path'; -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as iam from '@aws-cdk/aws-iam'; import * as cdk from '@aws-cdk/core'; import * as appsync from '../lib'; @@ -38,11 +38,12 @@ describe('grant Permissions', () => { api.grant(role, appsync.IamResource.custom('types/Mutation/fields/addTest'), 'appsync:GraphQL'); // THEN - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { Action: 'appsync:GraphQL', + Effect: 'Allow', Resource: { 'Fn::Join': ['', [ 'arn:', @@ -67,11 +68,12 @@ describe('grant Permissions', () => { api.grant(role, appsync.IamResource.ofType('Mutation'), 'appsync:GraphQL'); // THEN - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { Action: 'appsync:GraphQL', + Effect: 'Allow', Resource: { 'Fn::Join': ['', [ 'arn:', @@ -96,11 +98,12 @@ describe('grant Permissions', () => { api.grant(role, appsync.IamResource.ofType('Mutation', 'addTest'), 'appsync:GraphQL'); // THEN - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { Action: 'appsync:GraphQL', + Effect: 'Allow', Resource: { 'Fn::Join': ['', [ 'arn:', @@ -125,11 +128,12 @@ describe('grant Permissions', () => { api.grant(role, appsync.IamResource.all(), 'appsync:GraphQL'); // THEN - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { Action: 'appsync:GraphQL', + Effect: 'Allow', Resource: { 'Fn::Join': ['', [ 'arn:', @@ -154,11 +158,12 @@ describe('grant Permissions', () => { api.grant(role, appsync.IamResource.custom('I', 'am', 'custom'), 'appsync:GraphQL'); // THEN - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { Action: 'appsync:GraphQL', + Effect: 'Allow', Resource: [ { 'Fn::Join': ['', [ @@ -211,11 +216,12 @@ describe('grant Permissions', () => { api.grant(role, appsync.IamResource.ofType('I', 'am', 'custom'), 'appsync:GraphQL'); // THEN - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { Action: 'appsync:GraphQL', + Effect: 'Allow', Resource: [ { 'Fn::Join': ['', [ @@ -258,11 +264,12 @@ describe('grantMutation Permissions', () => { api.grantMutation(role); // THEN - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { Action: 'appsync:GraphQL', + Effect: 'Allow', Resource: { 'Fn::Join': ['', [ 'arn:', @@ -287,11 +294,12 @@ describe('grantMutation Permissions', () => { api.grantMutation(role, 'addTest'); // THEN - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { Action: 'appsync:GraphQL', + Effect: 'Allow', Resource: { 'Fn::Join': ['', [ 'arn:', @@ -316,11 +324,12 @@ describe('grantMutation Permissions', () => { api.grantMutation(role, 'addTest', 'removeTest'); // THEN - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { Action: 'appsync:GraphQL', + Effect: 'Allow', Resource: [ { 'Fn::Join': ['', [ @@ -363,11 +372,12 @@ describe('grantQuery Permissions', () => { api.grantQuery(role); // THEN - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { Action: 'appsync:GraphQL', + Effect: 'Allow', Resource: { 'Fn::Join': ['', [ 'arn:', @@ -392,11 +402,12 @@ describe('grantQuery Permissions', () => { api.grantQuery(role, 'getTest'); // THEN - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { Action: 'appsync:GraphQL', + Effect: 'Allow', Resource: { 'Fn::Join': ['', [ 'arn:', @@ -421,11 +432,12 @@ describe('grantQuery Permissions', () => { api.grantQuery(role, 'getTests', 'getTest'); // THEN - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { Action: 'appsync:GraphQL', + Effect: 'Allow', Resource: [ { 'Fn::Join': ['', [ @@ -468,11 +480,12 @@ describe('grantSubscription Permissions', () => { api.grantSubscription(role); // THEN - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { Action: 'appsync:GraphQL', + Effect: 'Allow', Resource: { 'Fn::Join': ['', [ 'arn:', @@ -496,11 +509,12 @@ describe('grantSubscription Permissions', () => { api.grantSubscription(role, 'subscribe'); // THEN - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { Action: 'appsync:GraphQL', + Effect: 'Allow', Resource: { 'Fn::Join': ['', [ 'arn:', @@ -525,11 +539,12 @@ describe('grantSubscription Permissions', () => { api.grantSubscription(role, 'subscribe', 'custom'); // THEN - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { Action: 'appsync:GraphQL', + Effect: 'Allow', Resource: [ { 'Fn::Join': ['', [ diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-http.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-http.test.ts index 8023412c78a55..2f380b028c592 100644 --- a/packages/@aws-cdk/aws-appsync/test/appsync-http.test.ts +++ b/packages/@aws-cdk/aws-appsync/test/appsync-http.test.ts @@ -1,5 +1,5 @@ -import '@aws-cdk/assert-internal/jest'; import * as path from 'path'; +import { Template } from '@aws-cdk/assertions'; import * as sfn from '@aws-cdk/aws-stepfunctions'; import * as cdk from '@aws-cdk/core'; import * as appsync from '../lib'; @@ -24,7 +24,7 @@ describe('Http Data Source configuration', () => { api.addHttpDataSource('ds', endpoint); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::DataSource', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::DataSource', { Type: 'HTTP', Name: 'ds', }); @@ -37,7 +37,7 @@ describe('Http Data Source configuration', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::DataSource', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::DataSource', { Type: 'HTTP', Name: 'custom', }); @@ -51,7 +51,7 @@ describe('Http Data Source configuration', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::DataSource', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::DataSource', { Type: 'HTTP', Name: 'custom', Description: 'custom description', @@ -70,7 +70,7 @@ describe('Http Data Source configuration', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::DataSource', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::DataSource', { Type: 'HTTP', Name: 'custom', Description: 'custom description', @@ -103,7 +103,7 @@ describe('Http Data Source configuration', () => { // THEN - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -176,7 +176,7 @@ describe('adding http data source from imported api', () => { importedApi.addHttpDataSource('ds', endpoint); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::DataSource', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::DataSource', { Type: 'HTTP', ApiId: { 'Fn::GetAtt': ['baseApiCDA4D43A', 'ApiId'] }, }); @@ -191,7 +191,7 @@ describe('adding http data source from imported api', () => { importedApi.addHttpDataSource('ds', endpoint); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::DataSource', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::DataSource', { Type: 'HTTP', ApiId: { 'Fn::GetAtt': ['baseApiCDA4D43A', 'ApiId'] }, }); diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-input-types.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-input-types.test.ts index bfc391aeaf0f3..f58196e43cd31 100644 --- a/packages/@aws-cdk/aws-appsync/test/appsync-input-types.test.ts +++ b/packages/@aws-cdk/aws-appsync/test/appsync-input-types.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as cdk from '@aws-cdk/core'; import * as appsync from '../lib'; import * as t from './scalar-type-defintions'; @@ -23,10 +23,10 @@ describe('testing Input Type properties', () => { api.addType(test); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); - expect(stack).not.toHaveResource('AWS::AppSync::Resolver'); + Template.fromStack(stack).resourceCountIs('AWS::AppSync::Resolver', 0); }); test('InputType can addField', () => { @@ -36,7 +36,7 @@ describe('testing Input Type properties', () => { test.addField({ fieldName: 'test', field: t.string }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -88,7 +88,7 @@ describe('testing Input Type properties', () => { const obj = 'type Test2 {\n input: Test\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}${obj}`, }); }); diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-interface-type.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-interface-type.test.ts index 4061a2e69a0f9..f94400fab6ea3 100644 --- a/packages/@aws-cdk/aws-appsync/test/appsync-interface-type.test.ts +++ b/packages/@aws-cdk/aws-appsync/test/appsync-interface-type.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as cdk from '@aws-cdk/core'; import * as appsync from '../lib'; import * as t from './scalar-type-defintions'; @@ -28,7 +28,7 @@ describe('testing InterfaceType properties', () => { const out = 'interface baseTest {\n id: ID\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -46,7 +46,7 @@ describe('testing InterfaceType properties', () => { const out = 'interface baseTest {\n id: ID\n test(success: Int): String\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -65,10 +65,10 @@ describe('testing InterfaceType properties', () => { const out = 'interface baseTest {\n id: ID\n test(success: Int): String\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); - expect(stack).not.toHaveResource('AWS::AppSync::Resolver'); + Template.fromStack(stack).resourceCountIs('AWS::AppSync::Resolver', 0); }); test('Interface Type can be a Graphql Type', () => { @@ -84,7 +84,7 @@ describe('testing InterfaceType properties', () => { const out = 'type Test {\n test: baseTest\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -108,7 +108,7 @@ describe('testing InterfaceType properties', () => { const out = 'interface Test {\n test: String\n resolve: String\n @aws_api_key\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -133,10 +133,10 @@ describe('testing InterfaceType properties', () => { const out = 'interface Test {\n test: String\n resolve: String\n @aws_api_key\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); - expect(stack).not.toHaveResource('AWS::AppSync::Resolver'); + Template.fromStack(stack).resourceCountIs('AWS::AppSync::Resolver', 0); }); test('appsync fails addField with InterfaceType missing fieldName', () => { diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-lambda.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-lambda.test.ts index 55c2ec0f132eb..b714b0f28cef9 100644 --- a/packages/@aws-cdk/aws-appsync/test/appsync-lambda.test.ts +++ b/packages/@aws-cdk/aws-appsync/test/appsync-lambda.test.ts @@ -1,5 +1,5 @@ -import '@aws-cdk/assert-internal/jest'; import * as path from 'path'; +import { Template } from '@aws-cdk/assertions'; import * as lambda from '@aws-cdk/aws-lambda'; import * as cdk from '@aws-cdk/core'; import * as appsync from '../lib'; @@ -31,7 +31,7 @@ describe('Lambda Data Source configuration', () => { api.addLambdaDataSource('ds', func); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::DataSource', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::DataSource', { Type: 'AWS_LAMBDA', Name: 'ds', }); @@ -44,7 +44,7 @@ describe('Lambda Data Source configuration', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::DataSource', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::DataSource', { Type: 'AWS_LAMBDA', Name: 'custom', }); @@ -58,7 +58,7 @@ describe('Lambda Data Source configuration', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::DataSource', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::DataSource', { Type: 'AWS_LAMBDA', Name: 'custom', Description: 'custom description', @@ -86,7 +86,7 @@ describe('Lambda Data Source configuration', () => { }); // THEN - expect(stack).toHaveResource('AWS::AppSync::Resolver'); + Template.fromStack(stack).resourceCountIs('AWS::AppSync::Resolver', 1); }); }); @@ -108,7 +108,7 @@ describe('adding lambda data source from imported api', () => { importedApi.addLambdaDataSource('ds', func); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::DataSource', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::DataSource', { Type: 'AWS_LAMBDA', ApiId: { 'Fn::GetAtt': ['baseApiCDA4D43A', 'ApiId'] }, }); @@ -123,7 +123,7 @@ describe('adding lambda data source from imported api', () => { importedApi.addLambdaDataSource('ds', func); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::DataSource', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::DataSource', { Type: 'AWS_LAMBDA', ApiId: { 'Fn::GetAtt': ['baseApiCDA4D43A', 'ApiId'] }, }); diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-mapping-template.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-mapping-template.test.ts index d19b07d196b21..2259cbb4c48df 100644 --- a/packages/@aws-cdk/aws-appsync/test/appsync-mapping-template.test.ts +++ b/packages/@aws-cdk/aws-appsync/test/appsync-mapping-template.test.ts @@ -1,5 +1,5 @@ -import '@aws-cdk/assert-internal/jest'; import * as path from 'path'; +import { Template } from '@aws-cdk/assertions'; import * as lambda from '@aws-cdk/aws-lambda'; import * as cdk from '@aws-cdk/core'; import * as appsync from '../lib'; @@ -42,7 +42,7 @@ describe('Lambda Mapping Templates', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::Resolver', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::Resolver', { FieldName: 'allPosts', RequestMappingTemplate: invokeMT, }); @@ -60,7 +60,7 @@ describe('Lambda Mapping Templates', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::Resolver', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::Resolver', { FieldName: 'relatedPosts', RequestMappingTemplate: batchMT, }); diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-none.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-none.test.ts index 6dc1e0ad9273f..5dec58aa5b726 100644 --- a/packages/@aws-cdk/aws-appsync/test/appsync-none.test.ts +++ b/packages/@aws-cdk/aws-appsync/test/appsync-none.test.ts @@ -1,5 +1,5 @@ -import '@aws-cdk/assert-internal/jest'; import * as path from 'path'; +import { Template } from '@aws-cdk/assertions'; import * as cdk from '@aws-cdk/core'; import * as appsync from '../lib'; @@ -21,7 +21,7 @@ describe('None Data Source configuration', () => { api.addNoneDataSource('ds'); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::DataSource', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::DataSource', { Type: 'NONE', Name: 'ds', }); @@ -34,7 +34,7 @@ describe('None Data Source configuration', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::DataSource', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::DataSource', { Type: 'NONE', Name: 'custom', }); @@ -48,7 +48,7 @@ describe('None Data Source configuration', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::DataSource', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::DataSource', { Type: 'NONE', Name: 'custom', Description: 'custom description', @@ -81,7 +81,7 @@ describe('adding none data source from imported api', () => { importedApi.addNoneDataSource('none'); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::DataSource', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::DataSource', { Type: 'NONE', ApiId: { 'Fn::GetAtt': ['baseApiCDA4D43A', 'ApiId'] }, }); @@ -96,7 +96,7 @@ describe('adding none data source from imported api', () => { importedApi.addNoneDataSource('none'); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::DataSource', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::DataSource', { Type: 'NONE', ApiId: { 'Fn::GetAtt': ['baseApiCDA4D43A', 'ApiId'] }, }); diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-object-type.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-object-type.test.ts index 03e2bb411bbe9..4180ec9d30dad 100644 --- a/packages/@aws-cdk/aws-appsync/test/appsync-object-type.test.ts +++ b/packages/@aws-cdk/aws-appsync/test/appsync-object-type.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as cdk from '@aws-cdk/core'; import * as appsync from '../lib'; import * as t from './scalar-type-defintions'; @@ -36,7 +36,7 @@ describe('testing Object Type properties', () => { const out = `${gql_interface}${gql_object}`; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -65,7 +65,7 @@ describe('testing Object Type properties', () => { const out = `${gql_interface}${gql_object}`; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -87,7 +87,7 @@ describe('testing Object Type properties', () => { const out = 'type Test {\n test: baseTest\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -112,7 +112,7 @@ describe('testing Object Type properties', () => { const out = 'type Test {\n test: String\n resolve(arg: Int): String\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -137,7 +137,7 @@ describe('testing Object Type properties', () => { const out = 'type Test {\n test: String\n resolve(arg: Int): String\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -171,7 +171,7 @@ describe('testing Object Type properties', () => { api.addType(test); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::Resolver', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::Resolver', { Kind: 'PIPELINE', PipelineConfig: { Functions: [ @@ -202,10 +202,10 @@ describe('testing Object Type properties', () => { const out = 'type Test {\n test: String\n resolve(arg: Int): String\n dynamic: String\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); - expect(stack).toHaveResource('AWS::AppSync::Resolver'); + Template.fromStack(stack).resourceCountIs('AWS::AppSync::Resolver', 1); }); test('Object Type can generate Fields with Directives', () => { @@ -227,7 +227,7 @@ describe('testing Object Type properties', () => { const out = 'type Test {\n test: String\n resolve: String\n @aws_api_key\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -254,10 +254,10 @@ describe('testing Object Type properties', () => { const out = 'type Test {\n test: String\n resolve(arg: String): String\n @aws_api_key\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); - expect(stack).toHaveResource('AWS::AppSync::Resolver'); + Template.fromStack(stack).resourceCountIs('AWS::AppSync::Resolver', 1); }); test('appsync fails addField with ObjectType missing fieldName', () => { diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-rds.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-rds.test.ts index 9a328b0fe65a0..cc7329344b84e 100644 --- a/packages/@aws-cdk/aws-appsync/test/appsync-rds.test.ts +++ b/packages/@aws-cdk/aws-appsync/test/appsync-rds.test.ts @@ -1,5 +1,5 @@ -import '@aws-cdk/assert-internal/jest'; import * as path from 'path'; +import { Template } from '@aws-cdk/assertions'; import { Vpc, SecurityGroup, SubnetType } from '@aws-cdk/aws-ec2'; import { DatabaseSecret, DatabaseClusterEngine, AuroraMysqlEngineVersion, ServerlessCluster } from '@aws-cdk/aws-rds'; import * as cdk from '@aws-cdk/core'; @@ -47,7 +47,7 @@ describe('Rds Data Source configuration', () => { api.addRdsDataSource('ds', cluster, secret); // THEN - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Version: '2012-10-17', Statement: [{ @@ -117,7 +117,7 @@ describe('Rds Data Source configuration', () => { api.addRdsDataSource('ds', cluster, secret); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::DataSource', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::DataSource', { Type: 'RELATIONAL_DATABASE', RelationalDatabaseConfig: { RdsHttpEndpointConfig: { @@ -144,7 +144,7 @@ describe('Rds Data Source configuration', () => { api.addRdsDataSource('ds', cluster, secret, testDatabaseName); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::DataSource', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::DataSource', { Type: 'RELATIONAL_DATABASE', RelationalDatabaseConfig: { RdsHttpEndpointConfig: { @@ -171,7 +171,7 @@ describe('Rds Data Source configuration', () => { api.addRdsDataSource('ds', cluster, secret); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::DataSource', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::DataSource', { Type: 'RELATIONAL_DATABASE', Name: 'ds', }); @@ -184,7 +184,7 @@ describe('Rds Data Source configuration', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::DataSource', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::DataSource', { Type: 'RELATIONAL_DATABASE', Name: 'custom', }); @@ -198,7 +198,7 @@ describe('Rds Data Source configuration', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::DataSource', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::DataSource', { Type: 'RELATIONAL_DATABASE', Name: 'custom', Description: 'custom description', @@ -249,7 +249,7 @@ describe('adding rds data source from imported api', () => { importedApi.addRdsDataSource('ds', cluster, secret); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::DataSource', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::DataSource', { Type: 'RELATIONAL_DATABASE', ApiId: { 'Fn::GetAtt': ['baseApiCDA4D43A', 'ApiId'] }, }); @@ -264,7 +264,7 @@ describe('adding rds data source from imported api', () => { importedApi.addRdsDataSource('ds', cluster, secret); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::DataSource', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::DataSource', { Type: 'RELATIONAL_DATABASE', ApiId: { 'Fn::GetAtt': ['baseApiCDA4D43A', 'ApiId'] }, }); diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-scalar-type.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-scalar-type.test.ts index 150b45e747006..01cf50bd8904b 100644 --- a/packages/@aws-cdk/aws-appsync/test/appsync-scalar-type.test.ts +++ b/packages/@aws-cdk/aws-appsync/test/appsync-scalar-type.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as cdk from '@aws-cdk/core'; import * as appsync from '../lib'; import * as t from './scalar-type-defintions'; @@ -24,7 +24,7 @@ describe('testing all GraphQL Types', () => { const out = 'type Test {\n id: ID\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -39,7 +39,7 @@ describe('testing all GraphQL Types', () => { const out = 'type Test {\n id: String\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -54,7 +54,7 @@ describe('testing all GraphQL Types', () => { const out = 'type Test {\n id: Int\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -69,7 +69,7 @@ describe('testing all GraphQL Types', () => { const out = 'type Test {\n id: Float\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -84,7 +84,7 @@ describe('testing all GraphQL Types', () => { const out = 'type Test {\n id: Boolean\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -99,7 +99,7 @@ describe('testing all GraphQL Types', () => { const out = 'type Test {\n id: AWSDate\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -114,7 +114,7 @@ describe('testing all GraphQL Types', () => { const out = 'type Test {\n id: AWSTime\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -129,7 +129,7 @@ describe('testing all GraphQL Types', () => { const out = 'type Test {\n id: AWSDateTime\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -144,7 +144,7 @@ describe('testing all GraphQL Types', () => { const out = 'type Test {\n id: AWSTimestamp\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -159,7 +159,7 @@ describe('testing all GraphQL Types', () => { const out = 'type Test {\n id: AWSEmail\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -174,7 +174,7 @@ describe('testing all GraphQL Types', () => { const out = 'type Test {\n id: AWSJSON\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -190,7 +190,7 @@ describe('testing all GraphQL Types', () => { const out = 'type Test {\n id: AWSURL\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -205,7 +205,7 @@ describe('testing all GraphQL Types', () => { const out = 'type Test {\n id: AWSPhone\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -220,7 +220,7 @@ describe('testing all GraphQL Types', () => { const out = 'type Test {\n id: AWSIPAddress\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-schema.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-schema.test.ts index 37db685807139..9e3c5d951d807 100644 --- a/packages/@aws-cdk/aws-appsync/test/appsync-schema.test.ts +++ b/packages/@aws-cdk/aws-appsync/test/appsync-schema.test.ts @@ -1,5 +1,5 @@ import { join } from 'path'; -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as cdk from '@aws-cdk/core'; import * as appsync from '../lib'; import * as t from './scalar-type-defintions'; @@ -41,7 +41,7 @@ describe('basic testing schema definition mode `code`', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: '', }); }); @@ -56,7 +56,7 @@ describe('basic testing schema definition mode `code`', () => { api.addType(mutation); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${type.toString()}\n${query.toString()}\n${mutation.toString()}\n`, }); }); @@ -71,7 +71,7 @@ describe('basic testing schema definition mode `code`', () => { })); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: 'schema {\n query: Query\n}\ntype Query {\n test: String\n}\n', }); }); @@ -88,7 +88,7 @@ describe('basic testing schema definition mode `code`', () => { })); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: 'schema {\n query: Query\n}\ntype Query {\n test: String\n}\n', }); }); @@ -103,7 +103,7 @@ describe('basic testing schema definition mode `code`', () => { })); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: 'schema {\n mutation: Mutation\n}\ntype Mutation {\n test: String\n}\n', }); }); @@ -120,7 +120,7 @@ describe('basic testing schema definition mode `code`', () => { })); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: 'schema {\n mutation: Mutation\n}\ntype Mutation {\n test: String\n}\n', }); }); @@ -135,7 +135,7 @@ describe('basic testing schema definition mode `code`', () => { })); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: 'schema {\n subscription: Subscription\n}\ntype Subscription {\n test: String\n}\n', }); }); @@ -152,7 +152,7 @@ describe('basic testing schema definition mode `code`', () => { })); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: 'schema {\n subscription: Subscription\n}\ntype Subscription {\n test: String\n}\n', }); }); @@ -170,7 +170,7 @@ describe('basic testing schema definition mode `code`', () => { const out = 'schema {\n subscription: Subscription\n}\ntype Subscription {\n test: String\n @aws_subscribe(mutations: ["test1"])\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: out, }); }); @@ -186,7 +186,7 @@ describe('testing schema definition mode `file`', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${type.toString()}\n${query.toString()}\n${mutation.toString()}\n`, }); }); diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-union-types.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-union-types.test.ts index a2f0e6f47a41a..b84099b93e68f 100644 --- a/packages/@aws-cdk/aws-appsync/test/appsync-union-types.test.ts +++ b/packages/@aws-cdk/aws-appsync/test/appsync-union-types.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as cdk from '@aws-cdk/core'; import * as appsync from '../lib'; import * as t from './scalar-type-defintions'; @@ -30,10 +30,10 @@ describe('testing Union Type properties', () => { }); api.addType(union); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); - expect(stack).not.toHaveResource('AWS::AppSync::Resolver'); + Template.fromStack(stack).resourceCountIs('AWS::AppSync::Resolver', 0); }); test('UnionType can addField', () => { @@ -45,7 +45,7 @@ describe('testing Union Type properties', () => { union.addField({ field: test2.attribute() }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}`, }); }); @@ -90,7 +90,7 @@ describe('testing Union Type properties', () => { const obj = 'type Test2 {\n union: UnionTest\n}\n'; // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLSchema', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { Definition: `${out}${obj}`, }); }); diff --git a/packages/@aws-cdk/aws-appsync/test/appsync.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync.test.ts index 773b1142b0917..9c75c0c7a28c9 100644 --- a/packages/@aws-cdk/aws-appsync/test/appsync.test.ts +++ b/packages/@aws-cdk/aws-appsync/test/appsync.test.ts @@ -1,5 +1,5 @@ import * as path from 'path'; -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as iam from '@aws-cdk/aws-iam'; import * as cdk from '@aws-cdk/core'; import * as appsync from '../lib'; @@ -32,7 +32,7 @@ test('appsync should configure pipeline when pipelineConfig has contents', () => }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::Resolver', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::Resolver', { Kind: 'PIPELINE', PipelineConfig: { Functions: [ @@ -74,7 +74,7 @@ test('appsync should configure resolver as unit when pipelineConfig is empty', ( }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::Resolver', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::Resolver', { Kind: 'UNIT', }); }); @@ -88,7 +88,7 @@ test('appsync should configure resolver as unit when pipelineConfig is empty arr }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::Resolver', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::Resolver', { Kind: 'UNIT', }); }); @@ -103,7 +103,7 @@ test('when xray is enabled should not throw an Error', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLApi', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLApi', { XrayEnabled: true, }); }); @@ -128,7 +128,7 @@ test('appsync GraphqlApi should be configured with custom CloudWatch Logs role w }); // THEN - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLApi', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLApi', { Name: 'apiWithCustomRole', LogConfig: { CloudWatchLogsRoleArn: { @@ -143,7 +143,7 @@ test('appsync GraphqlApi should be configured with custom CloudWatch Logs role w test('appsync GraphqlApi should not use custom role for CW Logs when not specified', () => { // EXPECT - expect(stack).toHaveResourceLike('AWS::AppSync::GraphQLApi', { + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLApi', { Name: 'api', LogConfig: { CloudWatchLogsRoleArn: { diff --git a/packages/@aws-cdk/aws-batch/package.json b/packages/@aws-cdk/aws-batch/package.json index 158edc9ff76ff..bc9cbf389cd8c 100644 --- a/packages/@aws-cdk/aws-batch/package.json +++ b/packages/@aws-cdk/aws-batch/package.json @@ -73,13 +73,13 @@ }, "license": "Apache-2.0", "devDependencies": { + "@aws-cdk/assertions": "0.0.0", "@types/jest": "^26.0.24", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", "jest": "^26.6.3", - "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "pkglint": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-batch/test/batch.test.ts b/packages/@aws-cdk/aws-batch/test/batch.test.ts deleted file mode 100644 index c4505ad966984..0000000000000 --- a/packages/@aws-cdk/aws-batch/test/batch.test.ts +++ /dev/null @@ -1,6 +0,0 @@ -import '@aws-cdk/assert-internal/jest'; -import {} from '../lib'; - -test('No tests are specified for this package', () => { - expect(true).toBe(true); -}); diff --git a/packages/@aws-cdk/aws-batch/test/compute-environment.test.ts b/packages/@aws-cdk/aws-batch/test/compute-environment.test.ts index dd18be3f1496c..c7ead4cd47de8 100644 --- a/packages/@aws-cdk/aws-batch/test/compute-environment.test.ts +++ b/packages/@aws-cdk/aws-batch/test/compute-environment.test.ts @@ -1,6 +1,5 @@ import { throws } from 'assert'; -import { expect, haveResource, haveResourceLike, ResourcePart } from '@aws-cdk/assert-internal'; -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as ecs from '@aws-cdk/aws-ecs'; import * as iam from '@aws-cdk/aws-iam'; @@ -96,7 +95,7 @@ describe('Batch Compute Evironment', () => { }); // THEN - expect(stack).to(haveResourceLike('AWS::Batch::ComputeEnvironment', { + Template.fromStack(stack).hasResourceProperties('AWS::Batch::ComputeEnvironment', { Type: 'MANAGED', ...expectedManagedDefaultComputeProps({ Type: batch.ComputeResourceType.SPOT, @@ -117,7 +116,7 @@ describe('Batch Compute Evironment', () => { ], }, }), - }, ResourcePart.Properties)); + }); }); describe('with a bid percentage', () => { @@ -200,7 +199,7 @@ describe('Batch Compute Evironment', () => { new batch.ComputeEnvironment(stack, 'test-compute-env', props); // THEN - expect(stack).to(haveResourceLike('AWS::Batch::ComputeEnvironment', { + Template.fromStack(stack).hasResourceProperties('AWS::Batch::ComputeEnvironment', { ComputeEnvironmentName: 'my-test-compute-env', Type: 'MANAGED', State: 'DISABLED', @@ -251,7 +250,7 @@ describe('Batch Compute Evironment', () => { }, Type: 'EC2', }, - }, ResourcePart.Properties)); + }); }); describe('with no allocation strategy specified', () => { @@ -265,7 +264,7 @@ describe('Batch Compute Evironment', () => { }); // THEN - expect(stack).to(haveResourceLike('AWS::Batch::ComputeEnvironment', { + Template.fromStack(stack).hasResourceProperties('AWS::Batch::ComputeEnvironment', { Type: 'MANAGED', ServiceRole: { 'Fn::GetAtt': [ @@ -273,7 +272,7 @@ describe('Batch Compute Evironment', () => { 'Arn', ], }, - }, ResourcePart.Properties)); + }); }); }); @@ -317,12 +316,12 @@ describe('Batch Compute Evironment', () => { }); // THEN - expect(stack).to(haveResourceLike('AWS::Batch::ComputeEnvironment', { + Template.fromStack(stack).hasResourceProperties('AWS::Batch::ComputeEnvironment', { ...defaultServiceRole, ...expectedManagedDefaultComputeProps({ MinvCpus: 0, }), - }, ResourcePart.Properties)); + }); }); }); @@ -337,11 +336,11 @@ describe('Batch Compute Evironment', () => { }); // THEN - expect(stack).to(haveResourceLike('AWS::Batch::ComputeEnvironment', { + Template.fromStack(stack).hasResourceProperties('AWS::Batch::ComputeEnvironment', { ...expectedManagedDefaultComputeProps({ MaxvCpus: 256, }), - }, ResourcePart.Properties)); + }); }); }); @@ -356,8 +355,8 @@ describe('Batch Compute Evironment', () => { }); // THEN - expect(stack).to(haveResource('AWS::Batch::ComputeEnvironment')); - expect(stack).to(haveResource('AWS::IAM::Role')); + Template.fromStack(stack).resourceCountIs('AWS::Batch::ComputeEnvironment', 1); + Template.fromStack(stack).resourceCountIs('AWS::IAM::Role', 2); }); }); @@ -372,11 +371,11 @@ describe('Batch Compute Evironment', () => { }); // THEN - expect(stack).to(haveResourceLike('AWS::Batch::ComputeEnvironment', { + Template.fromStack(stack).hasResourceProperties('AWS::Batch::ComputeEnvironment', { ...expectedManagedDefaultComputeProps({ InstanceTypes: ['optimal'], }), - }, ResourcePart.Properties)); + }); }); }); @@ -391,11 +390,11 @@ describe('Batch Compute Evironment', () => { }); // THEN - expect(stack).to(haveResourceLike('AWS::Batch::ComputeEnvironment', { + Template.fromStack(stack).hasResourceProperties('AWS::Batch::ComputeEnvironment', { ...expectedManagedDefaultComputeProps({ Type: batch.ComputeResourceType.ON_DEMAND, }), - }, ResourcePart.Properties)); + }); }); }); }); diff --git a/packages/@aws-cdk/aws-batch/test/job-definition.test.ts b/packages/@aws-cdk/aws-batch/test/job-definition.test.ts index 2761611e063bb..ed9bffb7a90bc 100644 --- a/packages/@aws-cdk/aws-batch/test/job-definition.test.ts +++ b/packages/@aws-cdk/aws-batch/test/job-definition.test.ts @@ -1,5 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; -import { ResourcePart } from '@aws-cdk/assert-internal/lib/assertions/have-resource'; +import { Template } from '@aws-cdk/assertions'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as ecr from '@aws-cdk/aws-ecr'; import * as ecs from '@aws-cdk/aws-ecs'; @@ -70,7 +69,7 @@ describe('Batch Job Definition', () => { new batch.JobDefinition(stack, 'job-def', jobDefProps); // THEN - expect(stack).toHaveResourceLike('AWS::Batch::JobDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::Batch::JobDefinition', { JobDefinitionName: jobDefProps.jobDefinitionName, ContainerProperties: jobDefProps.container ? { Command: jobDefProps.container.command, @@ -113,7 +112,7 @@ describe('Batch Job Definition', () => { AttemptDurationSeconds: jobDefProps.timeout ? jobDefProps.timeout.toSeconds() : -1, }, Type: 'container', - }, ResourcePart.Properties); + }); }); test('can use an ecr image', () => { // WHEN @@ -126,7 +125,7 @@ describe('Batch Job Definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::Batch::JobDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::Batch::JobDefinition', { ContainerProperties: { Image: { 'Fn::Join': [ @@ -182,7 +181,7 @@ describe('Batch Job Definition', () => { ReadonlyRootFilesystem: false, Vcpus: 1, }, - }, ResourcePart.Properties); + }); }); test('can use a registry image', () => { @@ -194,7 +193,7 @@ describe('Batch Job Definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::Batch::JobDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::Batch::JobDefinition', { ContainerProperties: { Image: 'docker/whalesay', Memory: 4, @@ -202,7 +201,7 @@ describe('Batch Job Definition', () => { ReadonlyRootFilesystem: false, Vcpus: 1, }, - }, ResourcePart.Properties); + }); }); test('can be imported from an ARN', () => { @@ -247,7 +246,7 @@ describe('Batch Job Definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::Batch::JobDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::Batch::JobDefinition', { ContainerProperties: { LogConfiguration: { LogDriver: 'awslogs', @@ -285,6 +284,6 @@ describe('Batch Job Definition', () => { ], }, }, - }, ResourcePart.Properties); + }); }); }); diff --git a/packages/@aws-cdk/aws-batch/test/job-queue.test.ts b/packages/@aws-cdk/aws-batch/test/job-queue.test.ts index 0bec27b20899a..94fe03c5e93f0 100644 --- a/packages/@aws-cdk/aws-batch/test/job-queue.test.ts +++ b/packages/@aws-cdk/aws-batch/test/job-queue.test.ts @@ -1,5 +1,4 @@ -import { ResourcePart } from '@aws-cdk/assert-internal'; -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as cdk from '@aws-cdk/core'; import * as batch from '../lib'; @@ -48,7 +47,7 @@ describe('Batch Job Queue', () => { new batch.JobQueue(stack, 'test-job-queue', props); // THEN - expect(stack).toHaveResourceLike('AWS::Batch::JobQueue', { + Template.fromStack(stack).hasResourceProperties('AWS::Batch::JobQueue', { JobQueueName: props.jobQueueName, State: props.enabled ? 'ENABLED' : 'DISABLED', Priority: props.priority, @@ -60,7 +59,7 @@ describe('Batch Job Queue', () => { Order: 1, }, ], - }, ResourcePart.Properties); + }); }); it('should have a default queue priority of 1', () => { @@ -76,8 +75,8 @@ describe('Batch Job Queue', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::Batch::JobQueue', { + Template.fromStack(stack).hasResourceProperties('AWS::Batch::JobQueue', { Priority: 1, - }, ResourcePart.Properties); + }); }); }); diff --git a/packages/@aws-cdk/aws-cloud9/package.json b/packages/@aws-cdk/aws-cloud9/package.json index 8aac346d87398..452002a0e5dde 100644 --- a/packages/@aws-cdk/aws-cloud9/package.json +++ b/packages/@aws-cdk/aws-cloud9/package.json @@ -73,13 +73,13 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/jest": "^26.0.24", + "@aws-cdk/assertions": "0.0.0", "@aws-cdk/aws-codecommit": "0.0.0", + "@types/jest": "^26.0.24", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", - "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "pkglint": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-cloud9/test/cloud9.environment.test.ts b/packages/@aws-cdk/aws-cloud9/test/cloud9.environment.test.ts index 231484ea26ffb..079fe546d0a4f 100644 --- a/packages/@aws-cdk/aws-cloud9/test/cloud9.environment.test.ts +++ b/packages/@aws-cdk/aws-cloud9/test/cloud9.environment.test.ts @@ -1,4 +1,4 @@ -import { expect as expectCDK, haveResource, haveResourceLike } from '@aws-cdk/assert-internal'; +import { Template } from '@aws-cdk/assertions'; import * as codecommit from '@aws-cdk/aws-codecommit'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as cdk from '@aws-cdk/core'; @@ -16,7 +16,7 @@ test('create resource correctly with only vpc provide', () => { // WHEN new cloud9.Ec2Environment(stack, 'C9Env', { vpc }); // THEN - expectCDK(stack).to(haveResource('AWS::Cloud9::EnvironmentEC2')); + Template.fromStack(stack).resourceCountIs('AWS::Cloud9::EnvironmentEC2', 1); }); test('create resource correctly with both vpc and subnetSelectio', () => { @@ -28,7 +28,7 @@ test('create resource correctly with both vpc and subnetSelectio', () => { }, }); // THEN - expectCDK(stack).to(haveResource('AWS::Cloud9::EnvironmentEC2')); + Template.fromStack(stack).resourceCountIs('AWS::Cloud9::EnvironmentEC2', 1); }); test('import correctly from existing environment', () => { @@ -45,7 +45,7 @@ test('create correctly with instanceType specified', () => { instanceType: ec2.InstanceType.of(ec2.InstanceClass.C5, ec2.InstanceSize.LARGE), }); // THEN - expectCDK(stack).to(haveResource('AWS::Cloud9::EnvironmentEC2')); + Template.fromStack(stack).resourceCountIs('AWS::Cloud9::EnvironmentEC2', 1); }); test('throw error when subnetSelection not specified and the provided VPC has no public subnets', () => { @@ -80,7 +80,7 @@ test('can use CodeCommit repositories', () => { ], }); // THEN - expectCDK(stack).to(haveResourceLike('AWS::Cloud9::EnvironmentEC2', { + Template.fromStack(stack).hasResourceProperties('AWS::Cloud9::EnvironmentEC2', { InstanceType: 't2.micro', Repositories: [ { @@ -103,5 +103,5 @@ test('can use CodeCommit repositories', () => { }, }, ], - })); + }); }); diff --git a/packages/@aws-cdk/aws-cloud9/test/cloud9.test.ts b/packages/@aws-cdk/aws-cloud9/test/cloud9.test.ts deleted file mode 100644 index c4505ad966984..0000000000000 --- a/packages/@aws-cdk/aws-cloud9/test/cloud9.test.ts +++ /dev/null @@ -1,6 +0,0 @@ -import '@aws-cdk/assert-internal/jest'; -import {} from '../lib'; - -test('No tests are specified for this package', () => { - expect(true).toBe(true); -}); diff --git a/packages/@aws-cdk/aws-codestar/package.json b/packages/@aws-cdk/aws-codestar/package.json index 8b943f821668d..7740100ab9d29 100644 --- a/packages/@aws-cdk/aws-codestar/package.json +++ b/packages/@aws-cdk/aws-codestar/package.json @@ -75,12 +75,12 @@ }, "license": "Apache-2.0", "devDependencies": { + "@aws-cdk/assertions": "0.0.0", "@types/jest": "^26.0.24", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", - "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "pkglint": "0.0.0" }, "dependencies": { "@aws-cdk/aws-s3": "0.0.0", diff --git a/packages/@aws-cdk/aws-codestar/test/codestar.test.ts b/packages/@aws-cdk/aws-codestar/test/codestar.test.ts index 7b142a03ac221..c1af7348d849c 100644 --- a/packages/@aws-cdk/aws-codestar/test/codestar.test.ts +++ b/packages/@aws-cdk/aws-codestar/test/codestar.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import { Bucket } from '@aws-cdk/aws-s3'; import * as cdk from '@aws-cdk/core'; import { GitHubRepository, RepositoryVisibility } from '../lib'; @@ -22,7 +22,7 @@ describe('GitHub Repository', () => { contentsKey: 'import.zip', }); - expect(stack).toHaveResource('AWS::CodeStar::GitHubRepository', { + Template.fromStack(stack).hasResourceProperties('AWS::CodeStar::GitHubRepository', { RepositoryAccessToken: '{{resolve:secretsmanager:my-github-token:SecretString:token::}}', RepositoryName: 'bar', RepositoryOwner: 'foo', @@ -48,7 +48,7 @@ describe('GitHub Repository', () => { visibility: RepositoryVisibility.PRIVATE, }); - expect(stack).toHaveResourceLike('AWS::CodeStar::GitHubRepository', { + Template.fromStack(stack).hasResourceProperties('AWS::CodeStar::GitHubRepository', { EnableIssues: true, IsPrivate: true, }); diff --git a/packages/@aws-cdk/aws-glue/package.json b/packages/@aws-cdk/aws-glue/package.json index f489c1955478e..5f11a3895db92 100644 --- a/packages/@aws-cdk/aws-glue/package.json +++ b/packages/@aws-cdk/aws-glue/package.json @@ -74,14 +74,14 @@ "license": "Apache-2.0", "devDependencies": { "@types/jest": "^26.0.24", + "@aws-cdk/assertions": "0.0.0", "@aws-cdk/cx-api": "0.0.0", "@types/nodeunit": "^0.0.32", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", "jest": "^26.6.3", - "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "pkglint": "0.0.0" }, "dependencies": { "@aws-cdk/aws-ec2": "0.0.0", diff --git a/packages/@aws-cdk/aws-glue/test/connection.test.ts b/packages/@aws-cdk/aws-glue/test/connection.test.ts index c61cc6197130d..b4fdaa2988cde 100644 --- a/packages/@aws-cdk/aws-glue/test/connection.test.ts +++ b/packages/@aws-cdk/aws-glue/test/connection.test.ts @@ -1,7 +1,6 @@ -import * as cdkassert from '@aws-cdk/assert-internal'; +import { Template } from '@aws-cdk/assertions'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as cdk from '@aws-cdk/core'; -import '@aws-cdk/assert-internal/jest'; import * as glue from '../lib'; test('a connection with connection properties', () => { @@ -15,7 +14,7 @@ test('a connection with connection properties', () => { }, }); - cdkassert.expect(stack).to(cdkassert.haveResource('AWS::Glue::Connection', { + Template.fromStack(stack).hasResourceProperties('AWS::Glue::Connection', { CatalogId: { Ref: 'AWS::AccountId', }, @@ -27,7 +26,7 @@ test('a connection with connection properties', () => { }, ConnectionType: 'JDBC', }, - })); + }); }); test('a connection with a subnet and security group', () => { @@ -43,7 +42,7 @@ test('a connection with a subnet and security group', () => { subnet, }); - cdkassert.expect(stack).to(cdkassert.haveResource('AWS::Glue::Connection', { + Template.fromStack(stack).hasResourceProperties('AWS::Glue::Connection', { CatalogId: { Ref: 'AWS::AccountId', }, @@ -55,7 +54,7 @@ test('a connection with a subnet and security group', () => { SecurityGroupIdList: ['sgId'], }, }, - })); + }); }); test('a connection with a name and description', () => { @@ -66,7 +65,7 @@ test('a connection with a name and description', () => { type: glue.ConnectionType.NETWORK, }); - cdkassert.expect(stack).to(cdkassert.haveResource('AWS::Glue::Connection', { + Template.fromStack(stack).hasResourceProperties('AWS::Glue::Connection', { CatalogId: { Ref: 'AWS::AccountId', }, @@ -75,7 +74,7 @@ test('a connection with a name and description', () => { Name: 'name', Description: 'description', }, - })); + }); }); test('a connection with a custom type', () => { @@ -86,7 +85,7 @@ test('a connection with a custom type', () => { type: new glue.ConnectionType('CUSTOM_TYPE'), }); - cdkassert.expect(stack).to(cdkassert.haveResource('AWS::Glue::Connection', { + Template.fromStack(stack).hasResourceProperties('AWS::Glue::Connection', { CatalogId: { Ref: 'AWS::AccountId', }, @@ -95,7 +94,7 @@ test('a connection with a custom type', () => { Name: 'name', Description: 'description', }, - })); + }); }); test('a connection with match criteria', () => { @@ -105,7 +104,7 @@ test('a connection with match criteria', () => { matchCriteria: ['c1', 'c2'], }); - cdkassert.expect(stack).to(cdkassert.haveResource('AWS::Glue::Connection', { + Template.fromStack(stack).hasResourceProperties('AWS::Glue::Connection', { CatalogId: { Ref: 'AWS::AccountId', }, @@ -113,7 +112,7 @@ test('a connection with match criteria', () => { ConnectionType: 'NETWORK', MatchCriteria: ['c1', 'c2'], }, - })); + }); }); test('addProperty', () => { @@ -123,7 +122,7 @@ test('addProperty', () => { }); connection.addProperty('SomeKey', 'SomeValue'); - cdkassert.expect(stack).to(cdkassert.haveResource('AWS::Glue::Connection', { + Template.fromStack(stack).hasResourceProperties('AWS::Glue::Connection', { CatalogId: { Ref: 'AWS::AccountId', }, @@ -133,7 +132,7 @@ test('addProperty', () => { SomeKey: 'SomeValue', }, }, - })); + }); }); test('fromConnectionName', () => { diff --git a/packages/@aws-cdk/aws-glue/test/database.test.ts b/packages/@aws-cdk/aws-glue/test/database.test.ts index f5ad6461ee190..6c8171df3547c 100644 --- a/packages/@aws-cdk/aws-glue/test/database.test.ts +++ b/packages/@aws-cdk/aws-glue/test/database.test.ts @@ -1,6 +1,4 @@ -import { deepEqual, throws } from 'assert'; -import { expect } from '@aws-cdk/assert-internal'; -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import { Stack } from '@aws-cdk/core'; import * as glue from '../lib'; @@ -11,7 +9,7 @@ test('default database does not create a bucket', () => { databaseName: 'test_database', }); - expect(stack).toMatch({ + Template.fromStack(stack).templateMatches({ Resources: { DatabaseB269D8BB: { Type: 'AWS::Glue::Database', @@ -37,7 +35,7 @@ test('explicit locationURI', () => { locationUri: 's3://my-uri/', }); - expect(stack).toMatch({ + Template.fromStack(stack).templateMatches({ Resources: { DatabaseB269D8BB: { Type: 'AWS::Glue::Database', @@ -64,31 +62,31 @@ test('fromDatabase', () => { const database = glue.Database.fromDatabaseArn(stack, 'import', 'arn:aws:glue:us-east-1:123456789012:database/db1'); // THEN - deepEqual(database.databaseArn, 'arn:aws:glue:us-east-1:123456789012:database/db1'); - deepEqual(database.databaseName, 'db1'); - deepEqual(stack.resolve(database.catalogArn), { + expect(database.databaseArn).toEqual('arn:aws:glue:us-east-1:123456789012:database/db1'); + expect(database.databaseName).toEqual('db1'); + expect(stack.resolve(database.catalogArn)).toEqual({ 'Fn::Join': ['', ['arn:', { Ref: 'AWS::Partition' }, ':glue:', { Ref: 'AWS::Region' }, ':', { Ref: 'AWS::AccountId' }, ':catalog']], }); - deepEqual(stack.resolve(database.catalogId), { Ref: 'AWS::AccountId' }); + expect(stack.resolve(database.catalogId)).toEqual({ Ref: 'AWS::AccountId' }); }); test('locationUri length must be >= 1', () => { const stack = new Stack(); - throws(() => + expect(() => new glue.Database(stack, 'Database', { databaseName: 'test_database', locationUri: '', }), - ); + ).toThrow(); }); test('locationUri length must be <= 1024', () => { const stack = new Stack(); - throws(() => + expect(() => new glue.Database(stack, 'Database', { databaseName: 'test_database', locationUri: 'a'.repeat(1025), }), - ); + ).toThrow(); }); diff --git a/packages/@aws-cdk/aws-glue/test/schema.test.ts b/packages/@aws-cdk/aws-glue/test/schema.test.ts index 2155655e27e6d..dcb6b731a0e27 100644 --- a/packages/@aws-cdk/aws-glue/test/schema.test.ts +++ b/packages/@aws-cdk/aws-glue/test/schema.test.ts @@ -1,126 +1,124 @@ -import '@aws-cdk/assert-internal/jest'; -import { doesNotThrow, equal, throws } from 'assert'; import { Schema } from '../lib'; test('boolean type', () => { - equal(Schema.BOOLEAN.inputString, 'boolean'); - equal(Schema.BOOLEAN.isPrimitive, true); + expect(Schema.BOOLEAN.inputString).toEqual('boolean'); + expect(Schema.BOOLEAN.isPrimitive).toEqual(true); }); test('binary type', () => { - equal(Schema.BINARY.inputString, 'binary'); - equal(Schema.BINARY.isPrimitive, true); + expect(Schema.BINARY.inputString).toEqual('binary'); + expect(Schema.BINARY.isPrimitive).toEqual(true); }); test('bigint type', () => { - equal(Schema.BIG_INT.inputString, 'bigint'); - equal(Schema.BIG_INT.isPrimitive, true); + expect(Schema.BIG_INT.inputString).toEqual('bigint'); + expect(Schema.BIG_INT.isPrimitive).toEqual(true); }); test('double type', () => { - equal(Schema.DOUBLE.inputString, 'double'); - equal(Schema.DOUBLE.isPrimitive, true); + expect(Schema.DOUBLE.inputString).toEqual('double'); + expect(Schema.DOUBLE.isPrimitive).toEqual(true); }); test('float type', () => { - equal(Schema.FLOAT.inputString, 'float'); - equal(Schema.FLOAT.isPrimitive, true); + expect(Schema.FLOAT.inputString).toEqual('float'); + expect(Schema.FLOAT.isPrimitive).toEqual(true); }); test('integer type', () => { - equal(Schema.INTEGER.inputString, 'int'); - equal(Schema.INTEGER.isPrimitive, true); + expect(Schema.INTEGER.inputString).toEqual('int'); + expect(Schema.INTEGER.isPrimitive).toEqual(true); }); test('smallint type', () => { - equal(Schema.SMALL_INT.inputString, 'smallint'); - equal(Schema.SMALL_INT.isPrimitive, true); + expect(Schema.SMALL_INT.inputString).toEqual('smallint'); + expect(Schema.SMALL_INT.isPrimitive).toEqual(true); }); test('tinyint type', () => { - equal(Schema.TINY_INT.inputString, 'tinyint'); - equal(Schema.TINY_INT.isPrimitive, true); + expect(Schema.TINY_INT.inputString).toEqual('tinyint'); + expect(Schema.TINY_INT.isPrimitive).toEqual(true); }); test('decimal type', () => { - equal(Schema.decimal(16).inputString, 'decimal(16)'); - equal(Schema.decimal(16, 1).inputString, 'decimal(16,1)'); - equal(Schema.decimal(16).isPrimitive, true); - equal(Schema.decimal(16, 1).isPrimitive, true); + expect(Schema.decimal(16).inputString).toEqual('decimal(16)'); + expect(Schema.decimal(16, 1).inputString).toEqual('decimal(16,1)'); + expect(Schema.decimal(16).isPrimitive).toEqual(true); + expect(Schema.decimal(16, 1).isPrimitive).toEqual(true); }); // TODO: decimal bounds test('date type', () => { - equal(Schema.DATE.inputString, 'date'); - equal(Schema.DATE.isPrimitive, true); + expect(Schema.DATE.inputString).toEqual('date'); + expect(Schema.DATE.isPrimitive).toEqual(true); }); test('timestamp type', () => { - equal(Schema.TIMESTAMP.inputString, 'timestamp'); - equal(Schema.TIMESTAMP.isPrimitive, true); + expect(Schema.TIMESTAMP.inputString).toEqual('timestamp'); + expect(Schema.TIMESTAMP.isPrimitive).toEqual(true); }); test('string type', () => { - equal(Schema.STRING.inputString, 'string'); - equal(Schema.STRING.isPrimitive, true); + expect(Schema.STRING.inputString).toEqual('string'); + expect(Schema.STRING.isPrimitive).toEqual(true); }); test('char type', () => { - equal(Schema.char(1).inputString, 'char(1)'); - equal(Schema.char(1).isPrimitive, true); + expect(Schema.char(1).inputString).toEqual('char(1)'); + expect(Schema.char(1).isPrimitive).toEqual(true); }); test('char length must be test(at least 1', () => { - doesNotThrow(() => Schema.char(1)); - throws(() => Schema.char(0)); - throws(() => Schema.char(-1)); + expect(() => Schema.char(1)).not.toThrow(); + expect(() => Schema.char(0)).toThrow(); + expect(() => Schema.char(-1)).toThrow(); }); test('char length must test(be <= 255', () => { - doesNotThrow(() => Schema.char(255)); - throws(() => Schema.char(256)); + expect(() => Schema.char(255)).not.toThrow(); + expect(() => Schema.char(256)).toThrow(); }); test('varchar type', () => { - equal(Schema.varchar(1).inputString, 'varchar(1)'); - equal(Schema.varchar(1).isPrimitive, true); + expect(Schema.varchar(1).inputString).toEqual('varchar(1)'); + expect(Schema.varchar(1).isPrimitive).toEqual(true); }); test('varchar length must be test(at least 1', () => { - doesNotThrow(() => Schema.varchar(1)); - throws(() => Schema.varchar(0)); - throws(() => Schema.varchar(-1)); + expect(() => Schema.varchar(1)).not.toThrow(); + expect(() => Schema.varchar(0)).toThrow(); + expect(() => Schema.varchar(-1)).toThrow(); }); test('varchar length must test(be <= 65535', () => { - doesNotThrow(() => Schema.varchar(65535)); - throws(() => Schema.varchar(65536)); + expect(() => Schema.varchar(65535)).not.toThrow(); + expect(() => Schema.varchar(65536)).toThrow(); }); test('test(array', () => { const type = Schema.array(Schema.STRING); - equal(type.inputString, 'array'); - equal(type.isPrimitive, false); + expect(type.inputString).toEqual('array'); + expect(type.isPrimitive).toEqual(false); }); test('array', () => { const type = Schema.array(Schema.char(1)); - equal(type.inputString, 'array'); - equal(type.isPrimitive, false); + expect(type.inputString).toEqual('array'); + expect(type.isPrimitive).toEqual(false); }); test('test(array', () => { const type = Schema.array( Schema.array(Schema.STRING)); - equal(type.inputString, 'array>'); - equal(type.isPrimitive, false); + expect(type.inputString).toEqual('array>'); + expect(type.isPrimitive).toEqual(false); }); test('test(array', () => { const type = Schema.array( Schema.map(Schema.STRING, Schema.STRING)); - equal(type.inputString, 'array>'); - equal(type.isPrimitive, false); + expect(type.inputString).toEqual('array>'); + expect(type.isPrimitive).toEqual(false); }); test('test(array', () => { @@ -129,8 +127,8 @@ test('test(array', () => { name: 'key', type: Schema.STRING, }])); - equal(type.inputString, 'array>'); - equal(type.isPrimitive, false); + expect(type.inputString).toEqual('array>'); + expect(type.isPrimitive).toEqual(false); }); test('map', () => { @@ -138,8 +136,8 @@ test('map', () => { Schema.STRING, Schema.STRING, ); - equal(type.inputString, 'map'); - equal(type.isPrimitive, false); + expect(type.inputString).toEqual('map'); + expect(type.isPrimitive).toEqual(false); }); test('map', () => { @@ -147,8 +145,8 @@ test('map', () => { Schema.INTEGER, Schema.STRING, ); - equal(type.inputString, 'map'); - equal(type.isPrimitive, false); + expect(type.inputString).toEqual('map'); + expect(type.isPrimitive).toEqual(false); }); test('map', () => { @@ -156,8 +154,8 @@ test('map', () => { Schema.char(1), Schema.char(1), ); - equal(type.inputString, 'map'); - equal(type.isPrimitive, false); + expect(type.inputString).toEqual('map'); + expect(type.isPrimitive).toEqual(false); }); test('map', () => { @@ -165,8 +163,8 @@ test('map', () => { Schema.char(1), Schema.array(Schema.STRING), ); - equal(type.inputString, 'map>'); - equal(type.isPrimitive, false); + expect(type.inputString).toEqual('map>'); + expect(type.isPrimitive).toEqual(false); }); test('map', () => { @@ -176,8 +174,8 @@ test('map', () => { Schema.STRING, Schema.STRING), ); - equal(type.inputString, 'map>'); - equal(type.isPrimitive, false); + expect(type.inputString).toEqual('map>'); + expect(type.isPrimitive).toEqual(false); }); test('map', () => { @@ -188,26 +186,26 @@ test('map', () => { type: Schema.STRING, }]), ); - equal(type.inputString, 'map>'); - equal(type.isPrimitive, false); + expect(type.inputString).toEqual('map>'); + expect(type.isPrimitive).toEqual(false); }); test('map throws if keyType is test(non-primitive', () => { - throws(() => Schema.map( + expect(() => Schema.map( Schema.array(Schema.STRING), Schema.STRING, - )); - throws(() => Schema.map( + )).toThrow(); + expect(() => Schema.map( Schema.map(Schema.STRING, Schema.STRING), Schema.STRING, - )); - throws(() => Schema.map( + )).toThrow(); + expect(() => Schema.map( Schema.struct([{ name: 'key', type: Schema.STRING, }]), Schema.STRING, - )); + )).toThrow(); }); test('struct type', () => { @@ -233,9 +231,9 @@ test('struct type', () => { }]), }]); - equal(type.isPrimitive, false); - equal( - type.inputString, + expect(type.isPrimitive).toEqual(false); + expect(type.inputString).toEqual( // eslint-disable-next-line max-len - 'struct,map:map,nested_struct:struct>'); + 'struct,map:map,nested_struct:struct>', + ); }); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-glue/test/security-configuration.test.ts b/packages/@aws-cdk/aws-glue/test/security-configuration.test.ts index ce89c393e5301..ca42a4eb53453 100644 --- a/packages/@aws-cdk/aws-glue/test/security-configuration.test.ts +++ b/packages/@aws-cdk/aws-glue/test/security-configuration.test.ts @@ -1,7 +1,6 @@ -import * as cdkassert from '@aws-cdk/assert-internal'; +import { Template } from '@aws-cdk/assertions'; import * as kms from '@aws-cdk/aws-kms'; import * as cdk from '@aws-cdk/core'; -import '@aws-cdk/assert-internal/jest'; import * as glue from '../lib'; test('throws when a security configuration has no encryption config', () => { @@ -29,7 +28,7 @@ test('a security configuration with encryption configuration requiring kms key a expect(securityConfiguration.jobBookmarksEncryptionKey).toBeUndefined(); expect(securityConfiguration.s3EncryptionKey).toBeUndefined(); - cdkassert.expect(stack).to(cdkassert.haveResource('AWS::Glue::SecurityConfiguration', { + Template.fromStack(stack).hasResourceProperties('AWS::Glue::SecurityConfiguration', { Name: 'name', EncryptionConfiguration: { CloudWatchEncryption: { @@ -37,7 +36,7 @@ test('a security configuration with encryption configuration requiring kms key a KmsKeyArn: keyArn, }, }, - })); + }); }); test('a security configuration with an encryption configuration requiring kms key but not providing an explicit one', () => { @@ -54,9 +53,9 @@ test('a security configuration with an encryption configuration requiring kms ke expect(securityConfiguration.jobBookmarksEncryptionKey).toBeUndefined(); expect(securityConfiguration.s3EncryptionKey).toBeUndefined(); - cdkassert.expect(stack).to(cdkassert.haveResource('AWS::KMS::Key')); + Template.fromStack(stack).resourceCountIs('AWS::KMS::Key', 1); - cdkassert.expect(stack).to(cdkassert.haveResource('AWS::Glue::SecurityConfiguration', { + Template.fromStack(stack).hasResourceProperties('AWS::Glue::SecurityConfiguration', { Name: 'name', EncryptionConfiguration: { CloudWatchEncryption: { @@ -64,7 +63,7 @@ test('a security configuration with an encryption configuration requiring kms ke KmsKeyArn: stack.resolve(securityConfiguration.cloudWatchEncryptionKey?.keyArn), }, }, - })); + }); }); test('a security configuration with all encryption configs and mixed kms key inputs', () => { @@ -90,9 +89,9 @@ test('a security configuration with all encryption configs and mixed kms key inp expect(securityConfiguration.jobBookmarksEncryptionKey?.keyArn).toEqual(keyArn); expect(securityConfiguration.s3EncryptionKey).toBeUndefined(); - cdkassert.expect(stack).to(cdkassert.haveResource('AWS::KMS::Key')); + Template.fromStack(stack).resourceCountIs('AWS::KMS::Key', 1); - cdkassert.expect(stack).to(cdkassert.haveResource('AWS::Glue::SecurityConfiguration', { + Template.fromStack(stack).hasResourceProperties('AWS::Glue::SecurityConfiguration', { Name: 'name', EncryptionConfiguration: { CloudWatchEncryption: { @@ -109,7 +108,7 @@ test('a security configuration with all encryption configs and mixed kms key inp S3EncryptionMode: 'SSE-S3', }], }, - })); + }); }); test('fromSecurityConfigurationName', () => { diff --git a/packages/@aws-cdk/aws-glue/test/table.test.ts b/packages/@aws-cdk/aws-glue/test/table.test.ts index 084eaa67ab564..fbb1424f766c1 100644 --- a/packages/@aws-cdk/aws-glue/test/table.test.ts +++ b/packages/@aws-cdk/aws-glue/test/table.test.ts @@ -1,6 +1,4 @@ -import { deepEqual, doesNotThrow, equal, notEqual, ok } from 'assert'; -import { expect as cdkExpect, haveResource, ResourcePart } from '@aws-cdk/assert-internal'; -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as iam from '@aws-cdk/aws-iam'; import * as kms from '@aws-cdk/aws-kms'; import * as s3 from '@aws-cdk/aws-s3'; @@ -28,15 +26,15 @@ test('unpartitioned JSON table', () => { }], dataFormat: glue.DataFormat.JSON, }); - equal(table.encryption, glue.TableEncryption.UNENCRYPTED); + expect(table.encryption).toEqual(glue.TableEncryption.UNENCRYPTED); - cdkExpect(tableStack).to(haveResource('AWS::S3::Bucket', { + Template.fromStack(tableStack).hasResource('AWS::S3::Bucket', { Type: 'AWS::S3::Bucket', DeletionPolicy: 'Retain', UpdateReplacePolicy: 'Retain', - }, ResourcePart.CompleteDefinition)); + }); - cdkExpect(tableStack).to(haveResource('AWS::Glue::Table', { + Template.fromStack(tableStack).hasResourceProperties('AWS::Glue::Table', { CatalogId: { Ref: 'AWS::AccountId', }, @@ -79,7 +77,7 @@ test('unpartitioned JSON table', () => { }, TableType: 'EXTERNAL_TABLE', }, - })); + }); }); @@ -104,11 +102,11 @@ test('partitioned JSON table', () => { }], dataFormat: glue.DataFormat.JSON, }); - equal(table.encryption, glue.TableEncryption.UNENCRYPTED); - equal(table.encryptionKey, undefined); - equal(table.bucket.encryptionKey, undefined); + expect(table.encryption).toEqual(glue.TableEncryption.UNENCRYPTED); + expect(table.encryptionKey).toEqual(undefined); + expect(table.bucket.encryptionKey).toEqual(undefined); - cdkExpect(tableStack).to(haveResource('AWS::Glue::Table', { + Template.fromStack(tableStack).hasResourceProperties('AWS::Glue::Table', { CatalogId: { Ref: 'AWS::AccountId', }, @@ -157,7 +155,7 @@ test('partitioned JSON table', () => { }, TableType: 'EXTERNAL_TABLE', }, - })); + }); }); @@ -177,10 +175,10 @@ test('compressed table', () => { compressed: true, dataFormat: glue.DataFormat.JSON, }); - equal(table.encryptionKey, undefined); - equal(table.bucket.encryptionKey, undefined); + expect(table.encryptionKey).toEqual(undefined); + expect(table.bucket.encryptionKey).toEqual(undefined); - cdkExpect(stack).to(haveResource('AWS::Glue::Table', { + Template.fromStack(stack).hasResourceProperties('AWS::Glue::Table', { CatalogId: { Ref: 'AWS::AccountId', }, @@ -223,7 +221,7 @@ test('compressed table', () => { }, TableType: 'EXTERNAL_TABLE', }, - })); + }); }); @@ -247,7 +245,7 @@ test('table.node.defaultChild', () => { }); // THEN - ok(table.node.defaultChild instanceof glue.CfnTable); + expect(table.node.defaultChild instanceof glue.CfnTable).toEqual(true); }); test('encrypted table: SSE-S3', () => { @@ -266,11 +264,11 @@ test('encrypted table: SSE-S3', () => { encryption: glue.TableEncryption.S3_MANAGED, dataFormat: glue.DataFormat.JSON, }); - equal(table.encryption, glue.TableEncryption.S3_MANAGED); - equal(table.encryptionKey, undefined); - equal(table.bucket.encryptionKey, undefined); + expect(table.encryption).toEqual(glue.TableEncryption.S3_MANAGED); + expect(table.encryptionKey).toEqual(undefined); + expect(table.bucket.encryptionKey).toEqual(undefined); - cdkExpect(stack).to(haveResource('AWS::Glue::Table', { + Template.fromStack(stack).hasResourceProperties('AWS::Glue::Table', { CatalogId: { Ref: 'AWS::AccountId', }, @@ -313,9 +311,9 @@ test('encrypted table: SSE-S3', () => { }, TableType: 'EXTERNAL_TABLE', }, - })); + }); - cdkExpect(stack).to(haveResource('AWS::S3::Bucket', { + Template.fromStack(stack).hasResourceProperties('AWS::S3::Bucket', { BucketEncryption: { ServerSideEncryptionConfiguration: [ { @@ -325,7 +323,7 @@ test('encrypted table: SSE-S3', () => { }, ], }, - })); + }); }); @@ -345,14 +343,14 @@ test('encrypted table: SSE-KMS (implicitly created key)', () => { encryption: glue.TableEncryption.KMS, dataFormat: glue.DataFormat.JSON, }); - equal(table.encryption, glue.TableEncryption.KMS); - equal(table.encryptionKey, table.bucket.encryptionKey); + expect(table.encryption).toEqual(glue.TableEncryption.KMS); + expect(table.encryptionKey).toEqual(table.bucket.encryptionKey); - cdkExpect(stack).to(haveResource('AWS::KMS::Key', { + Template.fromStack(stack).hasResourceProperties('AWS::KMS::Key', { Description: 'Created by Default/Table/Bucket', - })); + }); - cdkExpect(stack).to(haveResource('AWS::S3::Bucket', { + Template.fromStack(stack).hasResourceProperties('AWS::S3::Bucket', { BucketEncryption: { ServerSideEncryptionConfiguration: [ { @@ -368,9 +366,9 @@ test('encrypted table: SSE-KMS (implicitly created key)', () => { }, ], }, - })); + }); - cdkExpect(stack).to(haveResource('AWS::Glue::Table', { + Template.fromStack(stack).hasResourceProperties('AWS::Glue::Table', { CatalogId: { Ref: 'AWS::AccountId', }, @@ -413,7 +411,7 @@ test('encrypted table: SSE-KMS (implicitly created key)', () => { }, TableType: 'EXTERNAL_TABLE', }, - })); + }); }); @@ -437,15 +435,15 @@ test('encrypted table: SSE-KMS (explicitly created key)', () => { encryptionKey, dataFormat: glue.DataFormat.JSON, }); - equal(table.encryption, glue.TableEncryption.KMS); - equal(table.encryptionKey, table.bucket.encryptionKey); - notEqual(table.encryptionKey, undefined); + expect(table.encryption).toEqual(glue.TableEncryption.KMS); + expect(table.encryptionKey).toEqual(table.bucket.encryptionKey); + expect(table.encryptionKey).not.toEqual(undefined); - cdkExpect(stack).to(haveResource('AWS::KMS::Key', { + Template.fromStack(stack).hasResourceProperties('AWS::KMS::Key', { Description: 'OurKey', - })); + }); - cdkExpect(stack).to(haveResource('AWS::S3::Bucket', { + Template.fromStack(stack).hasResourceProperties('AWS::S3::Bucket', { BucketEncryption: { ServerSideEncryptionConfiguration: [ { @@ -461,9 +459,9 @@ test('encrypted table: SSE-KMS (explicitly created key)', () => { }, ], }, - })); + }); - cdkExpect(stack).to(haveResource('AWS::Glue::Table', { + Template.fromStack(stack).hasResourceProperties('AWS::Glue::Table', { CatalogId: { Ref: 'AWS::AccountId', }, @@ -506,7 +504,7 @@ test('encrypted table: SSE-KMS (explicitly created key)', () => { }, TableType: 'EXTERNAL_TABLE', }, - })); + }); }); @@ -526,11 +524,11 @@ test('encrypted table: SSE-KMS_MANAGED', () => { encryption: glue.TableEncryption.KMS_MANAGED, dataFormat: glue.DataFormat.JSON, }); - equal(table.encryption, glue.TableEncryption.KMS_MANAGED); - equal(table.encryptionKey, undefined); - equal(table.bucket.encryptionKey, undefined); + expect(table.encryption).toEqual(glue.TableEncryption.KMS_MANAGED); + expect(table.encryptionKey).toEqual(undefined); + expect(table.bucket.encryptionKey).toEqual(undefined); - cdkExpect(stack).to(haveResource('AWS::S3::Bucket', { + Template.fromStack(stack).hasResourceProperties('AWS::S3::Bucket', { BucketEncryption: { ServerSideEncryptionConfiguration: [ { @@ -540,9 +538,9 @@ test('encrypted table: SSE-KMS_MANAGED', () => { }, ], }, - })); + }); - cdkExpect(stack).to(haveResource('AWS::Glue::Table', { + Template.fromStack(stack).hasResourceProperties('AWS::Glue::Table', { CatalogId: { Ref: 'AWS::AccountId', }, @@ -585,7 +583,7 @@ test('encrypted table: SSE-KMS_MANAGED', () => { }, TableType: 'EXTERNAL_TABLE', }, - })); + }); }); @@ -605,13 +603,13 @@ test('encrypted table: CSE-KMS (implicitly created key)', () => { encryption: glue.TableEncryption.CLIENT_SIDE_KMS, dataFormat: glue.DataFormat.JSON, }); - equal(table.encryption, glue.TableEncryption.CLIENT_SIDE_KMS); - notEqual(table.encryptionKey, undefined); - equal(table.bucket.encryptionKey, undefined); + expect(table.encryption).toEqual(glue.TableEncryption.CLIENT_SIDE_KMS); + expect(table.encryptionKey).not.toEqual(undefined); + expect(table.bucket.encryptionKey).toEqual(undefined); - cdkExpect(stack).to(haveResource('AWS::KMS::Key')); + Template.fromStack(stack).resourceCountIs('AWS::KMS::Key', 1); - cdkExpect(stack).to(haveResource('AWS::Glue::Table', { + Template.fromStack(stack).hasResourceProperties('AWS::Glue::Table', { CatalogId: { Ref: 'AWS::AccountId', }, @@ -654,7 +652,7 @@ test('encrypted table: CSE-KMS (implicitly created key)', () => { }, TableType: 'EXTERNAL_TABLE', }, - })); + }); }); @@ -678,15 +676,15 @@ test('encrypted table: CSE-KMS (explicitly created key)', () => { encryptionKey, dataFormat: glue.DataFormat.JSON, }); - equal(table.encryption, glue.TableEncryption.CLIENT_SIDE_KMS); - notEqual(table.encryptionKey, undefined); - equal(table.bucket.encryptionKey, undefined); + expect(table.encryption).toEqual(glue.TableEncryption.CLIENT_SIDE_KMS); + expect(table.encryptionKey).not.toEqual(undefined); + expect(table.bucket.encryptionKey).toEqual(undefined); - cdkExpect(stack).to(haveResource('AWS::KMS::Key', { + Template.fromStack(stack).hasResourceProperties('AWS::KMS::Key', { Description: 'MyKey', - })); + }); - cdkExpect(stack).to(haveResource('AWS::Glue::Table', { + Template.fromStack(stack).hasResourceProperties('AWS::Glue::Table', { CatalogId: { Ref: 'AWS::AccountId', }, @@ -729,7 +727,7 @@ test('encrypted table: CSE-KMS (explicitly created key)', () => { }, TableType: 'EXTERNAL_TABLE', }, - })); + }); }); @@ -755,15 +753,15 @@ test('encrypted table: CSE-KMS (explicitly passed bucket and key)', () => { encryptionKey, dataFormat: glue.DataFormat.JSON, }); - equal(table.encryption, glue.TableEncryption.CLIENT_SIDE_KMS); - notEqual(table.encryptionKey, undefined); - equal(table.bucket.encryptionKey, undefined); + expect(table.encryption).toEqual(glue.TableEncryption.CLIENT_SIDE_KMS); + expect(table.encryptionKey).not.toEqual(undefined); + expect(table.bucket.encryptionKey).toEqual(undefined); - cdkExpect(stack).to(haveResource('AWS::KMS::Key', { + Template.fromStack(stack).hasResourceProperties('AWS::KMS::Key', { Description: 'MyKey', - })); + }); - cdkExpect(stack).to(haveResource('AWS::Glue::Table', { + Template.fromStack(stack).hasResourceProperties('AWS::Glue::Table', { CatalogId: { Ref: 'AWS::AccountId', }, @@ -806,7 +804,7 @@ test('encrypted table: CSE-KMS (explicitly passed bucket and key)', () => { }, TableType: 'EXTERNAL_TABLE', }, - })); + }); }); @@ -831,7 +829,7 @@ test('explicit s3 bucket and prefix', () => { dataFormat: glue.DataFormat.JSON, }); - cdkExpect(stack).to(haveResource('AWS::Glue::Table', { + Template.fromStack(stack).hasResourceProperties('AWS::Glue::Table', { CatalogId: { Ref: 'AWS::AccountId', }, @@ -874,7 +872,7 @@ test('explicit s3 bucket and prefix', () => { }, TableType: 'EXTERNAL_TABLE', }, - })); + }); }); @@ -899,7 +897,7 @@ test('explicit s3 bucket and with empty prefix', () => { dataFormat: glue.DataFormat.JSON, }); - cdkExpect(stack).to(haveResource('AWS::Glue::Table', { + Template.fromStack(stack).hasResourceProperties('AWS::Glue::Table', { CatalogId: { Ref: 'AWS::AccountId', }, @@ -942,7 +940,7 @@ test('explicit s3 bucket and with empty prefix', () => { }, TableType: 'EXTERNAL_TABLE', }, - })); + }); }); @@ -966,7 +964,7 @@ test('grants: read only', () => { table.grantRead(user); - cdkExpect(stack).to(haveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -1048,7 +1046,7 @@ test('grants: read only', () => { Ref: 'User00B015A1', }, ], - })); + }); }); @@ -1072,7 +1070,7 @@ testFutureBehavior('grants: write only', s3GrantWriteCtx, cdk.App, (app) => { table.grantWrite(user); - cdkExpect(stack).to(haveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -1151,7 +1149,7 @@ testFutureBehavior('grants: write only', s3GrantWriteCtx, cdk.App, (app) => { Ref: 'User00B015A1', }, ], - })); + }); }); @@ -1175,7 +1173,7 @@ testFutureBehavior('grants: read and write', s3GrantWriteCtx, cdk.App, (app) => table.grantReadWrite(user); - cdkExpect(stack).to(haveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -1264,7 +1262,7 @@ testFutureBehavior('grants: read and write', s3GrantWriteCtx, cdk.App, (app) => Ref: 'User00B015A1', }, ], - })); + }); }); @@ -1346,7 +1344,7 @@ test('validate: can not specify an explicit bucket and encryption', () => { }); test('validate: can explicitly pass bucket if Encryption undefined', () => { - doesNotThrow(() => createTable({ + expect(() => createTable({ tableName: 'name', columns: [{ name: 'col1', @@ -1354,11 +1352,11 @@ test('validate: can explicitly pass bucket if Encryption undefined', () => { }], bucket: new s3.Bucket(new cdk.Stack(), 'Bucket'), encryption: undefined, - })); + })).not.toThrow(); }); test('validate: can explicitly pass bucket if Unencrypted', () => { - doesNotThrow(() => createTable({ + expect(() => createTable({ tableName: 'name', columns: [{ name: 'col1', @@ -1366,11 +1364,11 @@ test('validate: can explicitly pass bucket if Unencrypted', () => { }], bucket: new s3.Bucket(new cdk.Stack(), 'Bucket'), encryption: undefined, - })); + })).not.toThrow(); }); test('validate: can explicitly pass bucket if ClientSideKms', () => { - doesNotThrow(() => createTable({ + expect(() => createTable({ tableName: 'name', columns: [{ name: 'col1', @@ -1378,7 +1376,7 @@ test('validate: can explicitly pass bucket if ClientSideKms', () => { }], bucket: new s3.Bucket(new cdk.Stack(), 'Bucket'), encryption: glue.TableEncryption.CLIENT_SIDE_KMS, - })); + })).not.toThrow(); }); test('Table.fromTableArn', () => { @@ -1389,8 +1387,8 @@ test('Table.fromTableArn', () => { const table = glue.Table.fromTableArn(stack, 'boom', 'arn:aws:glue:us-east-1:123456789012:table/db1/tbl1'); // THEN - deepEqual(table.tableArn, 'arn:aws:glue:us-east-1:123456789012:table/db1/tbl1'); - deepEqual(table.tableName, 'tbl1'); + expect(table.tableArn).toEqual('arn:aws:glue:us-east-1:123456789012:table/db1/tbl1'); + expect(table.tableName).toEqual('tbl1'); }); function createTable(props: Pick>): void { diff --git a/packages/@aws-cdk/aws-ivs/package.json b/packages/@aws-cdk/aws-ivs/package.json index 31a2a63490f4d..b199d66182db2 100644 --- a/packages/@aws-cdk/aws-ivs/package.json +++ b/packages/@aws-cdk/aws-ivs/package.json @@ -85,12 +85,12 @@ }, "license": "Apache-2.0", "devDependencies": { + "@aws-cdk/assertions": "0.0.0", "@types/jest": "^26.0.24", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", - "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "pkglint": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-ivs/test/ivs.test.ts b/packages/@aws-cdk/aws-ivs/test/ivs.test.ts index 5f4f29e833df7..0e5efd63d5b2a 100644 --- a/packages/@aws-cdk/aws-ivs/test/ivs.test.ts +++ b/packages/@aws-cdk/aws-ivs/test/ivs.test.ts @@ -1,5 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; -import { expect as expectStack } from '@aws-cdk/assert-internal'; +import { Template } from '@aws-cdk/assertions'; import { Stack } from '@aws-cdk/core'; import * as ivs from '../lib'; @@ -13,7 +12,7 @@ test('channel default properties', () => { const stack = new Stack(); new ivs.Channel(stack, 'Channel'); - expectStack(stack).toMatch({ + Template.fromStack(stack).templateMatches({ Resources: { Channel4048F119: { Type: 'AWS::IVS::Channel', @@ -28,7 +27,7 @@ test('channel name', () => { name: 'CarrotsAreTasty', }); - expectStack(stack).toMatch({ + Template.fromStack(stack).templateMatches({ Resources: { Channel4048F119: { Type: 'AWS::IVS::Channel', @@ -46,7 +45,7 @@ test('channel is authorized', () => { authorized: true, }); - expectStack(stack).toMatch({ + Template.fromStack(stack).templateMatches({ Resources: { Channel4048F119: { Type: 'AWS::IVS::Channel', @@ -64,7 +63,7 @@ test('channel type', () => { type: ivs.ChannelType.BASIC, }); - expectStack(stack).toMatch({ + Template.fromStack(stack).templateMatches({ Resources: { Channel4048F119: { Type: 'AWS::IVS::Channel', @@ -82,7 +81,7 @@ test('channel latency mode', () => { latencyMode: ivs.LatencyMode.NORMAL, }); - expectStack(stack).toMatch({ + Template.fromStack(stack).templateMatches({ Resources: { Channel4048F119: { Type: 'AWS::IVS::Channel', @@ -115,7 +114,7 @@ test('playback key pair mandatory properties', () => { publicKeyMaterial: publicKey, }); - expectStack(stack).toMatch({ + Template.fromStack(stack).templateMatches({ Resources: { PlaybackKeyPairBE17315B: { Type: 'AWS::IVS::PlaybackKeyPair', @@ -134,7 +133,7 @@ test('playback key pair name', () => { name: 'CarrotsAreNutritious', }); - expectStack(stack).toMatch({ + Template.fromStack(stack).templateMatches({ Resources: { PlaybackKeyPairBE17315B: { Type: 'AWS::IVS::PlaybackKeyPair', @@ -162,7 +161,7 @@ test('stream key mandatory properties', () => { channel: ivs.Channel.fromChannelArn(stack, 'ChannelRef', 'arn:aws:ivs:us-west-2:123456789012:channel/abcdABCDefgh'), }); - expectStack(stack).toMatch({ + Template.fromStack(stack).templateMatches({ Resources: { StreamKey9F296F4F: { Type: 'AWS::IVS::StreamKey', @@ -179,7 +178,7 @@ test('channel and stream key.. at the same time', () => { const channel = new ivs.Channel(stack, 'Channel'); channel.addStreamKey('StreamKey'); - expectStack(stack).toMatch({ + Template.fromStack(stack).templateMatches({ Resources: { Channel4048F119: { Type: 'AWS::IVS::Channel', @@ -199,7 +198,7 @@ test('stream key from channel reference', () => { const channel = ivs.Channel.fromChannelArn(stack, 'Channel', 'arn:aws:ivs:us-west-2:123456789012:channel/abcdABCDefgh'); channel.addStreamKey('StreamKey'); - expectStack(stack).toMatch({ + Template.fromStack(stack).templateMatches({ Resources: { ChannelStreamKey60BDC2BE: { Type: 'AWS::IVS::StreamKey', diff --git a/packages/@aws-cdk/aws-kinesisanalytics-flink/package.json b/packages/@aws-cdk/aws-kinesisanalytics-flink/package.json index 02ffcb62439e7..d9ee895e0ed29 100644 --- a/packages/@aws-cdk/aws-kinesisanalytics-flink/package.json +++ b/packages/@aws-cdk/aws-kinesisanalytics-flink/package.json @@ -66,12 +66,12 @@ }, "license": "Apache-2.0", "devDependencies": { + "@aws-cdk/assertions": "0.0.0", "@types/jest": "^26.0.24", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "jest": "^26.6.3", - "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "pkglint": "0.0.0" }, "dependencies": { "@aws-cdk/assets": "0.0.0", diff --git a/packages/@aws-cdk/aws-kinesisanalytics-flink/test/application.test.ts b/packages/@aws-cdk/aws-kinesisanalytics-flink/test/application.test.ts index 09ccedef9bc83..a4546a5fa9423 100644 --- a/packages/@aws-cdk/aws-kinesisanalytics-flink/test/application.test.ts +++ b/packages/@aws-cdk/aws-kinesisanalytics-flink/test/application.test.ts @@ -1,10 +1,9 @@ -import { arrayWith, objectLike, ResourcePart } from '@aws-cdk/assert-internal'; -import '@aws-cdk/assert-internal/jest'; +import * as path from 'path'; +import { Match, Template } from '@aws-cdk/assertions'; import * as iam from '@aws-cdk/aws-iam'; import * as logs from '@aws-cdk/aws-logs'; import * as s3 from '@aws-cdk/aws-s3'; import * as core from '@aws-cdk/core'; -import * as path from 'path'; import * as flink from '../lib'; describe('Application', () => { @@ -31,7 +30,7 @@ describe('Application', () => { applicationName: 'MyFlinkApplication', }); - expect(stack).toHaveResource('AWS::KinesisAnalyticsV2::Application', { + Template.fromStack(stack).hasResourceProperties('AWS::KinesisAnalyticsV2::Application', { ApplicationName: 'MyFlinkApplication', RuntimeEnvironment: 'FLINK-1_11', ServiceExecutionRole: { @@ -56,11 +55,11 @@ describe('Application', () => { }, }); - expect(stack).toHaveResourceLike('AWS::KinesisAnalyticsV2::Application', { + Template.fromStack(stack).hasResource('AWS::KinesisAnalyticsV2::Application', { DeletionPolicy: 'Delete', - }, ResourcePart.CompleteDefinition); + }); - expect(stack).toHaveResource('AWS::IAM::Role', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Role', { AssumeRolePolicyDocument: { Statement: [{ Action: 'sts:AssumeRole', @@ -73,9 +72,9 @@ describe('Application', () => { }, }); - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { - Statement: arrayWith( + Statement: Match.arrayWith([ { Action: 'cloudwatch:PutMetricData', Effect: 'Allow', Resource: '*' }, { Action: 'logs:DescribeLogGroups', @@ -119,7 +118,7 @@ describe('Application', () => { ]], }, }, - ), + ]), }, }); }); @@ -132,7 +131,7 @@ describe('Application', () => { }), }); - expect(stack).toHaveResource('AWS::IAM::Role', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Role', { AssumeRolePolicyDocument: { Statement: [ { @@ -158,11 +157,11 @@ describe('Application', () => { resources: ['*'], })); - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { - Statement: arrayWith( - objectLike({ Action: 'custom:action', Effect: 'Allow', Resource: '*' }), - ), + Statement: Match.arrayWith([ + Match.objectLike({ Action: 'custom:action', Effect: 'Allow', Resource: '*' }), + ]), }, }); }); @@ -173,7 +172,7 @@ describe('Application', () => { runtime: flink.Runtime.of('custom'), }); - expect(stack).toHaveResourceLike('AWS::KinesisAnalyticsV2::Application', { + Template.fromStack(stack).hasResourceProperties('AWS::KinesisAnalyticsV2::Application', { RuntimeEnvironment: 'custom', }); }); @@ -184,9 +183,9 @@ describe('Application', () => { removalPolicy: core.RemovalPolicy.RETAIN, }); - expect(stack).toHaveResourceLike('AWS::KinesisAnalyticsV2::Application', { + Template.fromStack(stack).hasResource('AWS::KinesisAnalyticsV2::Application', { DeletionPolicy: 'Retain', - }, ResourcePart.CompleteDefinition); + }); }); test('granting permissions to resources', () => { @@ -197,12 +196,12 @@ describe('Application', () => { const dataBucket = new s3.Bucket(stack, 'DataBucket'); dataBucket.grantRead(app); - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Version: '2012-10-17', - Statement: arrayWith( - objectLike({ Action: ['s3:GetObject*', 's3:GetBucket*', 's3:List*'] }), - ), + Statement: Match.arrayWith([ + Match.objectLike({ Action: ['s3:GetObject*', 's3:GetBucket*', 's3:List*'] }), + ]), }, }); }); @@ -216,7 +215,7 @@ describe('Application', () => { const assetRef = 'AssetParameters8be9e0b5f53d41e9a3b1d51c9572c65f24f8170a7188d0ed57fb7d571de4d577S3BucketEBA17A67'; const versionKeyRef = 'AssetParameters8be9e0b5f53d41e9a3b1d51c9572c65f24f8170a7188d0ed57fb7d571de4d577S3VersionKey5922697E'; - expect(stack).toHaveResourceLike('AWS::KinesisAnalyticsV2::Application', { + Template.fromStack(stack).hasResourceProperties('AWS::KinesisAnalyticsV2::Application', { ApplicationConfiguration: { ApplicationCodeConfiguration: { CodeContent: { @@ -253,7 +252,7 @@ describe('Application', () => { }, }); - expect(stack).toHaveResourceLike('AWS::KinesisAnalyticsV2::Application', { + Template.fromStack(stack).hasResourceProperties('AWS::KinesisAnalyticsV2::Application', { ApplicationConfiguration: { EnvironmentProperties: { PropertyGroups: [ @@ -275,7 +274,7 @@ describe('Application', () => { checkpointingEnabled: false, }); - expect(stack).toHaveResourceLike('AWS::KinesisAnalyticsV2::Application', { + Template.fromStack(stack).hasResourceProperties('AWS::KinesisAnalyticsV2::Application', { ApplicationConfiguration: { FlinkApplicationConfiguration: { CheckpointConfiguration: { @@ -293,7 +292,7 @@ describe('Application', () => { checkpointInterval: core.Duration.minutes(5), }); - expect(stack).toHaveResourceLike('AWS::KinesisAnalyticsV2::Application', { + Template.fromStack(stack).hasResourceProperties('AWS::KinesisAnalyticsV2::Application', { ApplicationConfiguration: { FlinkApplicationConfiguration: { CheckpointConfiguration: { @@ -311,7 +310,7 @@ describe('Application', () => { minPauseBetweenCheckpoints: core.Duration.seconds(10), }); - expect(stack).toHaveResourceLike('AWS::KinesisAnalyticsV2::Application', { + Template.fromStack(stack).hasResourceProperties('AWS::KinesisAnalyticsV2::Application', { ApplicationConfiguration: { FlinkApplicationConfiguration: { CheckpointConfiguration: { @@ -329,7 +328,7 @@ describe('Application', () => { logLevel: flink.LogLevel.DEBUG, }); - expect(stack).toHaveResourceLike('AWS::KinesisAnalyticsV2::Application', { + Template.fromStack(stack).hasResourceProperties('AWS::KinesisAnalyticsV2::Application', { ApplicationConfiguration: { FlinkApplicationConfiguration: { MonitoringConfiguration: { @@ -347,7 +346,7 @@ describe('Application', () => { metricsLevel: flink.MetricsLevel.PARALLELISM, }); - expect(stack).toHaveResourceLike('AWS::KinesisAnalyticsV2::Application', { + Template.fromStack(stack).hasResourceProperties('AWS::KinesisAnalyticsV2::Application', { ApplicationConfiguration: { FlinkApplicationConfiguration: { MonitoringConfiguration: { @@ -365,7 +364,7 @@ describe('Application', () => { autoScalingEnabled: false, }); - expect(stack).toHaveResourceLike('AWS::KinesisAnalyticsV2::Application', { + Template.fromStack(stack).hasResourceProperties('AWS::KinesisAnalyticsV2::Application', { ApplicationConfiguration: { FlinkApplicationConfiguration: { ParallelismConfiguration: { @@ -383,7 +382,7 @@ describe('Application', () => { parallelism: 2, }); - expect(stack).toHaveResourceLike('AWS::KinesisAnalyticsV2::Application', { + Template.fromStack(stack).hasResourceProperties('AWS::KinesisAnalyticsV2::Application', { ApplicationConfiguration: { FlinkApplicationConfiguration: { ParallelismConfiguration: { @@ -401,7 +400,7 @@ describe('Application', () => { parallelismPerKpu: 2, }); - expect(stack).toHaveResourceLike('AWS::KinesisAnalyticsV2::Application', { + Template.fromStack(stack).hasResourceProperties('AWS::KinesisAnalyticsV2::Application', { ApplicationConfiguration: { FlinkApplicationConfiguration: { ParallelismConfiguration: { @@ -419,7 +418,7 @@ describe('Application', () => { snapshotsEnabled: false, }); - expect(stack).toHaveResourceLike('AWS::KinesisAnalyticsV2::Application', { + Template.fromStack(stack).hasResourceProperties('AWS::KinesisAnalyticsV2::Application', { ApplicationConfiguration: { ApplicationSnapshotConfiguration: { SnapshotsEnabled: false, @@ -434,7 +433,7 @@ describe('Application', () => { snapshotsEnabled: false, }); - expect(stack).toHaveResource('AWS::KinesisAnalyticsV2::ApplicationCloudWatchLoggingOption', { + Template.fromStack(stack).hasResourceProperties('AWS::KinesisAnalyticsV2::ApplicationCloudWatchLoggingOption', { ApplicationName: { Ref: 'FlinkApplicationC5836815', }, @@ -469,18 +468,18 @@ describe('Application', () => { }, }); - expect(stack).toHaveResource('AWS::Logs::LogGroup', { + Template.fromStack(stack).hasResource('AWS::Logs::LogGroup', { Properties: { RetentionInDays: 731, }, UpdateReplacePolicy: 'Retain', DeletionPolicy: 'Retain', - }, ResourcePart.CompleteDefinition); + }); - expect(stack).toHaveResource('AWS::Logs::LogStream', { + Template.fromStack(stack).hasResource('AWS::Logs::LogStream', { UpdateReplacePolicy: 'Retain', DeletionPolicy: 'Retain', - }, ResourcePart.CompleteDefinition); + }); }); test('logGroup setting', () => { @@ -491,7 +490,7 @@ describe('Application', () => { }), }); - expect(stack).toHaveResource('AWS::Logs::LogGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::Logs::LogGroup', { LogGroupName: 'custom', }); }); diff --git a/packages/@aws-cdk/aws-kinesisfirehose-destinations/package.json b/packages/@aws-cdk/aws-kinesisfirehose-destinations/package.json index 1d158b0d08d75..6633645989caf 100644 --- a/packages/@aws-cdk/aws-kinesisfirehose-destinations/package.json +++ b/packages/@aws-cdk/aws-kinesisfirehose-destinations/package.json @@ -71,13 +71,13 @@ }, "license": "Apache-2.0", "devDependencies": { + "@aws-cdk/assertions": "0.0.0", "@types/jest": "^26.0.24", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", "jest": "^26.6.3", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0", "@aws-cdk/aws-lambda": "0.0.0", "@aws-cdk/aws-lambda-nodejs": "0.0.0" }, diff --git a/packages/@aws-cdk/aws-kinesisfirehose-destinations/test/s3-bucket.test.ts b/packages/@aws-cdk/aws-kinesisfirehose-destinations/test/s3-bucket.test.ts index dce9a250cbd43..448d0b8efcf40 100644 --- a/packages/@aws-cdk/aws-kinesisfirehose-destinations/test/s3-bucket.test.ts +++ b/packages/@aws-cdk/aws-kinesisfirehose-destinations/test/s3-bucket.test.ts @@ -1,5 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; -import { ABSENT, MatchStyle, ResourcePart, anything, arrayWith } from '@aws-cdk/assert-internal'; +import { Match, Template } from '@aws-cdk/assertions'; import * as iam from '@aws-cdk/aws-iam'; import * as firehose from '@aws-cdk/aws-kinesisfirehose'; import * as kms from '@aws-cdk/aws-kms'; @@ -27,19 +26,17 @@ describe('S3 destination', () => { destinations: [new firehosedestinations.S3Bucket(bucket, { role: destinationRole })], }); - expect(stack).toHaveResource('AWS::KinesisFirehose::DeliveryStream', { + Template.fromStack(stack).hasResourceProperties('AWS::KinesisFirehose::DeliveryStream', { ExtendedS3DestinationConfiguration: { BucketARN: stack.resolve(bucket.bucketArn), CloudWatchLoggingOptions: { Enabled: true, - LogGroupName: anything(), - LogStreamName: anything(), }, RoleARN: stack.resolve(destinationRole.roleArn), }, }); - expect(stack).toHaveResource('AWS::Logs::LogGroup'); - expect(stack).toHaveResource('AWS::Logs::LogStream'); + Template.fromStack(stack).resourceCountIs('AWS::Logs::LogGroup', 1); + Template.fromStack(stack).resourceCountIs('AWS::Logs::LogStream', 1); }); it('creates a role when none is provided', () => { @@ -48,7 +45,7 @@ describe('S3 destination', () => { destinations: [new firehosedestinations.S3Bucket(bucket)], }); - expect(stack).toHaveResourceLike('AWS::KinesisFirehose::DeliveryStream', { + Template.fromStack(stack).hasResourceProperties('AWS::KinesisFirehose::DeliveryStream', { ExtendedS3DestinationConfiguration: { RoleARN: { 'Fn::GetAtt': [ @@ -58,11 +55,19 @@ describe('S3 destination', () => { }, }, }); - expect(stack).toMatchTemplate({ - ['DeliveryStreamS3DestinationRoleD96B8345']: { - Type: 'AWS::IAM::Role', + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Role', { + AssumeRolePolicyDocument: { + Statement: [ + { + Effect: 'Allow', + Principal: { + Service: 'firehose.amazonaws.com', + }, + Action: 'sts:AssumeRole', + }, + ], }, - }, MatchStyle.SUPERSET); + }); }); it('grants read/write access to the bucket', () => { @@ -72,10 +77,10 @@ describe('S3 destination', () => { destinations: [destination], }); - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { Roles: [stack.resolve(destinationRole.roleName)], PolicyDocument: { - Statement: [ + Statement: Match.arrayWith([ { Action: [ 's3:GetObject*', @@ -91,7 +96,7 @@ describe('S3 destination', () => { { 'Fn::Join': ['', [stack.resolve(bucket.bucketArn), '/*']] }, ], }, - ], + ]), }, }); }); @@ -103,7 +108,7 @@ describe('S3 destination', () => { destinations: [destination], }); - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyName: 'DestinationRoleDefaultPolicy1185C75D', Roles: [stack.resolve(destinationRole.roleName)], PolicyDocument: { @@ -134,9 +139,9 @@ describe('S3 destination', () => { ], }, }); - expect(stack).toHaveResourceLike('AWS::KinesisFirehose::DeliveryStream', { + Template.fromStack(stack).hasResource('AWS::KinesisFirehose::DeliveryStream', { DependsOn: ['DestinationRoleDefaultPolicy1185C75D'], - }, ResourcePart.CompleteDefinition); + }); }); describe('logging', () => { @@ -145,14 +150,12 @@ describe('S3 destination', () => { destinations: [new firehosedestinations.S3Bucket(bucket)], }); - expect(stack).toHaveResource('AWS::Logs::LogGroup'); - expect(stack).toHaveResource('AWS::Logs::LogStream'); - expect(stack).toHaveResourceLike('AWS::KinesisFirehose::DeliveryStream', { + Template.fromStack(stack).resourceCountIs('AWS::Logs::LogGroup', 1); + Template.fromStack(stack).resourceCountIs('AWS::Logs::LogStream', 1); + Template.fromStack(stack).hasResourceProperties('AWS::KinesisFirehose::DeliveryStream', { ExtendedS3DestinationConfiguration: { CloudWatchLoggingOptions: { Enabled: true, - LogGroupName: anything(), - LogStreamName: anything(), }, }, }); @@ -163,10 +166,10 @@ describe('S3 destination', () => { destinations: [new firehosedestinations.S3Bucket(bucket, { logging: false })], }); - expect(stack).not.toHaveResource('AWS::Logs::LogGroup'); - expect(stack).toHaveResourceLike('AWS::KinesisFirehose::DeliveryStream', { + Template.fromStack(stack).resourceCountIs('AWS::Logs::LogGroup', 0); + Template.fromStack(stack).hasResourceProperties('AWS::KinesisFirehose::DeliveryStream', { ExtendedS3DestinationConfiguration: { - CloudWatchLoggingOptions: ABSENT, + CloudWatchLoggingOptions: Match.absentProperty(), }, }); }); @@ -178,13 +181,12 @@ describe('S3 destination', () => { destinations: [new firehosedestinations.S3Bucket(bucket, { logGroup })], }); - expect(stack).toCountResources('AWS::Logs::LogGroup', 1); - expect(stack).toHaveResourceLike('AWS::KinesisFirehose::DeliveryStream', { + Template.fromStack(stack).resourceCountIs('AWS::Logs::LogGroup', 1); + Template.fromStack(stack).hasResourceProperties('AWS::KinesisFirehose::DeliveryStream', { ExtendedS3DestinationConfiguration: { CloudWatchLoggingOptions: { Enabled: true, LogGroupName: stack.resolve(logGroup.logGroupName), - LogStreamName: anything(), }, }, }); @@ -205,10 +207,10 @@ describe('S3 destination', () => { destinations: [new firehosedestinations.S3Bucket(bucket, { logGroup, role: destinationRole })], }); - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { Roles: [stack.resolve(destinationRole.roleName)], PolicyDocument: { - Statement: arrayWith( + Statement: Match.arrayWith([ { Action: [ 'logs:CreateLogStream', @@ -217,7 +219,7 @@ describe('S3 destination', () => { Effect: 'Allow', Resource: stack.resolve(logGroup.logGroupArn), }, - ), + ]), }, }); }); @@ -246,8 +248,8 @@ describe('S3 destination', () => { destinations: [destinationWithBasicLambdaProcessor], }); - expect(stack).toHaveResource('AWS::Lambda::Function'); - expect(stack).toHaveResourceLike('AWS::KinesisFirehose::DeliveryStream', { + Template.fromStack(stack).resourceCountIs('AWS::Lambda::Function', 1); + Template.fromStack(stack).hasResourceProperties('AWS::KinesisFirehose::DeliveryStream', { ExtendedS3DestinationConfiguration: { ProcessingConfiguration: { Enabled: true, @@ -283,8 +285,8 @@ describe('S3 destination', () => { destinations: [destination], }); - expect(stack).toHaveResource('AWS::Lambda::Function'); - expect(stack).toHaveResourceLike('AWS::KinesisFirehose::DeliveryStream', { + Template.fromStack(stack).resourceCountIs('AWS::Lambda::Function', 1); + Template.fromStack(stack).hasResourceProperties('AWS::KinesisFirehose::DeliveryStream', { ExtendedS3DestinationConfiguration: { ProcessingConfiguration: { Enabled: true, @@ -323,22 +325,22 @@ describe('S3 destination', () => { destinations: [destinationWithBasicLambdaProcessor], }); - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyName: 'DestinationRoleDefaultPolicy1185C75D', Roles: [stack.resolve(destinationRole.roleName)], PolicyDocument: { - Statement: arrayWith( + Statement: Match.arrayWith([ { Action: 'lambda:InvokeFunction', Effect: 'Allow', Resource: stack.resolve(lambdaFunction.functionArn), }, - ), + ]), }, }); - expect(stack).toHaveResourceLike('AWS::KinesisFirehose::DeliveryStream', { + Template.fromStack(stack).hasResource('AWS::KinesisFirehose::DeliveryStream', { DependsOn: ['DestinationRoleDefaultPolicy1185C75D'], - }, ResourcePart.CompleteDefinition); + }); }); }); @@ -351,7 +353,7 @@ describe('S3 destination', () => { destinations: [destination], }); - expect(stack).toHaveResourceLike('AWS::KinesisFirehose::DeliveryStream', { + Template.fromStack(stack).hasResourceProperties('AWS::KinesisFirehose::DeliveryStream', { ExtendedS3DestinationConfiguration: { CompressionFormat: 'GZIP', }, @@ -366,7 +368,7 @@ describe('S3 destination', () => { destinations: [destination], }); - expect(stack).toHaveResourceLike('AWS::KinesisFirehose::DeliveryStream', { + Template.fromStack(stack).hasResourceProperties('AWS::KinesisFirehose::DeliveryStream', { ExtendedS3DestinationConfiguration: { CompressionFormat: 'SNAZZY', }, @@ -383,7 +385,7 @@ describe('S3 destination', () => { })], }); - expect(stack).toHaveResourceLike('AWS::KinesisFirehose::DeliveryStream', { + Template.fromStack(stack).hasResourceProperties('AWS::KinesisFirehose::DeliveryStream', { ExtendedS3DestinationConfiguration: { BufferingHints: { IntervalInSeconds: 60, @@ -438,7 +440,7 @@ describe('S3 destination', () => { })], }); - expect(stack).toHaveResourceLike('AWS::KinesisFirehose::DeliveryStream', { + Template.fromStack(stack).hasResourceProperties('AWS::KinesisFirehose::DeliveryStream', { ExtendedS3DestinationConfiguration: { EncryptionConfiguration: { KMSEncryptionConfig: { @@ -459,10 +461,10 @@ describe('S3 destination', () => { })], }); - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { Roles: [stack.resolve(destinationRole.roleName)], PolicyDocument: { - Statement: arrayWith({ + Statement: Match.arrayWith([{ Action: [ 'kms:Decrypt', 'kms:Encrypt', @@ -471,7 +473,7 @@ describe('S3 destination', () => { ], Effect: 'Allow', Resource: stack.resolve(key.keyArn), - }), + }]), }, }); }); @@ -489,14 +491,11 @@ describe('S3 destination', () => { destinations: [destination], }); - expect(stack).toHaveResourceLike('AWS::KinesisFirehose::DeliveryStream', { + Template.fromStack(stack).hasResourceProperties('AWS::KinesisFirehose::DeliveryStream', { ExtendedS3DestinationConfiguration: { S3BackupConfiguration: { - BucketARN: anything(), CloudWatchLoggingOptions: { Enabled: true, - LogGroupName: anything(), - LogStreamName: anything(), }, RoleARN: stack.resolve(destinationRole.roleArn), }, @@ -517,14 +516,12 @@ describe('S3 destination', () => { destinations: [destination], }); - expect(stack).toHaveResourceLike('AWS::KinesisFirehose::DeliveryStream', { + Template.fromStack(stack).hasResourceProperties('AWS::KinesisFirehose::DeliveryStream', { ExtendedS3DestinationConfiguration: { S3BackupConfiguration: { BucketARN: stack.resolve(backupBucket.bucketArn), CloudWatchLoggingOptions: { Enabled: true, - LogGroupName: anything(), - LogStreamName: anything(), }, RoleARN: stack.resolve(destinationRole.roleArn), }, @@ -548,10 +545,10 @@ describe('S3 destination', () => { destinations: [destination], }); - expect(stack).toHaveResource('AWS::S3::Bucket', 1); - expect(stack).toHaveResourceLike('AWS::KinesisFirehose::DeliveryStream', { + Template.fromStack(stack).resourceCountIs('AWS::S3::Bucket', 1); + Template.fromStack(stack).hasResourceProperties('AWS::KinesisFirehose::DeliveryStream', { ExtendedS3DestinationConfiguration: { - S3BackupConfiguration: ABSENT, + S3BackupConfiguration: Match.absentProperty(), }, }); }); @@ -579,14 +576,13 @@ describe('S3 destination', () => { destinations: [destination], }); - expect(stack).toHaveResourceLike('AWS::KinesisFirehose::DeliveryStream', { + Template.fromStack(stack).hasResourceProperties('AWS::KinesisFirehose::DeliveryStream', { ExtendedS3DestinationConfiguration: { S3BackupConfiguration: { BucketARN: stack.resolve(backupBucket.bucketArn), CloudWatchLoggingOptions: { Enabled: true, LogGroupName: stack.resolve(logGroup.logGroupName), - LogStreamName: anything(), }, RoleARN: stack.resolve(destinationRole.roleArn), EncryptionConfiguration: { diff --git a/packages/@aws-cdk/aws-lambda-go/package.json b/packages/@aws-cdk/aws-lambda-go/package.json index 9f83f91c15963..5ab8238df938e 100644 --- a/packages/@aws-cdk/aws-lambda-go/package.json +++ b/packages/@aws-cdk/aws-lambda-go/package.json @@ -66,7 +66,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "@types/jest": "^26.0.24", "@aws-cdk/aws-ec2": "0.0.0", "cdk-build-tools": "0.0.0", diff --git a/packages/@aws-cdk/aws-lambda-go/test/function.test.ts b/packages/@aws-cdk/aws-lambda-go/test/function.test.ts index 0251a49ea498c..1feb0db637ade 100644 --- a/packages/@aws-cdk/aws-lambda-go/test/function.test.ts +++ b/packages/@aws-cdk/aws-lambda-go/test/function.test.ts @@ -1,5 +1,5 @@ -import '@aws-cdk/assert-internal/jest'; import * as path from 'path'; +import { Template } from '@aws-cdk/assertions'; import { Runtime } from '@aws-cdk/aws-lambda'; import { Stack } from '@aws-cdk/core'; import { GoFunction } from '../lib'; @@ -34,7 +34,7 @@ test('GoFunction with defaults', () => { entry: expect.stringMatching(/aws-lambda-go\/test\/lambda-handler-vendor\/cmd\/api$/), })); - expect(stack).toHaveResource('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Handler: 'bootstrap', Runtime: 'provided.al2', }); @@ -51,7 +51,7 @@ test('GoFunction with using provided runtime', () => { entry: expect.stringMatching(/aws-lambda-go\/test\/lambda-handler-vendor\/cmd\/api$/), })); - expect(stack).toHaveResource('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Handler: 'bootstrap', Runtime: 'provided', }); @@ -68,7 +68,7 @@ test('GoFunction with using golang runtime', () => { entry: expect.stringMatching(/aws-lambda-go\/test\/lambda-handler-vendor\/cmd\/api$/), })); - expect(stack).toHaveResource('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Handler: 'bootstrap', Runtime: 'go1.x', }); @@ -130,7 +130,7 @@ test('custom moduleDir can be used', () => { moduleDir: 'test/lambda-handler-vendor', }); - expect(stack).toHaveResource('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Handler: 'bootstrap', }); }); @@ -141,7 +141,7 @@ test('custom moduleDir with file path can be used', () => { moduleDir: 'test/lambda-handler-vendor/go.mod', }); - expect(stack).toHaveResource('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Handler: 'bootstrap', }); }); diff --git a/packages/@aws-cdk/aws-lambda-python/package.json b/packages/@aws-cdk/aws-lambda-python/package.json index 814ec44de6c69..72e5a12de703a 100644 --- a/packages/@aws-cdk/aws-lambda-python/package.json +++ b/packages/@aws-cdk/aws-lambda-python/package.json @@ -64,11 +64,11 @@ }, "license": "Apache-2.0", "devDependencies": { + "@aws-cdk/assertions": "0.0.0", "@types/jest": "^26.0.24", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", - "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "pkglint": "0.0.0" }, "dependencies": { "@aws-cdk/aws-lambda": "0.0.0", diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.test.ts b/packages/@aws-cdk/aws-lambda-python/test/function.test.ts index a6bc4778e14f2..0eda2a419e97c 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.test.ts +++ b/packages/@aws-cdk/aws-lambda-python/test/function.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import { Code, Runtime } from '@aws-cdk/aws-lambda'; import { AssetHashType, AssetOptions, Stack } from '@aws-cdk/core'; import { PythonFunction } from '../lib'; @@ -52,7 +52,7 @@ test('PythonFunction with defaults', () => { outputPathSuffix: '.', })); - expect(stack).toHaveResource('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Handler: 'index.handler', }); }); @@ -69,7 +69,7 @@ test('PythonFunction with index in a subdirectory', () => { outputPathSuffix: '.', })); - expect(stack).toHaveResource('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Handler: 'inner/custom_index.custom_handler', }); }); @@ -122,21 +122,21 @@ test('allows specifying hash type', () => { assetHash: 'MY_CUSTOM_HASH', }); - expect(stack).toHaveResource('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Code: { S3Bucket: 'mock-bucket-name', S3Key: 'SOURCE_MOCK', }, }); - expect(stack).toHaveResource('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Code: { S3Bucket: 'mock-bucket-name', S3Key: 'OUTPUT_MOCK', }, }); - expect(stack).toHaveResource('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Code: { S3Bucket: 'mock-bucket-name', S3Key: 'MY_CUSTOM_HASH', diff --git a/packages/@aws-cdk/aws-lambda-python/test/layer.test.ts b/packages/@aws-cdk/aws-lambda-python/test/layer.test.ts index ff828301ee7f3..4f0199878a205 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/layer.test.ts +++ b/packages/@aws-cdk/aws-lambda-python/test/layer.test.ts @@ -1,4 +1,3 @@ -import '@aws-cdk/assert-internal/jest'; import * as path from 'path'; import { Runtime } from '@aws-cdk/aws-lambda'; import { Stack } from '@aws-cdk/core'; diff --git a/packages/@aws-cdk/aws-msk/package.json b/packages/@aws-cdk/aws-msk/package.json index 7309920e959ac..dd1523cffaf01 100644 --- a/packages/@aws-cdk/aws-msk/package.json +++ b/packages/@aws-cdk/aws-msk/package.json @@ -75,13 +75,13 @@ }, "license": "Apache-2.0", "devDependencies": { + "@aws-cdk/assertions": "0.0.0", "@types/jest": "^26.0.24", "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "cdk-integ-tools": "0.0.0", "pkglint": "0.0.0", - "jest": "^26.6.3", - "@aws-cdk/assert-internal": "0.0.0" + "jest": "^26.6.3" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-msk/test/cluster.test.ts b/packages/@aws-cdk/aws-msk/test/cluster.test.ts index 86b15c099f2a5..a990895e16d9c 100644 --- a/packages/@aws-cdk/aws-msk/test/cluster.test.ts +++ b/packages/@aws-cdk/aws-msk/test/cluster.test.ts @@ -1,6 +1,4 @@ -import { ResourcePart, SynthUtils } from '@aws-cdk/assert-internal'; -import '@aws-cdk/assert-internal/jest'; - +import { Template } from '@aws-cdk/assertions'; import * as acmpca from '@aws-cdk/aws-acmpca'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as kms from '@aws-cdk/aws-kms'; @@ -26,32 +24,31 @@ describe('MSK Cluster', () => { vpc, }); - expect(stack).toHaveResourceLike( + Template.fromStack(stack).hasResource( 'AWS::MSK::Cluster', { DeletionPolicy: 'Retain', UpdateReplacePolicy: 'Retain', }, - ResourcePart.CompleteDefinition, ); - expect(stack).toHaveResourceLike('AWS::MSK::Cluster', { + Template.fromStack(stack).hasResourceProperties('AWS::MSK::Cluster', { KafkaVersion: '2.6.1', }); - expect(stack).toHaveResourceLike('AWS::MSK::Cluster', { + Template.fromStack(stack).hasResourceProperties('AWS::MSK::Cluster', { EncryptionInfo: { EncryptionInTransit: { ClientBroker: 'TLS', InCluster: true }, }, }); - expect(stack).toHaveResourceLike('AWS::MSK::Cluster', { + Template.fromStack(stack).hasResourceProperties('AWS::MSK::Cluster', { NumberOfBrokerNodes: 2, }); - expect(stack).toHaveResourceLike('AWS::MSK::Cluster', { + Template.fromStack(stack).hasResourceProperties('AWS::MSK::Cluster', { BrokerNodeGroupInfo: { StorageInfo: { EBSStorageInfo: { VolumeSize: 1000 } }, }, }); - expect(stack).toHaveResource('AWS::EC2::SecurityGroup'); - expect(stack).toHaveResourceLike('AWS::MSK::Cluster', { + Template.fromStack(stack).resourceCountIs('AWS::EC2::SecurityGroup', 1); + Template.fromStack(stack).hasResourceProperties('AWS::MSK::Cluster', { BrokerNodeGroupInfo: { SecurityGroups: [ { @@ -141,7 +138,7 @@ describe('MSK Cluster', () => { iam: true, }), }); - expect(stack).toHaveResourceLike('AWS::MSK::Cluster', { + Template.fromStack(stack).hasResourceProperties('AWS::MSK::Cluster', { ClientAuthentication: { Sasl: { Iam: { Enabled: true } }, }, @@ -202,13 +199,13 @@ describe('MSK Cluster', () => { }); test('with alias msk/${clusterName}/sasl/scram', () => { - expect(stack).toHaveResourceLike('AWS::KMS::Alias', { + Template.fromStack(stack).hasResourceProperties('AWS::KMS::Alias', { AliasName: 'alias/msk/cluster/sasl/scram', }); }); test('with a policy allowing the secrets manager service to use the key', () => { - expect(stack).toHaveResourceLike('AWS::KMS::Key', { + Template.fromStack(stack).hasResourceProperties('AWS::KMS::Key', { KeyPolicy: { Statement: [ { @@ -281,6 +278,7 @@ describe('MSK Cluster', () => { Effect: 'Allow', Principal: { AWS: '*' }, Resource: '*', + Sid: 'Allow access through AWS Secrets Manager for all principals in the account that are authorized to use AWS Secrets Manager', }, ], }, @@ -319,7 +317,7 @@ describe('MSK Cluster', () => { ), }); - expect(stack).toHaveResourceLike('AWS::MSK::Cluster', { + Template.fromStack(stack).hasResourceProperties('AWS::MSK::Cluster', { BrokerNodeGroupInfo: { InstanceType: 'kafka.m5.xlarge' }, }); }); @@ -336,7 +334,7 @@ describe('MSK Cluster', () => { ), }); - expect(stack).toHaveResourceLike('AWS::MSK::Cluster', { + Template.fromStack(stack).hasResourceProperties('AWS::MSK::Cluster', { BrokerNodeGroupInfo: { InstanceType: 'kafka.m5.xlarge' }, }); }); @@ -352,7 +350,7 @@ describe('MSK Cluster', () => { }, }); - expect(stack).toHaveResourceLike('AWS::MSK::Cluster', { + Template.fromStack(stack).hasResourceProperties('AWS::MSK::Cluster', { LoggingInfo: { BrokerLogs: { CloudWatchLogs: { @@ -376,7 +374,7 @@ describe('MSK Cluster', () => { }, }); - expect(stack).toHaveResourceLike('AWS::MSK::Cluster', { + Template.fromStack(stack).hasResourceProperties('AWS::MSK::Cluster', { LoggingInfo: { BrokerLogs: { S3: { @@ -400,7 +398,7 @@ describe('MSK Cluster', () => { }, }); - expect(stack).toHaveResourceLike('AWS::MSK::Cluster', { + Template.fromStack(stack).hasResourceProperties('AWS::MSK::Cluster', { LoggingInfo: { BrokerLogs: { Firehose: { @@ -445,7 +443,7 @@ describe('MSK Cluster', () => { ebsStorageInfo: { encryptionKey: new kms.Key(stack, 'Key') }, }); - expect(stack).toHaveResourceLike('AWS::MSK::Cluster', { + Template.fromStack(stack).hasResourceProperties('AWS::MSK::Cluster', { EncryptionInfo: { EncryptionAtRest: { DataVolumeKMSKeyId: { @@ -526,7 +524,7 @@ describe('MSK Cluster', () => { ); // THEN - expect(SynthUtils.toCloudFormation(stack)).toMatchSnapshot(); + expect(Template.fromStack(stack)).toMatchSnapshot(); }); describe('when creating sasl/scram users', () => { @@ -555,7 +553,7 @@ describe('MSK Cluster', () => { const username = 'my-user'; cluster.addUser(username); - expect(stack).toHaveResourceLike('AWS::SecretsManager::Secret', { + Template.fromStack(stack).hasResourceProperties('AWS::SecretsManager::Secret', { 'Name': { 'Fn::Join': [ '', diff --git a/packages/@aws-cdk/aws-redshift/package.json b/packages/@aws-cdk/aws-redshift/package.json index 5ccccb2f4f2df..3bf492f83ee7b 100644 --- a/packages/@aws-cdk/aws-redshift/package.json +++ b/packages/@aws-cdk/aws-redshift/package.json @@ -73,12 +73,12 @@ }, "license": "Apache-2.0", "devDependencies": { + "@aws-cdk/assertions": "0.0.0", "@types/jest": "^26.0.24", "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "jest": "^26.6.3", - "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "pkglint": "0.0.0" }, "dependencies": { "@aws-cdk/aws-ec2": "0.0.0", diff --git a/packages/@aws-cdk/aws-redshift/test/cluster.test.ts b/packages/@aws-cdk/aws-redshift/test/cluster.test.ts index 7731320e8756c..28f2fbfd4655b 100644 --- a/packages/@aws-cdk/aws-redshift/test/cluster.test.ts +++ b/packages/@aws-cdk/aws-redshift/test/cluster.test.ts @@ -1,5 +1,4 @@ -import { ABSENT, expect as cdkExpect, haveResource, ResourcePart } from '@aws-cdk/assert-internal'; -import '@aws-cdk/assert-internal/jest'; +import { Match, Template } from '@aws-cdk/assertions'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as kms from '@aws-cdk/aws-kms'; import * as s3 from '@aws-cdk/aws-s3'; @@ -25,7 +24,7 @@ test('check that instantiation works', () => { }); // THEN - cdkExpect(stack).to(haveResource('AWS::Redshift::Cluster', { + Template.fromStack(stack).hasResource('AWS::Redshift::Cluster', { Properties: { AllowVersionUpgrade: true, MasterUsername: 'admin', @@ -42,9 +41,9 @@ test('check that instantiation works', () => { }, DeletionPolicy: 'Retain', UpdateReplacePolicy: 'Retain', - }, ResourcePart.CompleteDefinition)); + }); - cdkExpect(stack).to(haveResource('AWS::Redshift::ClusterSubnetGroup', { + Template.fromStack(stack).hasResource('AWS::Redshift::ClusterSubnetGroup', { Properties: { Description: 'Subnets for Redshift Redshift cluster', SubnetIds: [ @@ -55,7 +54,7 @@ test('check that instantiation works', () => { }, DeletionPolicy: 'Retain', UpdateReplacePolicy: 'Retain', - }, ResourcePart.CompleteDefinition)); + }); }); test('can create a cluster with imported vpc and security group', () => { @@ -76,12 +75,12 @@ test('can create a cluster with imported vpc and security group', () => { }); // THEN - cdkExpect(stack).to(haveResource('AWS::Redshift::Cluster', { + Template.fromStack(stack).hasResourceProperties('AWS::Redshift::Cluster', { ClusterSubnetGroupName: { Ref: 'RedshiftSubnetsDFE70E0A' }, MasterUsername: 'admin', MasterUserPassword: 'tooshort', VpcSecurityGroupIds: ['SecurityGroupId12345'], - })); + }); }); test('creates a secret when master credentials are not specified', () => { @@ -94,7 +93,7 @@ test('creates a secret when master credentials are not specified', () => { }); // THEN - cdkExpect(stack).to(haveResource('AWS::Redshift::Cluster', { + Template.fromStack(stack).hasResourceProperties('AWS::Redshift::Cluster', { MasterUsername: { 'Fn::Join': [ '', @@ -119,16 +118,16 @@ test('creates a secret when master credentials are not specified', () => { ], ], }, - })); + }); - cdkExpect(stack).to(haveResource('AWS::SecretsManager::Secret', { + Template.fromStack(stack).hasResourceProperties('AWS::SecretsManager::Secret', { GenerateSecretString: { ExcludeCharacters: '"@/\\\ \'', GenerateStringKey: 'password', PasswordLength: 30, SecretStringTemplate: '{"username":"admin"}', }, - })); + }); }); describe('node count', () => { @@ -144,10 +143,10 @@ describe('node count', () => { }); // THEN - cdkExpect(stack).to(haveResource('AWS::Redshift::Cluster', { + Template.fromStack(stack).hasResourceProperties('AWS::Redshift::Cluster', { ClusterType: 'single-node', - NumberOfNodes: ABSENT, - })); + NumberOfNodes: Match.absentProperty(), + }); }); test('Single Node Clusters treat 1 node as undefined', () => { @@ -162,10 +161,10 @@ describe('node count', () => { }); // THEN - cdkExpect(stack).to(haveResource('AWS::Redshift::Cluster', { + Template.fromStack(stack).hasResourceProperties('AWS::Redshift::Cluster', { ClusterType: 'single-node', - NumberOfNodes: ABSENT, - })); + NumberOfNodes: Match.absentProperty(), + }); }); test('Single Node Clusters throw if any other node count is specified', () => { @@ -192,10 +191,10 @@ describe('node count', () => { }); // THEN - cdkExpect(stack).to(haveResource('AWS::Redshift::Cluster', { + Template.fromStack(stack).hasResourceProperties('AWS::Redshift::Cluster', { ClusterType: 'multi-node', NumberOfNodes: 2, - })); + }); }); test.each([0, 1, -1, 101])('Multi-Node Clusters throw with %s nodes', (numberOfNodes: number) => { @@ -227,12 +226,12 @@ describe('node count', () => { }); // THEN - cdkExpect(stack).to(haveResource('AWS::Redshift::Cluster', { + Template.fromStack(stack).hasResourceProperties('AWS::Redshift::Cluster', { ClusterType: 'multi-node', NumberOfNodes: { Ref: 'numberOfNodes', }, - })); + }); }); }); @@ -247,14 +246,14 @@ test('create an encrypted cluster with custom KMS key', () => { }); // THEN - cdkExpect(stack).to(haveResource('AWS::Redshift::Cluster', { + Template.fromStack(stack).hasResourceProperties('AWS::Redshift::Cluster', { KmsKeyId: { 'Fn::GetAtt': [ 'Key961B73FD', 'Arn', ], }, - })); + }); }); test('cluster with parameter group', () => { @@ -275,9 +274,9 @@ test('cluster with parameter group', () => { }); // THEN - cdkExpect(stack).to(haveResource('AWS::Redshift::Cluster', { + Template.fromStack(stack).hasResourceProperties('AWS::Redshift::Cluster', { ClusterParameterGroupName: { Ref: 'ParamsA8366201' }, - })); + }); }); @@ -292,9 +291,9 @@ test('publicly accessible cluster', () => { }); // THEN - cdkExpect(stack).to(haveResource('AWS::Redshift::Cluster', { + Template.fromStack(stack).hasResourceProperties('AWS::Redshift::Cluster', { PubliclyAccessible: true, - })); + }); }); test('imported cluster with imported security group honors allowAllOutbound', () => { @@ -314,9 +313,9 @@ test('imported cluster with imported security group honors allowAllOutbound', () cluster.connections.allowToAnyIpv4(ec2.Port.tcp(443)); // THEN - cdkExpect(stack).to(haveResource('AWS::EC2::SecurityGroupEgress', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupEgress', { GroupId: 'sg-123456789', - })); + }); }); test('can create a cluster with logging enabled', () => { @@ -334,12 +333,12 @@ test('can create a cluster with logging enabled', () => { }); // THEN - cdkExpect(stack).to(haveResource('AWS::Redshift::Cluster', { + Template.fromStack(stack).hasResourceProperties('AWS::Redshift::Cluster', { LoggingProperties: { BucketName: 'logging-bucket', S3KeyPrefix: 'prefix', }, - })); + }); }); test('throws when trying to add rotation to a cluster without secret', () => { @@ -408,8 +407,8 @@ test('can use existing cluster subnet group', () => { subnetGroup: ClusterSubnetGroup.fromClusterSubnetGroupName(stack, 'Group', 'my-existing-cluster-subnet-group'), }); - expect(stack).not.toHaveResource('AWS::Redshift::ClusterSubnetGroup'); - expect(stack).toHaveResourceLike('AWS::Redshift::Cluster', { + Template.fromStack(stack).resourceCountIs('AWS::Redshift::ClusterSubnetGroup', 0); + Template.fromStack(stack).hasResourceProperties('AWS::Redshift::Cluster', { ClusterSubnetGroupName: 'my-existing-cluster-subnet-group', }); }); diff --git a/packages/@aws-cdk/aws-redshift/test/parameter-group.test.ts b/packages/@aws-cdk/aws-redshift/test/parameter-group.test.ts index c49708b8eb557..1853fc0f5baf5 100644 --- a/packages/@aws-cdk/aws-redshift/test/parameter-group.test.ts +++ b/packages/@aws-cdk/aws-redshift/test/parameter-group.test.ts @@ -1,4 +1,4 @@ -import { expect as cdkExpect, haveResource } from '@aws-cdk/assert-internal'; +import { Template } from '@aws-cdk/assertions'; import * as cdk from '@aws-cdk/core'; import { ClusterParameterGroup } from '../lib'; @@ -15,7 +15,7 @@ test('create a cluster parameter group', () => { }); // THEN - cdkExpect(stack).to(haveResource('AWS::Redshift::ClusterParameterGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::Redshift::ClusterParameterGroup', { Description: 'desc', ParameterGroupFamily: 'redshift-1.0', Parameters: [ @@ -24,6 +24,6 @@ test('create a cluster parameter group', () => { ParameterValue: 'value', }, ], - })); + }); }); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-redshift/test/subnet-group.test.ts b/packages/@aws-cdk/aws-redshift/test/subnet-group.test.ts index c27a4998ce76e..0fb5c6b17f21d 100644 --- a/packages/@aws-cdk/aws-redshift/test/subnet-group.test.ts +++ b/packages/@aws-cdk/aws-redshift/test/subnet-group.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as ec2 from '@aws-cdk/aws-ec2'; import { Stack } from '@aws-cdk/core'; import { ClusterSubnetGroup } from '../lib'; @@ -17,7 +17,7 @@ test('creates a subnet group from minimal properties', () => { vpc, }); - expect(stack).toHaveResource('AWS::Redshift::ClusterSubnetGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::Redshift::ClusterSubnetGroup', { Description: 'MyGroup', SubnetIds: [ { Ref: 'VPCPrivateSubnet1Subnet8BCA10E0' }, @@ -33,7 +33,7 @@ describe('subnet selection', () => { vpc, }); - expect(stack).toHaveResource('AWS::Redshift::ClusterSubnetGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::Redshift::ClusterSubnetGroup', { Description: 'MyGroup', SubnetIds: [ { Ref: 'VPCPrivateSubnet1Subnet8BCA10E0' }, @@ -49,7 +49,7 @@ describe('subnet selection', () => { vpcSubnets: { subnetType: ec2.SubnetType.PUBLIC }, }); - expect(stack).toHaveResource('AWS::Redshift::ClusterSubnetGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::Redshift::ClusterSubnetGroup', { Description: 'MyGroup', SubnetIds: [ { Ref: 'VPCPublicSubnet1SubnetB4246D30' }, diff --git a/packages/@aws-cdk/aws-sam/package.json b/packages/@aws-cdk/aws-sam/package.json index 0fa097ffba069..9083b5b5d83bf 100644 --- a/packages/@aws-cdk/aws-sam/package.json +++ b/packages/@aws-cdk/aws-sam/package.json @@ -80,7 +80,7 @@ "jest": "^26.6.3", "pkglint": "0.0.0", "ts-jest": "^26.5.6", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-sam/test/api.test.ts b/packages/@aws-cdk/aws-sam/test/api.test.ts index bed8a90ae4e57..6b2fd6853ba8a 100644 --- a/packages/@aws-cdk/aws-sam/test/api.test.ts +++ b/packages/@aws-cdk/aws-sam/test/api.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as cdk from '@aws-cdk/core'; import * as sam from '../lib'; @@ -19,7 +19,7 @@ describe('AWS::Serverless::Api', () => { }, }); - expect(stack).toHaveResourceLike('AWS::Serverless::Api', { + Template.fromStack(stack).hasResourceProperties('AWS::Serverless::Api', { StageName: 'prod', EndpointConfiguration: { Type: 'GLOBAL', @@ -36,7 +36,7 @@ describe('AWS::Serverless::Api', () => { endpointConfiguration: 'GLOBAL', }); - expect(stack).toHaveResourceLike('AWS::Serverless::Api', { + Template.fromStack(stack).hasResourceProperties('AWS::Serverless::Api', { StageName: 'prod', EndpointConfiguration: 'GLOBAL', }); diff --git a/packages/@aws-cdk/aws-sam/test/application.test.ts b/packages/@aws-cdk/aws-sam/test/application.test.ts index 748eaf75732e9..5ba6e59a186ed 100644 --- a/packages/@aws-cdk/aws-sam/test/application.test.ts +++ b/packages/@aws-cdk/aws-sam/test/application.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as cdk from '@aws-cdk/core'; import { CfnApplication } from '../lib'; @@ -16,7 +16,7 @@ test('construct an AWS::Serverless::Application', () => { }, }); - expect(stack).toMatchTemplate({ + Template.fromStack(stack).templateMatches({ Transform: 'AWS::Serverless-2016-10-31', Resources: { App: { diff --git a/packages/@aws-cdk/aws-sam/test/function.test.ts b/packages/@aws-cdk/aws-sam/test/function.test.ts index 2633c1ea46af3..889e3366549ec 100644 --- a/packages/@aws-cdk/aws-sam/test/function.test.ts +++ b/packages/@aws-cdk/aws-sam/test/function.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as cdk from '@aws-cdk/core'; import * as sam from '../lib'; @@ -15,7 +15,7 @@ test("correctly chooses a string array from the type unions of the 'policies' pr policies: ['AWSLambdaExecute'], }); - expect(stack).toHaveResourceLike('AWS::Serverless::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Serverless::Function', { CodeUri: { Bucket: 'my-bucket', Key: 'my-key', diff --git a/packages/@aws-cdk/aws-servicecatalog/package.json b/packages/@aws-cdk/aws-servicecatalog/package.json index 442fdbe8eb5c8..bc482eedff82e 100644 --- a/packages/@aws-cdk/aws-servicecatalog/package.json +++ b/packages/@aws-cdk/aws-servicecatalog/package.json @@ -73,12 +73,12 @@ }, "license": "Apache-2.0", "devDependencies": { + "@aws-cdk/assertions": "0.0.0", "@types/jest": "^26.0.24", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", - "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "pkglint": "0.0.0" }, "dependencies": { "@aws-cdk/aws-iam": "0.0.0", diff --git a/packages/@aws-cdk/aws-servicecatalog/test/portfolio.test.ts b/packages/@aws-cdk/aws-servicecatalog/test/portfolio.test.ts index bf6ef2c09b0ed..216c34295cab2 100644 --- a/packages/@aws-cdk/aws-servicecatalog/test/portfolio.test.ts +++ b/packages/@aws-cdk/aws-servicecatalog/test/portfolio.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as iam from '@aws-cdk/aws-iam'; import * as sns from '@aws-cdk/aws-sns'; import * as cdk from '@aws-cdk/core'; @@ -18,7 +18,7 @@ describe('Portfolio', () => { providerName: 'testProvider', }); - expect(stack).toMatchTemplate({ + Template.fromStack(stack).templateMatches({ Resources: { MyPortfolio59CCA9C9: { Type: 'AWS::ServiceCatalog::Portfolio', @@ -39,7 +39,7 @@ describe('Portfolio', () => { messageLanguage: servicecatalog.MessageLanguage.ZH, }); - expect(stack).toHaveResourceLike('AWS::ServiceCatalog::Portfolio', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceCatalog::Portfolio', { Description: 'test portfolio description', AcceptLanguage: servicecatalog.MessageLanguage.ZH, }); @@ -105,7 +105,7 @@ describe('Portfolio', () => { description: tokenDescription.valueAsString, }); - expect(stack).toHaveResourceLike('AWS::ServiceCatalog::Portfolio', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceCatalog::Portfolio', { Description: { Ref: 'Description', }, @@ -120,7 +120,7 @@ describe('Portfolio', () => { providerName: 'testProvider', }); - expect(stack).toHaveResourceLike('AWS::ServiceCatalog::Portfolio', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceCatalog::Portfolio', { DisplayName: { Ref: 'DisplayName', }, @@ -135,7 +135,7 @@ describe('Portfolio', () => { providerName: tokenProviderName.valueAsString, }); - expect(stack).toHaveResourceLike('AWS::ServiceCatalog::Portfolio', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceCatalog::Portfolio', { ProviderName: { Ref: 'ProviderName', }, @@ -157,7 +157,7 @@ describe('Portfolio', () => { cdk.Tags.of(portfolio).add('myTestKey1', 'myTestKeyValue1'); cdk.Tags.of(portfolio).add('myTestKey2', 'myTestKeyValue2'); - expect(stack).toHaveResourceLike('AWS::ServiceCatalog::Portfolio', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceCatalog::Portfolio', { Tags: [ { Key: 'myTestKey1', @@ -176,7 +176,7 @@ describe('Portfolio', () => { portfolio.shareWithAccount(shareAccountId); - expect(stack).toHaveResourceLike('AWS::ServiceCatalog::PortfolioShare', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceCatalog::PortfolioShare', { AccountId: shareAccountId, }); }), @@ -189,7 +189,7 @@ describe('Portfolio', () => { messageLanguage: servicecatalog.MessageLanguage.EN, }); - expect(stack).toHaveResourceLike('AWS::ServiceCatalog::PortfolioShare', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceCatalog::PortfolioShare', { AccountId: shareAccountId, ShareTagOptions: true, AcceptLanguage: 'en', @@ -201,7 +201,7 @@ describe('Portfolio', () => { portfolio.shareWithAccount(shareAccountId, { shareTagOptions: false }); - expect(stack).toHaveResourceLike('AWS::ServiceCatalog::PortfolioShare', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceCatalog::PortfolioShare', { AccountId: shareAccountId, ShareTagOptions: false, }); @@ -212,7 +212,7 @@ describe('Portfolio', () => { portfolio.shareWithAccount(shareAccountId); - expect(stack).toHaveResourceLike('AWS::ServiceCatalog::PortfolioShare', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceCatalog::PortfolioShare', { AccountId: shareAccountId, }); }), @@ -224,7 +224,7 @@ describe('Portfolio', () => { portfolio.giveAccessToRole(role); - expect(stack).toHaveResourceLike('AWS::ServiceCatalog::PortfolioPrincipalAssociation', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceCatalog::PortfolioPrincipalAssociation', { PrincipalARN: { 'Fn::GetAtt': ['TestRole6C9272DF', 'Arn'] }, }); }), @@ -234,7 +234,7 @@ describe('Portfolio', () => { portfolio.giveAccessToUser(user); - expect(stack).toHaveResourceLike('AWS::ServiceCatalog::PortfolioPrincipalAssociation', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceCatalog::PortfolioPrincipalAssociation', { PrincipalARN: { 'Fn::GetAtt': ['TestUser6A619381', 'Arn'] }, }); }), @@ -244,7 +244,7 @@ describe('Portfolio', () => { portfolio.giveAccessToGroup(group); - expect(stack).toHaveResourceLike('AWS::ServiceCatalog::PortfolioPrincipalAssociation', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceCatalog::PortfolioPrincipalAssociation', { PrincipalARN: { 'Fn::GetAtt': ['TestGroupAF88660E', 'Arn'] }, }); }), @@ -288,14 +288,14 @@ describe('portfolio associations and product constraints', () => { test('basic portfolio product association', () => { portfolio.addProduct(product); - expect(stack).toHaveResource('AWS::ServiceCatalog::PortfolioProductAssociation'); + Template.fromStack(stack).resourceCountIs('AWS::ServiceCatalog::PortfolioProductAssociation', 1); }); test('portfolio product associations are idempotent', () => { portfolio.addProduct(product); portfolio.addProduct(product); // If not idempotent these calls should fail - expect(stack).toCountResources('AWS::ServiceCatalog::PortfolioProductAssociation', 1); //check anyway + Template.fromStack(stack).resourceCountIs('AWS::ServiceCatalog::PortfolioProductAssociation', 1); //check anyway }), test('add tag options to portfolio', () => { @@ -306,8 +306,8 @@ describe('portfolio associations and product constraints', () => { portfolio.associateTagOptions(tagOptions); - expect(stack).toCountResources('AWS::ServiceCatalog::TagOption', 3); //Generates a resource for each unique key-value pair - expect(stack).toHaveResource('AWS::ServiceCatalog::TagOptionAssociation'); + Template.fromStack(stack).resourceCountIs('AWS::ServiceCatalog::TagOption', 3); //Generates a resource for each unique key-value pair + Template.fromStack(stack).resourceCountIs('AWS::ServiceCatalog::TagOptionAssociation', 3); }), test('add tag options to portfolio as prop', () => { @@ -322,8 +322,8 @@ describe('portfolio associations and product constraints', () => { tagOptions: tagOptions, }); - expect(stack).toCountResources('AWS::ServiceCatalog::TagOption', 3); //Generates a resource for each unique key-value pair - expect(stack).toHaveResource('AWS::ServiceCatalog::TagOptionAssociation'); + Template.fromStack(stack).resourceCountIs('AWS::ServiceCatalog::TagOption', 3); //Generates a resource for each unique key-value pair + Template.fromStack(stack).resourceCountIs('AWS::ServiceCatalog::TagOptionAssociation', 3); }), test('adding identical tag options to portfolio is idempotent', () => { @@ -339,8 +339,8 @@ describe('portfolio associations and product constraints', () => { portfolio.associateTagOptions(tagOptions1); portfolio.associateTagOptions(tagOptions2); // If not idempotent this would fail - expect(stack).toCountResources('AWS::ServiceCatalog::TagOption', 3); //Generates a resource for each unique key-value pair - expect(stack).toHaveResource('AWS::ServiceCatalog::TagOptionAssociation'); + Template.fromStack(stack).resourceCountIs('AWS::ServiceCatalog::TagOption', 3); //Generates a resource for each unique key-value pair + Template.fromStack(stack).resourceCountIs('AWS::ServiceCatalog::TagOptionAssociation', 3); }), test('fails to add tag options with invalid minimum key length', () => { @@ -379,7 +379,7 @@ describe('portfolio associations and product constraints', () => { allow: true, }); - expect(stack).toHaveResourceLike('AWS::ServiceCatalog::ResourceUpdateConstraint', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceCatalog::ResourceUpdateConstraint', { TagUpdateOnProvisionedProduct: 'ALLOWED', }); }); @@ -391,7 +391,7 @@ describe('portfolio associations and product constraints', () => { allow: false, }); - expect(stack).toHaveResourceLike('AWS::ServiceCatalog::ResourceUpdateConstraint', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceCatalog::ResourceUpdateConstraint', { AcceptLanguage: servicecatalog.MessageLanguage.EN, Description: 'test constraint description', TagUpdateOnProvisionedProduct: 'NOT_ALLOWED', @@ -421,7 +421,7 @@ describe('portfolio associations and product constraints', () => { description: description, }); - expect(stack).toHaveResource('AWS::ServiceCatalog::LaunchNotificationConstraint', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceCatalog::LaunchNotificationConstraint', { NotificationArns: [{ Ref: 'TopicBFC7AF6E' }], Description: description, PortfolioId: { Ref: 'MyPortfolio59CCA9C9' }, @@ -434,7 +434,7 @@ describe('portfolio associations and product constraints', () => { portfolio.notifyOnStackEvents(product, topic); - expect(stack).toCountResources('AWS::ServiceCatalog::LaunchNotificationConstraint', 1); + Template.fromStack(stack).resourceCountIs('AWS::ServiceCatalog::LaunchNotificationConstraint', 1); }), test('can add multiple notifications', () => { @@ -446,7 +446,7 @@ describe('portfolio associations and product constraints', () => { portfolio.notifyOnStackEvents(product, topic2); portfolio.notifyOnStackEvents(product, topic3); - expect(stack).toCountResources('AWS::ServiceCatalog::LaunchNotificationConstraint', 3); + Template.fromStack(stack).resourceCountIs('AWS::ServiceCatalog::LaunchNotificationConstraint', 3); }), test('fails to add same topic multiple times in event notification constraint', () => { @@ -473,7 +473,7 @@ describe('portfolio associations and product constraints', () => { }, }); - expect(stack).toHaveResourceLike('AWS::ServiceCatalog::LaunchTemplateConstraint', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceCatalog::LaunchTemplateConstraint', { PortfolioId: { Ref: 'MyPortfolio59CCA9C9' }, ProductId: { Ref: 'MyProduct49A3C587' }, Rules: JSON.stringify( { @@ -505,7 +505,7 @@ describe('portfolio associations and product constraints', () => { messageLanguage: servicecatalog.MessageLanguage.EN, }); - expect(stack).toHaveResourceLike('AWS::ServiceCatalog::LaunchTemplateConstraint'); + Template.fromStack(stack).resourceCountIs('AWS::ServiceCatalog::LaunchTemplateConstraint', 1); }), test('set multiple CloudFormation parameters constraints', () => { @@ -529,7 +529,7 @@ describe('portfolio associations and product constraints', () => { }, }); - expect(stack).toCountResources('AWS::ServiceCatalog::LaunchTemplateConstraint', 2); + Template.fromStack(stack).resourceCountIs('AWS::ServiceCatalog::LaunchTemplateConstraint', 2); }), test('fails to set a duplicate CloudFormation parameters constraint', () => { @@ -575,7 +575,7 @@ describe('portfolio associations and product constraints', () => { messageLanguage: servicecatalog.MessageLanguage.EN, }); - expect(stack).toHaveResourceLike('AWS::ServiceCatalog::LaunchRoleConstraint', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceCatalog::LaunchRoleConstraint', { PortfolioId: { Ref: 'MyPortfolio59CCA9C9' }, ProductId: { Ref: 'MyProduct49A3C587' }, Description: 'set launch role description', @@ -589,7 +589,7 @@ describe('portfolio associations and product constraints', () => { test('set launch role constraint still adds without explicit association', () => { portfolio.setLaunchRole(product, launchRole); - expect(stack).toHaveResourceLike('AWS::ServiceCatalog::LaunchRoleConstraint'); + Template.fromStack(stack).resourceCountIs('AWS::ServiceCatalog::LaunchRoleConstraint', 1); }), test('fails to add multiple set launch roles', () => { @@ -631,7 +631,7 @@ describe('portfolio associations and product constraints', () => { messageLanguage: servicecatalog.MessageLanguage.JP, }); - expect(stack).toHaveResourceLike('AWS::ServiceCatalog::StackSetConstraint', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceCatalog::StackSetConstraint', { PortfolioId: { Ref: 'MyPortfolio59CCA9C9' }, ProductId: { Ref: 'MyProduct49A3C587' }, AdminRole: { @@ -658,7 +658,7 @@ describe('portfolio associations and product constraints', () => { allowStackSetInstanceOperations: true, }); - expect(stack).toHaveResourceLike('AWS::ServiceCatalog::StackSetConstraint'); + Template.fromStack(stack).resourceCountIs('AWS::ServiceCatalog::StackSetConstraint', 1); }), test('fails to add multiple deploy with stackset constraints', () => { diff --git a/packages/@aws-cdk/aws-servicecatalog/test/product.test.ts b/packages/@aws-cdk/aws-servicecatalog/test/product.test.ts index 7325549db63d3..57f4e50bda0c0 100644 --- a/packages/@aws-cdk/aws-servicecatalog/test/product.test.ts +++ b/packages/@aws-cdk/aws-servicecatalog/test/product.test.ts @@ -1,5 +1,5 @@ -import '@aws-cdk/assert-internal/jest'; import * as path from 'path'; +import { Match, Template } from '@aws-cdk/assertions'; import * as cdk from '@aws-cdk/core'; import * as servicecatalog from '../lib'; @@ -24,7 +24,7 @@ describe('Product', () => { ], }); - expect(stack).toHaveResourceLike('AWS::ServiceCatalog::CloudFormationProduct', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceCatalog::CloudFormationProduct', { Name: 'testProduct', Owner: 'testOwner', ProvisioningArtifactParameters: [ @@ -50,7 +50,7 @@ describe('Product', () => { ], }); - expect(stack).toHaveResourceLike('AWS::ServiceCatalog::CloudFormationProduct', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceCatalog::CloudFormationProduct', { Name: 'testProduct', Owner: 'testOwner', ProvisioningArtifactParameters: [ @@ -100,16 +100,16 @@ describe('Product', () => { ], }); - expect(stack).toHaveResourceLike('AWS::ServiceCatalog::CloudFormationProduct', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceCatalog::CloudFormationProduct', { Name: 'testProduct', Owner: 'testOwner', - ProvisioningArtifactParameters: [ - { + ProvisioningArtifactParameters: Match.arrayWith([ + Match.objectLike({ 'Info': { 'LoadTemplateFromURL': 'https://awsdocs.s3.amazonaws.com/servicecatalog/development-environment.template', }, - }, - ], + }), + ]), }); }), diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/package.json b/packages/@aws-cdk/aws-servicecatalogappregistry/package.json index ecf6b6990c3ad..921cb1fd4de60 100644 --- a/packages/@aws-cdk/aws-servicecatalogappregistry/package.json +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/package.json @@ -77,7 +77,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "@types/jest": "^26.0.24", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/test/application.test.ts b/packages/@aws-cdk/aws-servicecatalogappregistry/test/application.test.ts index bdd4e26af2616..2cd30da1b5eb8 100644 --- a/packages/@aws-cdk/aws-servicecatalogappregistry/test/application.test.ts +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/test/application.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as cdk from '@aws-cdk/core'; import * as appreg from '../lib'; @@ -14,7 +14,7 @@ describe('Application', () => { applicationName: 'testApplication', }); - expect(stack).toMatchTemplate({ + Template.fromStack(stack).templateMatches({ Resources: { MyApplication5C63EC1D: { Type: 'AWS::ServiceCatalogAppRegistry::Application', @@ -33,7 +33,7 @@ describe('Application', () => { description: description, }); - expect(stack).toHaveResourceLike('AWS::ServiceCatalogAppRegistry::Application', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceCatalogAppRegistry::Application', { Description: description, }); }), @@ -46,7 +46,7 @@ describe('Application', () => { cdk.Tags.of(application).add('key1', 'value1'); cdk.Tags.of(application).add('key2', 'value2'); - expect(stack).toHaveResourceLike('AWS::ServiceCatalogAppRegistry::Application', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceCatalogAppRegistry::Application', { Tags: { key1: 'value1', key2: 'value2', @@ -76,7 +76,7 @@ describe('Application', () => { description: tokenDescription.valueAsString, }); - expect(stack).toHaveResourceLike('AWS::ServiceCatalogAppRegistry::Application', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceCatalogAppRegistry::Application', { Description: { Ref: 'Description', }, @@ -90,7 +90,7 @@ describe('Application', () => { applicationName: tokenApplicationName.valueAsString, }); - expect(stack).toHaveResourceLike('AWS::ServiceCatalogAppRegistry::Application', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceCatalogAppRegistry::Application', { Name: { Ref: 'ApplicationName', }, @@ -147,7 +147,7 @@ describe('Application', () => { application.associateAttributeGroup(attributeGroup); - expect(stack).toHaveResourceLike('AWS::ServiceCatalogAppRegistry::AttributeGroupAssociation', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceCatalogAppRegistry::AttributeGroupAssociation', { Application: { 'Fn::GetAtt': ['MyApplication5C63EC1D', 'Id'] }, AttributeGroup: { 'Fn::GetAtt': ['AttributeGroup409C6335', 'Id'] }, }); @@ -163,7 +163,7 @@ describe('Application', () => { application.associateAttributeGroup(attributeGroup); application.associateAttributeGroup(attributeGroup); - expect(stack).toCountResources('AWS::ServiceCatalogAppRegistry::AttributeGroupAssociation', 1); + Template.fromStack(stack).resourceCountIs('AWS::ServiceCatalogAppRegistry::AttributeGroupAssociation', 1); }), test('multiple applications and attribute groups can associate', () => { @@ -187,7 +187,7 @@ describe('Application', () => { application2.associateAttributeGroup(attributeGroup1); application2.associateAttributeGroup(attributeGroup2); - expect(stack).toCountResources('AWS::ServiceCatalogAppRegistry::AttributeGroupAssociation', 4); + Template.fromStack(stack).resourceCountIs('AWS::ServiceCatalogAppRegistry::AttributeGroupAssociation', 4); }), test('associate resource', () => { @@ -195,7 +195,7 @@ describe('Application', () => { application.associateStack(resource); - expect(stack).toHaveResourceLike('AWS::ServiceCatalogAppRegistry::ResourceAssociation', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceCatalogAppRegistry::ResourceAssociation', { Application: { 'Fn::GetAtt': ['MyApplication5C63EC1D', 'Id'] }, Resource: { 'Fn::ImportValue': 'MyStack:MyStackExportsOutputRefAWSStackId23D778D8' }, }); @@ -208,7 +208,7 @@ describe('Application', () => { application.associateStack(resource); application.associateStack(resource); - expect(stack).toCountResources('AWS::ServiceCatalogAppRegistry::ResourceAssociation', 1); + Template.fromStack(stack).resourceCountIs('AWS::ServiceCatalogAppRegistry::ResourceAssociation', 1); }); }); }); diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/test/attribute-group.test.ts b/packages/@aws-cdk/aws-servicecatalogappregistry/test/attribute-group.test.ts index 35bce4b8c5e29..728ee04976623 100644 --- a/packages/@aws-cdk/aws-servicecatalogappregistry/test/attribute-group.test.ts +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/test/attribute-group.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as cdk from '@aws-cdk/core'; import * as appreg from '../lib'; @@ -17,7 +17,7 @@ describe('Attribute Group', () => { }, }); - expect(stack).toMatchTemplate({ + Template.fromStack(stack).templateMatches({ Resources: { MyAttributeGroup99099500: { Type: 'AWS::ServiceCatalogAppRegistry::AttributeGroup', @@ -42,7 +42,7 @@ describe('Attribute Group', () => { description: description, }); - expect(stack).toHaveResourceLike('AWS::ServiceCatalogAppRegistry::AttributeGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceCatalogAppRegistry::AttributeGroup', { Description: description, }); }), @@ -58,7 +58,7 @@ describe('Attribute Group', () => { cdk.Tags.of(attributeGroup).add('key1', 'value1'); cdk.Tags.of(attributeGroup).add('key2', 'value2'); - expect(stack).toHaveResourceLike('AWS::ServiceCatalogAppRegistry::AttributeGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceCatalogAppRegistry::AttributeGroup', { Tags: { key1: 'value1', key2: 'value2', @@ -90,7 +90,7 @@ describe('Attribute Group', () => { description: tokenDescription.valueAsString, }); - expect(stack).toHaveResourceLike('AWS::ServiceCatalogAppRegistry::AttributeGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceCatalogAppRegistry::AttributeGroup', { Description: { Ref: 'Description', }, @@ -107,7 +107,7 @@ describe('Attribute Group', () => { }, }); - expect(stack).toHaveResourceLike('AWS::ServiceCatalogAppRegistry::AttributeGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceCatalogAppRegistry::AttributeGroup', { Name: { Ref: 'AttributeGroupName', }, @@ -165,7 +165,7 @@ describe('Attribute Group', () => { attributes: {}, }); - expect(stack).toHaveResourceLike('AWS::ServiceCatalogAppRegistry::AttributeGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceCatalogAppRegistry::AttributeGroup', { Attributes: {}, }); }); diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/test/servicecatalogappregistry.test.ts b/packages/@aws-cdk/aws-servicecatalogappregistry/test/servicecatalogappregistry.test.ts deleted file mode 100644 index c4505ad966984..0000000000000 --- a/packages/@aws-cdk/aws-servicecatalogappregistry/test/servicecatalogappregistry.test.ts +++ /dev/null @@ -1,6 +0,0 @@ -import '@aws-cdk/assert-internal/jest'; -import {} from '../lib'; - -test('No tests are specified for this package', () => { - expect(true).toBe(true); -}); From 4d9196012f5dc0d863bca71063ae1a524cac05b0 Mon Sep 17 00:00:00 2001 From: Niranjan Jayakar Date: Tue, 3 Aug 2021 17:42:49 +0100 Subject: [PATCH 05/99] chore: switch cfn only modules to assertions (#15869) Switch all current cfn-only packages to depend on `assertions` instead of `assert`. Update `example-construct-library` to showcase using the `assertions` module. Update `cfnspec` so that new packages are created with the `assertions` module. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/@aws-cdk/alexa-ask/package.json | 2 +- packages/@aws-cdk/alexa-ask/test/ask.test.ts | 2 +- .../@aws-cdk/aws-accessanalyzer/package.json | 2 +- .../test/accessanalyzer.test.ts | 2 +- packages/@aws-cdk/aws-amazonmq/package.json | 2 +- .../aws-amazonmq/test/amazonmq.test.ts | 2 +- packages/@aws-cdk/aws-appconfig/package.json | 2 +- .../aws-appconfig/test/appconfig.test.ts | 2 +- packages/@aws-cdk/aws-appflow/package.json | 2 +- .../@aws-cdk/aws-appflow/test/appflow.test.ts | 2 +- .../@aws-cdk/aws-appintegrations/package.json | 2 +- .../test/appintegrations.test.ts | 2 +- .../aws-applicationinsights/package.json | 2 +- .../test/applicationinsights.test.ts | 2 +- packages/@aws-cdk/aws-apprunner/package.json | 2 +- .../aws-apprunner/test/apprunner.test.ts | 2 +- packages/@aws-cdk/aws-appstream/package.json | 2 +- .../aws-appstream/test/appstream.test.ts | 2 +- packages/@aws-cdk/aws-athena/package.json | 2 +- .../@aws-cdk/aws-athena/test/athena.test.ts | 11 ++++----- .../@aws-cdk/aws-auditmanager/package.json | 2 +- .../test/auditmanager.test.ts | 2 +- .../aws-autoscalingplans/package.json | 2 +- .../test/autoscalingplans.test.ts | 2 +- packages/@aws-cdk/aws-budgets/package.json | 2 +- .../@aws-cdk/aws-budgets/test/budgets.test.ts | 2 +- packages/@aws-cdk/aws-cassandra/package.json | 2 +- .../aws-cassandra/test/cassandra.test.ts | 2 +- packages/@aws-cdk/aws-ce/package.json | 2 +- packages/@aws-cdk/aws-ce/test/ce.test.ts | 2 +- .../@aws-cdk/aws-codeartifact/package.json | 2 +- .../test/codeartifact.test.ts | 2 +- .../aws-codegurureviewer/package.json | 2 +- .../test/codegurureviewer.test.ts | 2 +- .../aws-codestarconnections/package.json | 2 +- .../test/codestarconnections.test.ts | 2 +- packages/@aws-cdk/aws-connect/package.json | 2 +- .../@aws-cdk/aws-connect/test/connect.test.ts | 2 +- packages/@aws-cdk/aws-cur/package.json | 2 +- packages/@aws-cdk/aws-cur/test/cur.test.ts | 2 +- .../aws-customerprofiles/package.json | 2 +- .../test/customerprofiles.test.ts | 2 +- packages/@aws-cdk/aws-databrew/package.json | 2 +- .../aws-databrew/test/databrew.test.ts | 2 +- .../@aws-cdk/aws-datapipeline/package.json | 2 +- .../test/datapipeline.test.ts | 2 +- packages/@aws-cdk/aws-datasync/package.json | 2 +- .../aws-datasync/test/datasync.test.ts | 2 +- packages/@aws-cdk/aws-dax/package.json | 2 +- packages/@aws-cdk/aws-dax/test/dax.test.ts | 2 +- packages/@aws-cdk/aws-detective/package.json | 2 +- .../aws-detective/test/detective.test.ts | 2 +- packages/@aws-cdk/aws-devopsguru/package.json | 2 +- .../aws-devopsguru/test/devopsguru.test.ts | 2 +- .../aws-directoryservice/package.json | 2 +- .../test/directoryservice.test.ts | 2 +- packages/@aws-cdk/aws-dlm/package.json | 2 +- packages/@aws-cdk/aws-dlm/test/dlm.test.ts | 2 +- packages/@aws-cdk/aws-dms/package.json | 2 +- packages/@aws-cdk/aws-dms/test/dms.test.ts | 2 +- .../@aws-cdk/aws-elasticache/package.json | 2 +- .../aws-elasticache/test/elasticache.test.ts | 2 +- .../aws-elasticbeanstalk/package.json | 2 +- .../test/elasticbeanstalk.test.ts | 2 +- packages/@aws-cdk/aws-emr/package.json | 2 +- packages/@aws-cdk/aws-emr/test/emr.test.ts | 2 +- .../@aws-cdk/aws-emrcontainers/package.json | 2 +- .../test/emrcontainers.test.ts | 2 +- .../@aws-cdk/aws-eventschemas/package.json | 2 +- .../test/eventschemas.test.ts | 2 +- packages/@aws-cdk/aws-finspace/package.json | 2 +- .../aws-finspace/test/finspace.test.ts | 2 +- packages/@aws-cdk/aws-fis/package.json | 2 +- packages/@aws-cdk/aws-fis/test/fis.test.ts | 2 +- packages/@aws-cdk/aws-fms/package.json | 2 +- packages/@aws-cdk/aws-fms/test/fms.test.ts | 2 +- .../@aws-cdk/aws-frauddetector/package.json | 2 +- .../test/frauddetector.test.ts | 2 +- packages/@aws-cdk/aws-gamelift/package.json | 2 +- .../aws-gamelift/test/gamelift.test.ts | 2 +- packages/@aws-cdk/aws-greengrass/package.json | 2 +- .../aws-greengrass/test/greengrass.test.ts | 2 +- .../@aws-cdk/aws-greengrassv2/package.json | 2 +- .../aws-greengrassv2/test/greengrass.test.ts | 2 +- .../@aws-cdk/aws-groundstation/package.json | 2 +- .../test/groundstation.test.ts | 2 +- packages/@aws-cdk/aws-guardduty/package.json | 2 +- .../aws-guardduty/test/guardduty.test.ts | 2 +- .../@aws-cdk/aws-imagebuilder/package.json | 2 +- .../test/imagebuilder.test.ts | 2 +- packages/@aws-cdk/aws-inspector/package.json | 2 +- .../aws-inspector/test/inspector.test.ts | 2 +- packages/@aws-cdk/aws-iot/package.json | 2 +- packages/@aws-cdk/aws-iot/test/iot.test.ts | 2 +- packages/@aws-cdk/aws-iot1click/package.json | 2 +- .../aws-iot1click/test/iot1click.test.ts | 2 +- .../@aws-cdk/aws-iotanalytics/package.json | 2 +- .../test/iotanalytics.test.ts | 2 +- .../aws-iotcoredeviceadvisor/package.json | 2 +- .../test/iotcoredeviceadvisor.test.ts | 2 +- packages/@aws-cdk/aws-iotevents/package.json | 2 +- .../aws-iotevents/test/iotevents.test.ts | 2 +- .../@aws-cdk/aws-iotfleethub/package.json | 2 +- .../aws-iotfleethub/test/iotfleethub.test.ts | 2 +- .../@aws-cdk/aws-iotsitewise/package.json | 2 +- .../aws-iotsitewise/test/iotsitewise.test.ts | 2 +- .../@aws-cdk/aws-iotthingsgraph/package.json | 2 +- .../test/iotthingsgraph.test.ts | 2 +- .../@aws-cdk/aws-iotwireless/package.json | 2 +- .../aws-iotwireless/test/iotwireless.test.ts | 2 +- packages/@aws-cdk/aws-kendra/package.json | 2 +- .../@aws-cdk/aws-kendra/test/kendra.test.ts | 2 +- .../aws-kinesisanalytics/package.json | 2 +- .../test/kinesisanalytics.test.ts | 2 +- .../@aws-cdk/aws-lakeformation/package.json | 2 +- .../test/lakeformation.test.ts | 2 +- .../@aws-cdk/aws-licensemanager/package.json | 2 +- .../test/licensemanager.test.ts | 2 +- packages/@aws-cdk/aws-location/package.json | 2 +- .../aws-location/test/location.test.ts | 2 +- .../aws-lookoutequipment/package.json | 2 +- .../test/lookoutequipment.test.ts | 2 +- .../@aws-cdk/aws-lookoutmetrics/package.json | 2 +- .../test/lookoutmetrics.test.ts | 2 +- .../@aws-cdk/aws-lookoutvision/package.json | 2 +- .../test/lookoutvision.test.ts | 2 +- packages/@aws-cdk/aws-macie/package.json | 2 +- .../@aws-cdk/aws-macie/test/macie.test.ts | 2 +- .../aws-managedblockchain/package.json | 2 +- .../test/managedblockchain.test.ts | 2 +- .../@aws-cdk/aws-mediaconnect/package.json | 2 +- .../test/mediaconnect.test.ts | 2 +- .../@aws-cdk/aws-mediaconvert/package.json | 2 +- .../test/mediaconvert.test.ts | 2 +- packages/@aws-cdk/aws-medialive/package.json | 2 +- .../aws-medialive/test/medialive.test.ts | 2 +- .../@aws-cdk/aws-mediapackage/package.json | 2 +- .../test/mediapackage.test.ts | 2 +- packages/@aws-cdk/aws-mediastore/package.json | 2 +- .../aws-mediastore/test/mediastore.test.ts | 2 +- packages/@aws-cdk/aws-mwaa/package.json | 2 +- packages/@aws-cdk/aws-mwaa/test/mwaa.test.ts | 2 +- .../@aws-cdk/aws-networkfirewall/package.json | 2 +- .../test/networkfirewall.test.ts | 2 +- .../@aws-cdk/aws-networkmanager/package.json | 2 +- .../test/networkmanager.test.ts | 2 +- .../@aws-cdk/aws-nimblestudio/package.json | 2 +- .../test/nimblestudio.test.ts | 2 +- packages/@aws-cdk/aws-opsworks/package.json | 2 +- .../aws-opsworks/test/opsworks.test.ts | 2 +- packages/@aws-cdk/aws-opsworkscm/package.json | 2 +- .../aws-opsworkscm/test/opsworkscm.test.ts | 2 +- packages/@aws-cdk/aws-pinpoint/package.json | 2 +- .../aws-pinpoint/test/pinpoint.test.ts | 2 +- .../@aws-cdk/aws-pinpointemail/package.json | 2 +- .../test/pinpointemail.test.ts | 2 +- packages/@aws-cdk/aws-qldb/package.json | 2 +- packages/@aws-cdk/aws-qldb/test/qldb.test.ts | 2 +- packages/@aws-cdk/aws-quicksight/package.json | 2 +- .../aws-quicksight/test/quicksight.test.ts | 2 +- packages/@aws-cdk/aws-ram/package.json | 2 +- packages/@aws-cdk/aws-ram/test/ram.test.ts | 2 +- .../@aws-cdk/aws-resourcegroups/package.json | 2 +- .../test/resourcegroups.test.ts | 2 +- packages/@aws-cdk/aws-robomaker/package.json | 2 +- .../aws-robomaker/test/robomaker.test.ts | 2 +- .../@aws-cdk/aws-route53resolver/package.json | 2 +- .../test/route53resolver.test.ts | 2 +- .../@aws-cdk/aws-s3objectlambda/package.json | 2 +- .../test/s3objectlambda.test.ts | 2 +- packages/@aws-cdk/aws-s3outposts/package.json | 2 +- .../aws-s3outposts/test/s3outposts.test.ts | 2 +- packages/@aws-cdk/aws-sagemaker/package.json | 2 +- .../aws-sagemaker/test/sagemaker.test.ts | 2 +- packages/@aws-cdk/aws-sdb/package.json | 2 +- packages/@aws-cdk/aws-sdb/test/sdb.test.ts | 2 +- .../@aws-cdk/aws-securityhub/package.json | 2 +- .../aws-securityhub/test/securityhub.test.ts | 2 +- .../@aws-cdk/aws-ssmcontacts/package.json | 2 +- .../aws-ssmcontacts/test/ssmcontacts.test.ts | 2 +- .../@aws-cdk/aws-ssmincidents/package.json | 2 +- .../test/ssmincidents.test.ts | 2 +- packages/@aws-cdk/aws-sso/package.json | 2 +- packages/@aws-cdk/aws-sso/test/sso.test.ts | 2 +- packages/@aws-cdk/aws-timestream/package.json | 2 +- .../aws-timestream/test/timestream.test.ts | 2 +- packages/@aws-cdk/aws-transfer/package.json | 2 +- .../aws-transfer/test/transfer.test.ts | 2 +- packages/@aws-cdk/aws-waf/package.json | 2 +- packages/@aws-cdk/aws-waf/test/waf.test.ts | 2 +- .../@aws-cdk/aws-wafregional/package.json | 2 +- .../aws-wafregional/test/wafregional.test.ts | 2 +- packages/@aws-cdk/aws-wafv2/package.json | 2 +- .../@aws-cdk/aws-wafv2/test/wafv2.test.ts | 2 +- packages/@aws-cdk/aws-workspaces/package.json | 2 +- .../aws-workspaces/test/workspaces.test.ts | 2 +- packages/@aws-cdk/aws-xray/package.json | 2 +- packages/@aws-cdk/aws-xray/test/xray.test.ts | 2 +- .../build-tools/create-missing-libraries.ts | 4 ++-- .../example-construct-library/package.json | 4 ++-- .../test/example-resource.test.ts | 24 +++++++++---------- 201 files changed, 217 insertions(+), 220 deletions(-) diff --git a/packages/@aws-cdk/alexa-ask/package.json b/packages/@aws-cdk/alexa-ask/package.json index 6462fd3fcc4ee..cf42ce0ff70cd 100644 --- a/packages/@aws-cdk/alexa-ask/package.json +++ b/packages/@aws-cdk/alexa-ask/package.json @@ -78,7 +78,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/alexa-ask/test/ask.test.ts b/packages/@aws-cdk/alexa-ask/test/ask.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/alexa-ask/test/ask.test.ts +++ b/packages/@aws-cdk/alexa-ask/test/ask.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-accessanalyzer/package.json b/packages/@aws-cdk/aws-accessanalyzer/package.json index dd207f1859f38..ef5d378f88205 100644 --- a/packages/@aws-cdk/aws-accessanalyzer/package.json +++ b/packages/@aws-cdk/aws-accessanalyzer/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-accessanalyzer/test/accessanalyzer.test.ts b/packages/@aws-cdk/aws-accessanalyzer/test/accessanalyzer.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-accessanalyzer/test/accessanalyzer.test.ts +++ b/packages/@aws-cdk/aws-accessanalyzer/test/accessanalyzer.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-amazonmq/package.json b/packages/@aws-cdk/aws-amazonmq/package.json index 4cdda66e3dbf4..393ef14b15326 100644 --- a/packages/@aws-cdk/aws-amazonmq/package.json +++ b/packages/@aws-cdk/aws-amazonmq/package.json @@ -78,7 +78,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-amazonmq/test/amazonmq.test.ts b/packages/@aws-cdk/aws-amazonmq/test/amazonmq.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-amazonmq/test/amazonmq.test.ts +++ b/packages/@aws-cdk/aws-amazonmq/test/amazonmq.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-appconfig/package.json b/packages/@aws-cdk/aws-appconfig/package.json index 7ae2918e7a24a..87877e48cadd7 100644 --- a/packages/@aws-cdk/aws-appconfig/package.json +++ b/packages/@aws-cdk/aws-appconfig/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-appconfig/test/appconfig.test.ts b/packages/@aws-cdk/aws-appconfig/test/appconfig.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-appconfig/test/appconfig.test.ts +++ b/packages/@aws-cdk/aws-appconfig/test/appconfig.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-appflow/package.json b/packages/@aws-cdk/aws-appflow/package.json index d3892bc22a18e..3c1164cb36e44 100644 --- a/packages/@aws-cdk/aws-appflow/package.json +++ b/packages/@aws-cdk/aws-appflow/package.json @@ -76,7 +76,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-appflow/test/appflow.test.ts b/packages/@aws-cdk/aws-appflow/test/appflow.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-appflow/test/appflow.test.ts +++ b/packages/@aws-cdk/aws-appflow/test/appflow.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-appintegrations/package.json b/packages/@aws-cdk/aws-appintegrations/package.json index cc372cc4fb1f7..df834c9675083 100644 --- a/packages/@aws-cdk/aws-appintegrations/package.json +++ b/packages/@aws-cdk/aws-appintegrations/package.json @@ -78,7 +78,7 @@ "license": "Apache-2.0", "devDependencies": { "@types/jest": "^26.0.24", - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0" diff --git a/packages/@aws-cdk/aws-appintegrations/test/appintegrations.test.ts b/packages/@aws-cdk/aws-appintegrations/test/appintegrations.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-appintegrations/test/appintegrations.test.ts +++ b/packages/@aws-cdk/aws-appintegrations/test/appintegrations.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-applicationinsights/package.json b/packages/@aws-cdk/aws-applicationinsights/package.json index 0dcc760a0ef2b..3b0b998051313 100644 --- a/packages/@aws-cdk/aws-applicationinsights/package.json +++ b/packages/@aws-cdk/aws-applicationinsights/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-applicationinsights/test/applicationinsights.test.ts b/packages/@aws-cdk/aws-applicationinsights/test/applicationinsights.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-applicationinsights/test/applicationinsights.test.ts +++ b/packages/@aws-cdk/aws-applicationinsights/test/applicationinsights.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-apprunner/package.json b/packages/@aws-cdk/aws-apprunner/package.json index 20db35c7a3264..ffbecdc004aa6 100644 --- a/packages/@aws-cdk/aws-apprunner/package.json +++ b/packages/@aws-cdk/aws-apprunner/package.json @@ -78,7 +78,7 @@ "license": "Apache-2.0", "devDependencies": { "@types/jest": "^26.0.24", - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0" diff --git a/packages/@aws-cdk/aws-apprunner/test/apprunner.test.ts b/packages/@aws-cdk/aws-apprunner/test/apprunner.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-apprunner/test/apprunner.test.ts +++ b/packages/@aws-cdk/aws-apprunner/test/apprunner.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-appstream/package.json b/packages/@aws-cdk/aws-appstream/package.json index 2bdd6def0c6f8..3605b0f0e9ccf 100644 --- a/packages/@aws-cdk/aws-appstream/package.json +++ b/packages/@aws-cdk/aws-appstream/package.json @@ -78,7 +78,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-appstream/test/appstream.test.ts b/packages/@aws-cdk/aws-appstream/test/appstream.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-appstream/test/appstream.test.ts +++ b/packages/@aws-cdk/aws-appstream/test/appstream.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-athena/package.json b/packages/@aws-cdk/aws-athena/package.json index 0170da3267a71..4248daf56fb68 100644 --- a/packages/@aws-cdk/aws-athena/package.json +++ b/packages/@aws-cdk/aws-athena/package.json @@ -79,7 +79,7 @@ "nodeunit-shim": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-athena/test/athena.test.ts b/packages/@aws-cdk/aws-athena/test/athena.test.ts index 3e954a5b6c39b..5e84a85f5e1cf 100644 --- a/packages/@aws-cdk/aws-athena/test/athena.test.ts +++ b/packages/@aws-cdk/aws-athena/test/athena.test.ts @@ -1,5 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; -import { expect, haveResource } from '@aws-cdk/assert-internal'; +import { Template } from '@aws-cdk/assertions'; import * as cdk from '@aws-cdk/core'; import { CfnWorkGroup } from '../lib'; @@ -28,7 +27,7 @@ describe('Athena Workgroup Tags', () => { }, }, }); - expect(stack).to(haveResource('AWS::Athena::WorkGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::Athena::WorkGroup', { Tags: [ { Key: 'key1', @@ -39,7 +38,7 @@ describe('Athena Workgroup Tags', () => { Value: 'value2', }, ], - })); + }); }); test('test tag aspect spec correction', () => { const stack = new cdk.Stack(); @@ -57,7 +56,7 @@ describe('Athena Workgroup Tags', () => { }, }, }); - expect(stack).to(haveResource('AWS::Athena::WorkGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::Athena::WorkGroup', { Tags: [ { Key: 'key1', @@ -68,6 +67,6 @@ describe('Athena Workgroup Tags', () => { Value: 'value2', }, ], - })); + }); }); }); diff --git a/packages/@aws-cdk/aws-auditmanager/package.json b/packages/@aws-cdk/aws-auditmanager/package.json index e1c4d99497507..f667b4c12c375 100644 --- a/packages/@aws-cdk/aws-auditmanager/package.json +++ b/packages/@aws-cdk/aws-auditmanager/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-auditmanager/test/auditmanager.test.ts b/packages/@aws-cdk/aws-auditmanager/test/auditmanager.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-auditmanager/test/auditmanager.test.ts +++ b/packages/@aws-cdk/aws-auditmanager/test/auditmanager.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-autoscalingplans/package.json b/packages/@aws-cdk/aws-autoscalingplans/package.json index e665150f6b980..653b5457f3c97 100644 --- a/packages/@aws-cdk/aws-autoscalingplans/package.json +++ b/packages/@aws-cdk/aws-autoscalingplans/package.json @@ -77,7 +77,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-autoscalingplans/test/autoscalingplans.test.ts b/packages/@aws-cdk/aws-autoscalingplans/test/autoscalingplans.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-autoscalingplans/test/autoscalingplans.test.ts +++ b/packages/@aws-cdk/aws-autoscalingplans/test/autoscalingplans.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-budgets/package.json b/packages/@aws-cdk/aws-budgets/package.json index b3d03d5d5d194..37c92a04ef9cc 100644 --- a/packages/@aws-cdk/aws-budgets/package.json +++ b/packages/@aws-cdk/aws-budgets/package.json @@ -77,7 +77,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-budgets/test/budgets.test.ts b/packages/@aws-cdk/aws-budgets/test/budgets.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-budgets/test/budgets.test.ts +++ b/packages/@aws-cdk/aws-budgets/test/budgets.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-cassandra/package.json b/packages/@aws-cdk/aws-cassandra/package.json index 94d5a49670f90..1515c0f8cbebe 100644 --- a/packages/@aws-cdk/aws-cassandra/package.json +++ b/packages/@aws-cdk/aws-cassandra/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-cassandra/test/cassandra.test.ts b/packages/@aws-cdk/aws-cassandra/test/cassandra.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-cassandra/test/cassandra.test.ts +++ b/packages/@aws-cdk/aws-cassandra/test/cassandra.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-ce/package.json b/packages/@aws-cdk/aws-ce/package.json index 1e0345dc6fb9c..8148d2c5f2dd2 100644 --- a/packages/@aws-cdk/aws-ce/package.json +++ b/packages/@aws-cdk/aws-ce/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-ce/test/ce.test.ts b/packages/@aws-cdk/aws-ce/test/ce.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-ce/test/ce.test.ts +++ b/packages/@aws-cdk/aws-ce/test/ce.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-codeartifact/package.json b/packages/@aws-cdk/aws-codeartifact/package.json index b1d8e76ef79d4..3dc1f03908775 100644 --- a/packages/@aws-cdk/aws-codeartifact/package.json +++ b/packages/@aws-cdk/aws-codeartifact/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-codeartifact/test/codeartifact.test.ts b/packages/@aws-cdk/aws-codeartifact/test/codeartifact.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-codeartifact/test/codeartifact.test.ts +++ b/packages/@aws-cdk/aws-codeartifact/test/codeartifact.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-codegurureviewer/package.json b/packages/@aws-cdk/aws-codegurureviewer/package.json index f7a900d2aef8b..c0619789ea414 100644 --- a/packages/@aws-cdk/aws-codegurureviewer/package.json +++ b/packages/@aws-cdk/aws-codegurureviewer/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-codegurureviewer/test/codegurureviewer.test.ts b/packages/@aws-cdk/aws-codegurureviewer/test/codegurureviewer.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-codegurureviewer/test/codegurureviewer.test.ts +++ b/packages/@aws-cdk/aws-codegurureviewer/test/codegurureviewer.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-codestarconnections/package.json b/packages/@aws-cdk/aws-codestarconnections/package.json index d45abecfe6ccd..76e45df893762 100644 --- a/packages/@aws-cdk/aws-codestarconnections/package.json +++ b/packages/@aws-cdk/aws-codestarconnections/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-codestarconnections/test/codestarconnections.test.ts b/packages/@aws-cdk/aws-codestarconnections/test/codestarconnections.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-codestarconnections/test/codestarconnections.test.ts +++ b/packages/@aws-cdk/aws-codestarconnections/test/codestarconnections.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-connect/package.json b/packages/@aws-cdk/aws-connect/package.json index 02e16855e466b..93d08397cf375 100644 --- a/packages/@aws-cdk/aws-connect/package.json +++ b/packages/@aws-cdk/aws-connect/package.json @@ -78,7 +78,7 @@ "license": "Apache-2.0", "devDependencies": { "@types/jest": "^26.0.24", - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0" diff --git a/packages/@aws-cdk/aws-connect/test/connect.test.ts b/packages/@aws-cdk/aws-connect/test/connect.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-connect/test/connect.test.ts +++ b/packages/@aws-cdk/aws-connect/test/connect.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-cur/package.json b/packages/@aws-cdk/aws-cur/package.json index ec2fb98a0d60c..8969e73dc4399 100644 --- a/packages/@aws-cdk/aws-cur/package.json +++ b/packages/@aws-cdk/aws-cur/package.json @@ -78,7 +78,7 @@ "license": "Apache-2.0", "devDependencies": { "@types/jest": "^26.0.24", - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0" diff --git a/packages/@aws-cdk/aws-cur/test/cur.test.ts b/packages/@aws-cdk/aws-cur/test/cur.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-cur/test/cur.test.ts +++ b/packages/@aws-cdk/aws-cur/test/cur.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-customerprofiles/package.json b/packages/@aws-cdk/aws-customerprofiles/package.json index 387a792b7a373..36ccdda69b39d 100644 --- a/packages/@aws-cdk/aws-customerprofiles/package.json +++ b/packages/@aws-cdk/aws-customerprofiles/package.json @@ -77,7 +77,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "@types/jest": "^26.0.24", "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", diff --git a/packages/@aws-cdk/aws-customerprofiles/test/customerprofiles.test.ts b/packages/@aws-cdk/aws-customerprofiles/test/customerprofiles.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-customerprofiles/test/customerprofiles.test.ts +++ b/packages/@aws-cdk/aws-customerprofiles/test/customerprofiles.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-databrew/package.json b/packages/@aws-cdk/aws-databrew/package.json index 9f36870538f10..bf710a7394d74 100644 --- a/packages/@aws-cdk/aws-databrew/package.json +++ b/packages/@aws-cdk/aws-databrew/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-databrew/test/databrew.test.ts b/packages/@aws-cdk/aws-databrew/test/databrew.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-databrew/test/databrew.test.ts +++ b/packages/@aws-cdk/aws-databrew/test/databrew.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-datapipeline/package.json b/packages/@aws-cdk/aws-datapipeline/package.json index f368c68baa360..b0c4cf9bf3218 100644 --- a/packages/@aws-cdk/aws-datapipeline/package.json +++ b/packages/@aws-cdk/aws-datapipeline/package.json @@ -77,7 +77,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-datapipeline/test/datapipeline.test.ts b/packages/@aws-cdk/aws-datapipeline/test/datapipeline.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-datapipeline/test/datapipeline.test.ts +++ b/packages/@aws-cdk/aws-datapipeline/test/datapipeline.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-datasync/package.json b/packages/@aws-cdk/aws-datasync/package.json index d63f373cfeef8..3ec205f0d6ee1 100644 --- a/packages/@aws-cdk/aws-datasync/package.json +++ b/packages/@aws-cdk/aws-datasync/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-datasync/test/datasync.test.ts b/packages/@aws-cdk/aws-datasync/test/datasync.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-datasync/test/datasync.test.ts +++ b/packages/@aws-cdk/aws-datasync/test/datasync.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-dax/package.json b/packages/@aws-cdk/aws-dax/package.json index bd4d0c94dc3d3..82d88fd70d8d1 100644 --- a/packages/@aws-cdk/aws-dax/package.json +++ b/packages/@aws-cdk/aws-dax/package.json @@ -77,7 +77,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-dax/test/dax.test.ts b/packages/@aws-cdk/aws-dax/test/dax.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-dax/test/dax.test.ts +++ b/packages/@aws-cdk/aws-dax/test/dax.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-detective/package.json b/packages/@aws-cdk/aws-detective/package.json index b5bd1c2a903df..3955b883cb2bf 100644 --- a/packages/@aws-cdk/aws-detective/package.json +++ b/packages/@aws-cdk/aws-detective/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-detective/test/detective.test.ts b/packages/@aws-cdk/aws-detective/test/detective.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-detective/test/detective.test.ts +++ b/packages/@aws-cdk/aws-detective/test/detective.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-devopsguru/package.json b/packages/@aws-cdk/aws-devopsguru/package.json index 6fc91c263db06..9c9ff7fdb0228 100644 --- a/packages/@aws-cdk/aws-devopsguru/package.json +++ b/packages/@aws-cdk/aws-devopsguru/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-devopsguru/test/devopsguru.test.ts b/packages/@aws-cdk/aws-devopsguru/test/devopsguru.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-devopsguru/test/devopsguru.test.ts +++ b/packages/@aws-cdk/aws-devopsguru/test/devopsguru.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-directoryservice/package.json b/packages/@aws-cdk/aws-directoryservice/package.json index 179e72a6a4a2a..1396430e3a34a 100644 --- a/packages/@aws-cdk/aws-directoryservice/package.json +++ b/packages/@aws-cdk/aws-directoryservice/package.json @@ -77,7 +77,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-directoryservice/test/directoryservice.test.ts b/packages/@aws-cdk/aws-directoryservice/test/directoryservice.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-directoryservice/test/directoryservice.test.ts +++ b/packages/@aws-cdk/aws-directoryservice/test/directoryservice.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-dlm/package.json b/packages/@aws-cdk/aws-dlm/package.json index 09d10c116da40..84fd44d939683 100644 --- a/packages/@aws-cdk/aws-dlm/package.json +++ b/packages/@aws-cdk/aws-dlm/package.json @@ -78,7 +78,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-dlm/test/dlm.test.ts b/packages/@aws-cdk/aws-dlm/test/dlm.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-dlm/test/dlm.test.ts +++ b/packages/@aws-cdk/aws-dlm/test/dlm.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-dms/package.json b/packages/@aws-cdk/aws-dms/package.json index 7e06f8859e421..d1ba735745e55 100644 --- a/packages/@aws-cdk/aws-dms/package.json +++ b/packages/@aws-cdk/aws-dms/package.json @@ -77,7 +77,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-dms/test/dms.test.ts b/packages/@aws-cdk/aws-dms/test/dms.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-dms/test/dms.test.ts +++ b/packages/@aws-cdk/aws-dms/test/dms.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-elasticache/package.json b/packages/@aws-cdk/aws-elasticache/package.json index c0b500a42f22d..8a8a5a70c6c16 100644 --- a/packages/@aws-cdk/aws-elasticache/package.json +++ b/packages/@aws-cdk/aws-elasticache/package.json @@ -77,7 +77,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-elasticache/test/elasticache.test.ts b/packages/@aws-cdk/aws-elasticache/test/elasticache.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-elasticache/test/elasticache.test.ts +++ b/packages/@aws-cdk/aws-elasticache/test/elasticache.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-elasticbeanstalk/package.json b/packages/@aws-cdk/aws-elasticbeanstalk/package.json index 80d5033ecc931..a9bde94b14589 100644 --- a/packages/@aws-cdk/aws-elasticbeanstalk/package.json +++ b/packages/@aws-cdk/aws-elasticbeanstalk/package.json @@ -77,7 +77,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-elasticbeanstalk/test/elasticbeanstalk.test.ts b/packages/@aws-cdk/aws-elasticbeanstalk/test/elasticbeanstalk.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-elasticbeanstalk/test/elasticbeanstalk.test.ts +++ b/packages/@aws-cdk/aws-elasticbeanstalk/test/elasticbeanstalk.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-emr/package.json b/packages/@aws-cdk/aws-emr/package.json index f216a69bdf839..337790cd07b03 100644 --- a/packages/@aws-cdk/aws-emr/package.json +++ b/packages/@aws-cdk/aws-emr/package.json @@ -77,7 +77,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-emr/test/emr.test.ts b/packages/@aws-cdk/aws-emr/test/emr.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-emr/test/emr.test.ts +++ b/packages/@aws-cdk/aws-emr/test/emr.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-emrcontainers/package.json b/packages/@aws-cdk/aws-emrcontainers/package.json index bf2a7fbe9a627..8ea1659c08e57 100644 --- a/packages/@aws-cdk/aws-emrcontainers/package.json +++ b/packages/@aws-cdk/aws-emrcontainers/package.json @@ -81,7 +81,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-emrcontainers/test/emrcontainers.test.ts b/packages/@aws-cdk/aws-emrcontainers/test/emrcontainers.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-emrcontainers/test/emrcontainers.test.ts +++ b/packages/@aws-cdk/aws-emrcontainers/test/emrcontainers.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-eventschemas/package.json b/packages/@aws-cdk/aws-eventschemas/package.json index 0e16baa12d4f4..2d9ea8b2602d6 100644 --- a/packages/@aws-cdk/aws-eventschemas/package.json +++ b/packages/@aws-cdk/aws-eventschemas/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-eventschemas/test/eventschemas.test.ts b/packages/@aws-cdk/aws-eventschemas/test/eventschemas.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-eventschemas/test/eventschemas.test.ts +++ b/packages/@aws-cdk/aws-eventschemas/test/eventschemas.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-finspace/package.json b/packages/@aws-cdk/aws-finspace/package.json index 8b70bc5443455..1886725b8d68e 100644 --- a/packages/@aws-cdk/aws-finspace/package.json +++ b/packages/@aws-cdk/aws-finspace/package.json @@ -78,7 +78,7 @@ "license": "Apache-2.0", "devDependencies": { "@types/jest": "^26.0.24", - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0" diff --git a/packages/@aws-cdk/aws-finspace/test/finspace.test.ts b/packages/@aws-cdk/aws-finspace/test/finspace.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-finspace/test/finspace.test.ts +++ b/packages/@aws-cdk/aws-finspace/test/finspace.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-fis/package.json b/packages/@aws-cdk/aws-fis/package.json index 7412ed44a10fc..ba17edd8f186f 100644 --- a/packages/@aws-cdk/aws-fis/package.json +++ b/packages/@aws-cdk/aws-fis/package.json @@ -81,7 +81,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-fis/test/fis.test.ts b/packages/@aws-cdk/aws-fis/test/fis.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-fis/test/fis.test.ts +++ b/packages/@aws-cdk/aws-fis/test/fis.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-fms/package.json b/packages/@aws-cdk/aws-fms/package.json index 5ed725a88b4cc..d9056b520b7f1 100644 --- a/packages/@aws-cdk/aws-fms/package.json +++ b/packages/@aws-cdk/aws-fms/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-fms/test/fms.test.ts b/packages/@aws-cdk/aws-fms/test/fms.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-fms/test/fms.test.ts +++ b/packages/@aws-cdk/aws-fms/test/fms.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-frauddetector/package.json b/packages/@aws-cdk/aws-frauddetector/package.json index fbf05f78a7640..84cfc1ce40738 100644 --- a/packages/@aws-cdk/aws-frauddetector/package.json +++ b/packages/@aws-cdk/aws-frauddetector/package.json @@ -78,7 +78,7 @@ "license": "Apache-2.0", "devDependencies": { "@types/jest": "^26.0.24", - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0" diff --git a/packages/@aws-cdk/aws-frauddetector/test/frauddetector.test.ts b/packages/@aws-cdk/aws-frauddetector/test/frauddetector.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-frauddetector/test/frauddetector.test.ts +++ b/packages/@aws-cdk/aws-frauddetector/test/frauddetector.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-gamelift/package.json b/packages/@aws-cdk/aws-gamelift/package.json index 07774ebf11293..299bf7e8ca563 100644 --- a/packages/@aws-cdk/aws-gamelift/package.json +++ b/packages/@aws-cdk/aws-gamelift/package.json @@ -77,7 +77,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-gamelift/test/gamelift.test.ts b/packages/@aws-cdk/aws-gamelift/test/gamelift.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-gamelift/test/gamelift.test.ts +++ b/packages/@aws-cdk/aws-gamelift/test/gamelift.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-greengrass/package.json b/packages/@aws-cdk/aws-greengrass/package.json index 9fa8de9238ee2..e5909de8cf591 100644 --- a/packages/@aws-cdk/aws-greengrass/package.json +++ b/packages/@aws-cdk/aws-greengrass/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-greengrass/test/greengrass.test.ts b/packages/@aws-cdk/aws-greengrass/test/greengrass.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-greengrass/test/greengrass.test.ts +++ b/packages/@aws-cdk/aws-greengrass/test/greengrass.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-greengrassv2/package.json b/packages/@aws-cdk/aws-greengrassv2/package.json index 8096e3269ac30..4c21e7594e26b 100644 --- a/packages/@aws-cdk/aws-greengrassv2/package.json +++ b/packages/@aws-cdk/aws-greengrassv2/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-greengrassv2/test/greengrass.test.ts b/packages/@aws-cdk/aws-greengrassv2/test/greengrass.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-greengrassv2/test/greengrass.test.ts +++ b/packages/@aws-cdk/aws-greengrassv2/test/greengrass.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-groundstation/package.json b/packages/@aws-cdk/aws-groundstation/package.json index f337bfd5dc79e..f24da08699f70 100644 --- a/packages/@aws-cdk/aws-groundstation/package.json +++ b/packages/@aws-cdk/aws-groundstation/package.json @@ -78,7 +78,7 @@ "license": "Apache-2.0", "devDependencies": { "@types/jest": "^26.0.24", - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0" diff --git a/packages/@aws-cdk/aws-groundstation/test/groundstation.test.ts b/packages/@aws-cdk/aws-groundstation/test/groundstation.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-groundstation/test/groundstation.test.ts +++ b/packages/@aws-cdk/aws-groundstation/test/groundstation.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-guardduty/package.json b/packages/@aws-cdk/aws-guardduty/package.json index 671cd3e85044c..0fb30da82ef61 100644 --- a/packages/@aws-cdk/aws-guardduty/package.json +++ b/packages/@aws-cdk/aws-guardduty/package.json @@ -77,7 +77,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-guardduty/test/guardduty.test.ts b/packages/@aws-cdk/aws-guardduty/test/guardduty.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-guardduty/test/guardduty.test.ts +++ b/packages/@aws-cdk/aws-guardduty/test/guardduty.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-imagebuilder/package.json b/packages/@aws-cdk/aws-imagebuilder/package.json index 0f37220e9e269..64537f6b27401 100644 --- a/packages/@aws-cdk/aws-imagebuilder/package.json +++ b/packages/@aws-cdk/aws-imagebuilder/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-imagebuilder/test/imagebuilder.test.ts b/packages/@aws-cdk/aws-imagebuilder/test/imagebuilder.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-imagebuilder/test/imagebuilder.test.ts +++ b/packages/@aws-cdk/aws-imagebuilder/test/imagebuilder.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-inspector/package.json b/packages/@aws-cdk/aws-inspector/package.json index 489f584c5b6e8..dad54ff5b2e51 100644 --- a/packages/@aws-cdk/aws-inspector/package.json +++ b/packages/@aws-cdk/aws-inspector/package.json @@ -77,7 +77,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-inspector/test/inspector.test.ts b/packages/@aws-cdk/aws-inspector/test/inspector.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-inspector/test/inspector.test.ts +++ b/packages/@aws-cdk/aws-inspector/test/inspector.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-iot/package.json b/packages/@aws-cdk/aws-iot/package.json index 1e83190d4b532..f816d5f680164 100644 --- a/packages/@aws-cdk/aws-iot/package.json +++ b/packages/@aws-cdk/aws-iot/package.json @@ -77,7 +77,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-iot/test/iot.test.ts b/packages/@aws-cdk/aws-iot/test/iot.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-iot/test/iot.test.ts +++ b/packages/@aws-cdk/aws-iot/test/iot.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-iot1click/package.json b/packages/@aws-cdk/aws-iot1click/package.json index b1821fe309430..17ad106a288f2 100644 --- a/packages/@aws-cdk/aws-iot1click/package.json +++ b/packages/@aws-cdk/aws-iot1click/package.json @@ -78,7 +78,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-iot1click/test/iot1click.test.ts b/packages/@aws-cdk/aws-iot1click/test/iot1click.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-iot1click/test/iot1click.test.ts +++ b/packages/@aws-cdk/aws-iot1click/test/iot1click.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-iotanalytics/package.json b/packages/@aws-cdk/aws-iotanalytics/package.json index 97acc44632e9b..66434d4db2d33 100644 --- a/packages/@aws-cdk/aws-iotanalytics/package.json +++ b/packages/@aws-cdk/aws-iotanalytics/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-iotanalytics/test/iotanalytics.test.ts b/packages/@aws-cdk/aws-iotanalytics/test/iotanalytics.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-iotanalytics/test/iotanalytics.test.ts +++ b/packages/@aws-cdk/aws-iotanalytics/test/iotanalytics.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-iotcoredeviceadvisor/package.json b/packages/@aws-cdk/aws-iotcoredeviceadvisor/package.json index ca500daa21d26..80fc81f75a022 100644 --- a/packages/@aws-cdk/aws-iotcoredeviceadvisor/package.json +++ b/packages/@aws-cdk/aws-iotcoredeviceadvisor/package.json @@ -78,7 +78,7 @@ "license": "Apache-2.0", "devDependencies": { "@types/jest": "^26.0.24", - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0" diff --git a/packages/@aws-cdk/aws-iotcoredeviceadvisor/test/iotcoredeviceadvisor.test.ts b/packages/@aws-cdk/aws-iotcoredeviceadvisor/test/iotcoredeviceadvisor.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-iotcoredeviceadvisor/test/iotcoredeviceadvisor.test.ts +++ b/packages/@aws-cdk/aws-iotcoredeviceadvisor/test/iotcoredeviceadvisor.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-iotevents/package.json b/packages/@aws-cdk/aws-iotevents/package.json index e6e819bba2aed..9125c6a9a05b1 100644 --- a/packages/@aws-cdk/aws-iotevents/package.json +++ b/packages/@aws-cdk/aws-iotevents/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-iotevents/test/iotevents.test.ts b/packages/@aws-cdk/aws-iotevents/test/iotevents.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-iotevents/test/iotevents.test.ts +++ b/packages/@aws-cdk/aws-iotevents/test/iotevents.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-iotfleethub/package.json b/packages/@aws-cdk/aws-iotfleethub/package.json index f873c33b08634..69891556a7f4b 100644 --- a/packages/@aws-cdk/aws-iotfleethub/package.json +++ b/packages/@aws-cdk/aws-iotfleethub/package.json @@ -78,7 +78,7 @@ "license": "Apache-2.0", "devDependencies": { "@types/jest": "^26.0.24", - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0" diff --git a/packages/@aws-cdk/aws-iotfleethub/test/iotfleethub.test.ts b/packages/@aws-cdk/aws-iotfleethub/test/iotfleethub.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-iotfleethub/test/iotfleethub.test.ts +++ b/packages/@aws-cdk/aws-iotfleethub/test/iotfleethub.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-iotsitewise/package.json b/packages/@aws-cdk/aws-iotsitewise/package.json index 81750ea6c4221..9c86ba4bcd889 100644 --- a/packages/@aws-cdk/aws-iotsitewise/package.json +++ b/packages/@aws-cdk/aws-iotsitewise/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-iotsitewise/test/iotsitewise.test.ts b/packages/@aws-cdk/aws-iotsitewise/test/iotsitewise.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-iotsitewise/test/iotsitewise.test.ts +++ b/packages/@aws-cdk/aws-iotsitewise/test/iotsitewise.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-iotthingsgraph/package.json b/packages/@aws-cdk/aws-iotthingsgraph/package.json index 39dee778b632f..a00fc435787fe 100644 --- a/packages/@aws-cdk/aws-iotthingsgraph/package.json +++ b/packages/@aws-cdk/aws-iotthingsgraph/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-iotthingsgraph/test/iotthingsgraph.test.ts b/packages/@aws-cdk/aws-iotthingsgraph/test/iotthingsgraph.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-iotthingsgraph/test/iotthingsgraph.test.ts +++ b/packages/@aws-cdk/aws-iotthingsgraph/test/iotthingsgraph.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-iotwireless/package.json b/packages/@aws-cdk/aws-iotwireless/package.json index 176941dd97bb4..ee46fc9ca58ec 100644 --- a/packages/@aws-cdk/aws-iotwireless/package.json +++ b/packages/@aws-cdk/aws-iotwireless/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-iotwireless/test/iotwireless.test.ts b/packages/@aws-cdk/aws-iotwireless/test/iotwireless.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-iotwireless/test/iotwireless.test.ts +++ b/packages/@aws-cdk/aws-iotwireless/test/iotwireless.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-kendra/package.json b/packages/@aws-cdk/aws-kendra/package.json index c78e48ea705e7..33ab4f2afa7f2 100644 --- a/packages/@aws-cdk/aws-kendra/package.json +++ b/packages/@aws-cdk/aws-kendra/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-kendra/test/kendra.test.ts b/packages/@aws-cdk/aws-kendra/test/kendra.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-kendra/test/kendra.test.ts +++ b/packages/@aws-cdk/aws-kendra/test/kendra.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-kinesisanalytics/package.json b/packages/@aws-cdk/aws-kinesisanalytics/package.json index 3a3933d62d655..db7c571c963c8 100644 --- a/packages/@aws-cdk/aws-kinesisanalytics/package.json +++ b/packages/@aws-cdk/aws-kinesisanalytics/package.json @@ -80,7 +80,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-kinesisanalytics/test/kinesisanalytics.test.ts b/packages/@aws-cdk/aws-kinesisanalytics/test/kinesisanalytics.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-kinesisanalytics/test/kinesisanalytics.test.ts +++ b/packages/@aws-cdk/aws-kinesisanalytics/test/kinesisanalytics.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-lakeformation/package.json b/packages/@aws-cdk/aws-lakeformation/package.json index a374c0d9627da..87af67a50de81 100644 --- a/packages/@aws-cdk/aws-lakeformation/package.json +++ b/packages/@aws-cdk/aws-lakeformation/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-lakeformation/test/lakeformation.test.ts b/packages/@aws-cdk/aws-lakeformation/test/lakeformation.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-lakeformation/test/lakeformation.test.ts +++ b/packages/@aws-cdk/aws-lakeformation/test/lakeformation.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-licensemanager/package.json b/packages/@aws-cdk/aws-licensemanager/package.json index eb66089eae974..0219ff3d93dc0 100644 --- a/packages/@aws-cdk/aws-licensemanager/package.json +++ b/packages/@aws-cdk/aws-licensemanager/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-licensemanager/test/licensemanager.test.ts b/packages/@aws-cdk/aws-licensemanager/test/licensemanager.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-licensemanager/test/licensemanager.test.ts +++ b/packages/@aws-cdk/aws-licensemanager/test/licensemanager.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-location/package.json b/packages/@aws-cdk/aws-location/package.json index dedff67266046..5a9473d0d22dd 100644 --- a/packages/@aws-cdk/aws-location/package.json +++ b/packages/@aws-cdk/aws-location/package.json @@ -78,7 +78,7 @@ "license": "Apache-2.0", "devDependencies": { "@types/jest": "^26.0.24", - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0" diff --git a/packages/@aws-cdk/aws-location/test/location.test.ts b/packages/@aws-cdk/aws-location/test/location.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-location/test/location.test.ts +++ b/packages/@aws-cdk/aws-location/test/location.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-lookoutequipment/package.json b/packages/@aws-cdk/aws-lookoutequipment/package.json index e34187a2c7e57..3d3d93d1a9bb4 100644 --- a/packages/@aws-cdk/aws-lookoutequipment/package.json +++ b/packages/@aws-cdk/aws-lookoutequipment/package.json @@ -78,7 +78,7 @@ "license": "Apache-2.0", "devDependencies": { "@types/jest": "^26.0.22", - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0" diff --git a/packages/@aws-cdk/aws-lookoutequipment/test/lookoutequipment.test.ts b/packages/@aws-cdk/aws-lookoutequipment/test/lookoutequipment.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-lookoutequipment/test/lookoutequipment.test.ts +++ b/packages/@aws-cdk/aws-lookoutequipment/test/lookoutequipment.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-lookoutmetrics/package.json b/packages/@aws-cdk/aws-lookoutmetrics/package.json index 93c04870c0f5d..f79a8e599ed12 100644 --- a/packages/@aws-cdk/aws-lookoutmetrics/package.json +++ b/packages/@aws-cdk/aws-lookoutmetrics/package.json @@ -78,7 +78,7 @@ "license": "Apache-2.0", "devDependencies": { "@types/jest": "^26.0.24", - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0" diff --git a/packages/@aws-cdk/aws-lookoutmetrics/test/lookoutmetrics.test.ts b/packages/@aws-cdk/aws-lookoutmetrics/test/lookoutmetrics.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-lookoutmetrics/test/lookoutmetrics.test.ts +++ b/packages/@aws-cdk/aws-lookoutmetrics/test/lookoutmetrics.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-lookoutvision/package.json b/packages/@aws-cdk/aws-lookoutvision/package.json index d55a122cb7624..33ede00a2af8c 100644 --- a/packages/@aws-cdk/aws-lookoutvision/package.json +++ b/packages/@aws-cdk/aws-lookoutvision/package.json @@ -81,7 +81,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-lookoutvision/test/lookoutvision.test.ts b/packages/@aws-cdk/aws-lookoutvision/test/lookoutvision.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-lookoutvision/test/lookoutvision.test.ts +++ b/packages/@aws-cdk/aws-lookoutvision/test/lookoutvision.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-macie/package.json b/packages/@aws-cdk/aws-macie/package.json index 1cbdb49f09399..cd1d450bd73b6 100644 --- a/packages/@aws-cdk/aws-macie/package.json +++ b/packages/@aws-cdk/aws-macie/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-macie/test/macie.test.ts b/packages/@aws-cdk/aws-macie/test/macie.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-macie/test/macie.test.ts +++ b/packages/@aws-cdk/aws-macie/test/macie.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-managedblockchain/package.json b/packages/@aws-cdk/aws-managedblockchain/package.json index 675de2f297c20..09d5ad7a954ea 100644 --- a/packages/@aws-cdk/aws-managedblockchain/package.json +++ b/packages/@aws-cdk/aws-managedblockchain/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-managedblockchain/test/managedblockchain.test.ts b/packages/@aws-cdk/aws-managedblockchain/test/managedblockchain.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-managedblockchain/test/managedblockchain.test.ts +++ b/packages/@aws-cdk/aws-managedblockchain/test/managedblockchain.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-mediaconnect/package.json b/packages/@aws-cdk/aws-mediaconnect/package.json index b67436e9224aa..d0f29ba806f03 100644 --- a/packages/@aws-cdk/aws-mediaconnect/package.json +++ b/packages/@aws-cdk/aws-mediaconnect/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-mediaconnect/test/mediaconnect.test.ts b/packages/@aws-cdk/aws-mediaconnect/test/mediaconnect.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-mediaconnect/test/mediaconnect.test.ts +++ b/packages/@aws-cdk/aws-mediaconnect/test/mediaconnect.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-mediaconvert/package.json b/packages/@aws-cdk/aws-mediaconvert/package.json index 4808bc6dda2ff..725541270f71b 100644 --- a/packages/@aws-cdk/aws-mediaconvert/package.json +++ b/packages/@aws-cdk/aws-mediaconvert/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-mediaconvert/test/mediaconvert.test.ts b/packages/@aws-cdk/aws-mediaconvert/test/mediaconvert.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-mediaconvert/test/mediaconvert.test.ts +++ b/packages/@aws-cdk/aws-mediaconvert/test/mediaconvert.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-medialive/package.json b/packages/@aws-cdk/aws-medialive/package.json index 3e1e7088f1f0c..dd9f764f06d1b 100644 --- a/packages/@aws-cdk/aws-medialive/package.json +++ b/packages/@aws-cdk/aws-medialive/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-medialive/test/medialive.test.ts b/packages/@aws-cdk/aws-medialive/test/medialive.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-medialive/test/medialive.test.ts +++ b/packages/@aws-cdk/aws-medialive/test/medialive.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-mediapackage/package.json b/packages/@aws-cdk/aws-mediapackage/package.json index 84077872af4d5..9910b1dc2f864 100644 --- a/packages/@aws-cdk/aws-mediapackage/package.json +++ b/packages/@aws-cdk/aws-mediapackage/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-mediapackage/test/mediapackage.test.ts b/packages/@aws-cdk/aws-mediapackage/test/mediapackage.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-mediapackage/test/mediapackage.test.ts +++ b/packages/@aws-cdk/aws-mediapackage/test/mediapackage.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-mediastore/package.json b/packages/@aws-cdk/aws-mediastore/package.json index 20e9b4057dbe5..5a5ec1ff16709 100644 --- a/packages/@aws-cdk/aws-mediastore/package.json +++ b/packages/@aws-cdk/aws-mediastore/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-mediastore/test/mediastore.test.ts b/packages/@aws-cdk/aws-mediastore/test/mediastore.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-mediastore/test/mediastore.test.ts +++ b/packages/@aws-cdk/aws-mediastore/test/mediastore.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-mwaa/package.json b/packages/@aws-cdk/aws-mwaa/package.json index 07fbbab350909..0a784d8121200 100644 --- a/packages/@aws-cdk/aws-mwaa/package.json +++ b/packages/@aws-cdk/aws-mwaa/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-mwaa/test/mwaa.test.ts b/packages/@aws-cdk/aws-mwaa/test/mwaa.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-mwaa/test/mwaa.test.ts +++ b/packages/@aws-cdk/aws-mwaa/test/mwaa.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-networkfirewall/package.json b/packages/@aws-cdk/aws-networkfirewall/package.json index 27b3aa04a7136..3b6617b2582c5 100644 --- a/packages/@aws-cdk/aws-networkfirewall/package.json +++ b/packages/@aws-cdk/aws-networkfirewall/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-networkfirewall/test/networkfirewall.test.ts b/packages/@aws-cdk/aws-networkfirewall/test/networkfirewall.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-networkfirewall/test/networkfirewall.test.ts +++ b/packages/@aws-cdk/aws-networkfirewall/test/networkfirewall.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-networkmanager/package.json b/packages/@aws-cdk/aws-networkmanager/package.json index f0666a1e676cc..dd671b4ffd623 100644 --- a/packages/@aws-cdk/aws-networkmanager/package.json +++ b/packages/@aws-cdk/aws-networkmanager/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-networkmanager/test/networkmanager.test.ts b/packages/@aws-cdk/aws-networkmanager/test/networkmanager.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-networkmanager/test/networkmanager.test.ts +++ b/packages/@aws-cdk/aws-networkmanager/test/networkmanager.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-nimblestudio/package.json b/packages/@aws-cdk/aws-nimblestudio/package.json index 5f9f77d2f58b2..8270304b555fa 100644 --- a/packages/@aws-cdk/aws-nimblestudio/package.json +++ b/packages/@aws-cdk/aws-nimblestudio/package.json @@ -78,7 +78,7 @@ "license": "Apache-2.0", "devDependencies": { "@types/jest": "^26.0.24", - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0" diff --git a/packages/@aws-cdk/aws-nimblestudio/test/nimblestudio.test.ts b/packages/@aws-cdk/aws-nimblestudio/test/nimblestudio.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-nimblestudio/test/nimblestudio.test.ts +++ b/packages/@aws-cdk/aws-nimblestudio/test/nimblestudio.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-opsworks/package.json b/packages/@aws-cdk/aws-opsworks/package.json index 978dd2b2b07c5..5d6f8b77a7d04 100644 --- a/packages/@aws-cdk/aws-opsworks/package.json +++ b/packages/@aws-cdk/aws-opsworks/package.json @@ -77,7 +77,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-opsworks/test/opsworks.test.ts b/packages/@aws-cdk/aws-opsworks/test/opsworks.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-opsworks/test/opsworks.test.ts +++ b/packages/@aws-cdk/aws-opsworks/test/opsworks.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-opsworkscm/package.json b/packages/@aws-cdk/aws-opsworkscm/package.json index 42c0e014301cb..03870f42fa5a0 100644 --- a/packages/@aws-cdk/aws-opsworkscm/package.json +++ b/packages/@aws-cdk/aws-opsworkscm/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-opsworkscm/test/opsworkscm.test.ts b/packages/@aws-cdk/aws-opsworkscm/test/opsworkscm.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-opsworkscm/test/opsworkscm.test.ts +++ b/packages/@aws-cdk/aws-opsworkscm/test/opsworkscm.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-pinpoint/package.json b/packages/@aws-cdk/aws-pinpoint/package.json index 0f5b7b48a84cf..8475739eaa6f7 100644 --- a/packages/@aws-cdk/aws-pinpoint/package.json +++ b/packages/@aws-cdk/aws-pinpoint/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-pinpoint/test/pinpoint.test.ts b/packages/@aws-cdk/aws-pinpoint/test/pinpoint.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-pinpoint/test/pinpoint.test.ts +++ b/packages/@aws-cdk/aws-pinpoint/test/pinpoint.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-pinpointemail/package.json b/packages/@aws-cdk/aws-pinpointemail/package.json index 7659ce4025b4a..d57fe0f9ac922 100644 --- a/packages/@aws-cdk/aws-pinpointemail/package.json +++ b/packages/@aws-cdk/aws-pinpointemail/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-pinpointemail/test/pinpointemail.test.ts b/packages/@aws-cdk/aws-pinpointemail/test/pinpointemail.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-pinpointemail/test/pinpointemail.test.ts +++ b/packages/@aws-cdk/aws-pinpointemail/test/pinpointemail.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-qldb/package.json b/packages/@aws-cdk/aws-qldb/package.json index ac50a35b7c1aa..3922e74b5a384 100644 --- a/packages/@aws-cdk/aws-qldb/package.json +++ b/packages/@aws-cdk/aws-qldb/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-qldb/test/qldb.test.ts b/packages/@aws-cdk/aws-qldb/test/qldb.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-qldb/test/qldb.test.ts +++ b/packages/@aws-cdk/aws-qldb/test/qldb.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-quicksight/package.json b/packages/@aws-cdk/aws-quicksight/package.json index 3d55f0052512b..00f42d396c801 100644 --- a/packages/@aws-cdk/aws-quicksight/package.json +++ b/packages/@aws-cdk/aws-quicksight/package.json @@ -81,7 +81,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-quicksight/test/quicksight.test.ts b/packages/@aws-cdk/aws-quicksight/test/quicksight.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-quicksight/test/quicksight.test.ts +++ b/packages/@aws-cdk/aws-quicksight/test/quicksight.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-ram/package.json b/packages/@aws-cdk/aws-ram/package.json index 6383a8a7ce1a1..6f817b0f45b4b 100644 --- a/packages/@aws-cdk/aws-ram/package.json +++ b/packages/@aws-cdk/aws-ram/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-ram/test/ram.test.ts b/packages/@aws-cdk/aws-ram/test/ram.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-ram/test/ram.test.ts +++ b/packages/@aws-cdk/aws-ram/test/ram.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-resourcegroups/package.json b/packages/@aws-cdk/aws-resourcegroups/package.json index 611c01ef93ae8..88e73e2bd2426 100644 --- a/packages/@aws-cdk/aws-resourcegroups/package.json +++ b/packages/@aws-cdk/aws-resourcegroups/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-resourcegroups/test/resourcegroups.test.ts b/packages/@aws-cdk/aws-resourcegroups/test/resourcegroups.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-resourcegroups/test/resourcegroups.test.ts +++ b/packages/@aws-cdk/aws-resourcegroups/test/resourcegroups.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-robomaker/package.json b/packages/@aws-cdk/aws-robomaker/package.json index 8f4f5c4350cc7..124451f52e67b 100644 --- a/packages/@aws-cdk/aws-robomaker/package.json +++ b/packages/@aws-cdk/aws-robomaker/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-robomaker/test/robomaker.test.ts b/packages/@aws-cdk/aws-robomaker/test/robomaker.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-robomaker/test/robomaker.test.ts +++ b/packages/@aws-cdk/aws-robomaker/test/robomaker.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-route53resolver/package.json b/packages/@aws-cdk/aws-route53resolver/package.json index ab96545ce6345..a515fecb3c120 100644 --- a/packages/@aws-cdk/aws-route53resolver/package.json +++ b/packages/@aws-cdk/aws-route53resolver/package.json @@ -78,7 +78,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-route53resolver/test/route53resolver.test.ts b/packages/@aws-cdk/aws-route53resolver/test/route53resolver.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-route53resolver/test/route53resolver.test.ts +++ b/packages/@aws-cdk/aws-route53resolver/test/route53resolver.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-s3objectlambda/package.json b/packages/@aws-cdk/aws-s3objectlambda/package.json index 7818c261a21bc..f8e0d0986fe8a 100644 --- a/packages/@aws-cdk/aws-s3objectlambda/package.json +++ b/packages/@aws-cdk/aws-s3objectlambda/package.json @@ -81,7 +81,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-s3objectlambda/test/s3objectlambda.test.ts b/packages/@aws-cdk/aws-s3objectlambda/test/s3objectlambda.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-s3objectlambda/test/s3objectlambda.test.ts +++ b/packages/@aws-cdk/aws-s3objectlambda/test/s3objectlambda.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-s3outposts/package.json b/packages/@aws-cdk/aws-s3outposts/package.json index 4645c65189333..da5317e14e7b3 100644 --- a/packages/@aws-cdk/aws-s3outposts/package.json +++ b/packages/@aws-cdk/aws-s3outposts/package.json @@ -81,7 +81,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-s3outposts/test/s3outposts.test.ts b/packages/@aws-cdk/aws-s3outposts/test/s3outposts.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-s3outposts/test/s3outposts.test.ts +++ b/packages/@aws-cdk/aws-s3outposts/test/s3outposts.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-sagemaker/package.json b/packages/@aws-cdk/aws-sagemaker/package.json index 3f2fa9d8ab857..136d5ad52ea25 100644 --- a/packages/@aws-cdk/aws-sagemaker/package.json +++ b/packages/@aws-cdk/aws-sagemaker/package.json @@ -78,7 +78,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-sagemaker/test/sagemaker.test.ts b/packages/@aws-cdk/aws-sagemaker/test/sagemaker.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-sagemaker/test/sagemaker.test.ts +++ b/packages/@aws-cdk/aws-sagemaker/test/sagemaker.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-sdb/package.json b/packages/@aws-cdk/aws-sdb/package.json index b1773cf5a3907..9863fe0333e24 100644 --- a/packages/@aws-cdk/aws-sdb/package.json +++ b/packages/@aws-cdk/aws-sdb/package.json @@ -77,7 +77,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-sdb/test/sdb.test.ts b/packages/@aws-cdk/aws-sdb/test/sdb.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-sdb/test/sdb.test.ts +++ b/packages/@aws-cdk/aws-sdb/test/sdb.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-securityhub/package.json b/packages/@aws-cdk/aws-securityhub/package.json index ad2e1abf1e401..e71153d4822ad 100644 --- a/packages/@aws-cdk/aws-securityhub/package.json +++ b/packages/@aws-cdk/aws-securityhub/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-securityhub/test/securityhub.test.ts b/packages/@aws-cdk/aws-securityhub/test/securityhub.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-securityhub/test/securityhub.test.ts +++ b/packages/@aws-cdk/aws-securityhub/test/securityhub.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-ssmcontacts/package.json b/packages/@aws-cdk/aws-ssmcontacts/package.json index fb7c8defd4291..350d243514340 100644 --- a/packages/@aws-cdk/aws-ssmcontacts/package.json +++ b/packages/@aws-cdk/aws-ssmcontacts/package.json @@ -78,7 +78,7 @@ "license": "Apache-2.0", "devDependencies": { "@types/jest": "^26.0.24", - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0" diff --git a/packages/@aws-cdk/aws-ssmcontacts/test/ssmcontacts.test.ts b/packages/@aws-cdk/aws-ssmcontacts/test/ssmcontacts.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-ssmcontacts/test/ssmcontacts.test.ts +++ b/packages/@aws-cdk/aws-ssmcontacts/test/ssmcontacts.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-ssmincidents/package.json b/packages/@aws-cdk/aws-ssmincidents/package.json index 1ef3f6cc287f7..668f68e02fd64 100644 --- a/packages/@aws-cdk/aws-ssmincidents/package.json +++ b/packages/@aws-cdk/aws-ssmincidents/package.json @@ -78,7 +78,7 @@ "license": "Apache-2.0", "devDependencies": { "@types/jest": "^26.0.24", - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0" diff --git a/packages/@aws-cdk/aws-ssmincidents/test/ssmincidents.test.ts b/packages/@aws-cdk/aws-ssmincidents/test/ssmincidents.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-ssmincidents/test/ssmincidents.test.ts +++ b/packages/@aws-cdk/aws-ssmincidents/test/ssmincidents.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-sso/package.json b/packages/@aws-cdk/aws-sso/package.json index 9eae6cfdc23a0..b6361b2336306 100644 --- a/packages/@aws-cdk/aws-sso/package.json +++ b/packages/@aws-cdk/aws-sso/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-sso/test/sso.test.ts b/packages/@aws-cdk/aws-sso/test/sso.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-sso/test/sso.test.ts +++ b/packages/@aws-cdk/aws-sso/test/sso.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-timestream/package.json b/packages/@aws-cdk/aws-timestream/package.json index 7a00e4fcb5c84..82e1fb198680b 100644 --- a/packages/@aws-cdk/aws-timestream/package.json +++ b/packages/@aws-cdk/aws-timestream/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0" diff --git a/packages/@aws-cdk/aws-timestream/test/timestream.test.ts b/packages/@aws-cdk/aws-timestream/test/timestream.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-timestream/test/timestream.test.ts +++ b/packages/@aws-cdk/aws-timestream/test/timestream.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-transfer/package.json b/packages/@aws-cdk/aws-transfer/package.json index 45fc2b0164fc1..4d8e05fab19f5 100644 --- a/packages/@aws-cdk/aws-transfer/package.json +++ b/packages/@aws-cdk/aws-transfer/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-transfer/test/transfer.test.ts b/packages/@aws-cdk/aws-transfer/test/transfer.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-transfer/test/transfer.test.ts +++ b/packages/@aws-cdk/aws-transfer/test/transfer.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-waf/package.json b/packages/@aws-cdk/aws-waf/package.json index ec2e3ec379265..8c4f85f3402b7 100644 --- a/packages/@aws-cdk/aws-waf/package.json +++ b/packages/@aws-cdk/aws-waf/package.json @@ -77,7 +77,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-waf/test/waf.test.ts b/packages/@aws-cdk/aws-waf/test/waf.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-waf/test/waf.test.ts +++ b/packages/@aws-cdk/aws-waf/test/waf.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-wafregional/package.json b/packages/@aws-cdk/aws-wafregional/package.json index 4003f4ff7b0f0..e82afe0e25e4a 100644 --- a/packages/@aws-cdk/aws-wafregional/package.json +++ b/packages/@aws-cdk/aws-wafregional/package.json @@ -77,7 +77,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-wafregional/test/wafregional.test.ts b/packages/@aws-cdk/aws-wafregional/test/wafregional.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-wafregional/test/wafregional.test.ts +++ b/packages/@aws-cdk/aws-wafregional/test/wafregional.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-wafv2/package.json b/packages/@aws-cdk/aws-wafv2/package.json index f7c5ae3b14798..c46028b894625 100644 --- a/packages/@aws-cdk/aws-wafv2/package.json +++ b/packages/@aws-cdk/aws-wafv2/package.json @@ -79,7 +79,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-wafv2/test/wafv2.test.ts b/packages/@aws-cdk/aws-wafv2/test/wafv2.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-wafv2/test/wafv2.test.ts +++ b/packages/@aws-cdk/aws-wafv2/test/wafv2.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-workspaces/package.json b/packages/@aws-cdk/aws-workspaces/package.json index ab45c38ed0fbd..84f7406237f45 100644 --- a/packages/@aws-cdk/aws-workspaces/package.json +++ b/packages/@aws-cdk/aws-workspaces/package.json @@ -77,7 +77,7 @@ "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "@aws-cdk/assertions": "0.0.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-workspaces/test/workspaces.test.ts b/packages/@aws-cdk/aws-workspaces/test/workspaces.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-workspaces/test/workspaces.test.ts +++ b/packages/@aws-cdk/aws-workspaces/test/workspaces.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-xray/package.json b/packages/@aws-cdk/aws-xray/package.json index 1d63e8fa740b3..e5ec9ff9da5fa 100644 --- a/packages/@aws-cdk/aws-xray/package.json +++ b/packages/@aws-cdk/aws-xray/package.json @@ -78,7 +78,7 @@ "license": "Apache-2.0", "devDependencies": { "@types/jest": "^26.0.24", - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "cdk-build-tools": "0.0.0", "cfn2ts": "0.0.0", "pkglint": "0.0.0" diff --git a/packages/@aws-cdk/aws-xray/test/xray.test.ts b/packages/@aws-cdk/aws-xray/test/xray.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-xray/test/xray.test.ts +++ b/packages/@aws-cdk/aws-xray/test/xray.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/cfnspec/build-tools/create-missing-libraries.ts b/packages/@aws-cdk/cfnspec/build-tools/create-missing-libraries.ts index 8a62868591119..db1edab50e8a4 100644 --- a/packages/@aws-cdk/cfnspec/build-tools/create-missing-libraries.ts +++ b/packages/@aws-cdk/cfnspec/build-tools/create-missing-libraries.ts @@ -179,7 +179,7 @@ async function main() { license: 'Apache-2.0', devDependencies: { '@types/jest': '^26.0.22', - '@aws-cdk/assert-internal': version, + '@aws-cdk/assertions': version, 'cdk-build-tools': version, 'cfn2ts': version, 'pkglint': version, @@ -263,7 +263,7 @@ async function main() { ]); await write(`test/${lowcaseModuleName}.test.ts`, [ - "import '@aws-cdk/assert-internal/jest';", + "import '@aws-cdk/assertions';", "import {} from '../lib';", '', "test('No tests are specified for this package', () => {", diff --git a/packages/@aws-cdk/example-construct-library/package.json b/packages/@aws-cdk/example-construct-library/package.json index 9eb248eba276e..7f66f7c22ee55 100644 --- a/packages/@aws-cdk/example-construct-library/package.json +++ b/packages/@aws-cdk/example-construct-library/package.json @@ -66,12 +66,12 @@ }, "license": "Apache-2.0", "devDependencies": { + "@aws-cdk/assertions": "0.0.0", "@types/jest": "^26.0.24", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "jest": "^26.6.3", - "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "pkglint": "0.0.0" }, "dependencies": { "@aws-cdk/aws-cloudwatch": "0.0.0", diff --git a/packages/@aws-cdk/example-construct-library/test/example-resource.test.ts b/packages/@aws-cdk/example-construct-library/test/example-resource.test.ts index 8145feddb307d..091c0c7d1f65a 100644 --- a/packages/@aws-cdk/example-construct-library/test/example-resource.test.ts +++ b/packages/@aws-cdk/example-construct-library/test/example-resource.test.ts @@ -4,10 +4,7 @@ * but it's considered Names, and we want to migrate to Jest). */ -// import the various CDK assertion helpers -import { ABSENT, ResourcePart } from '@aws-cdk/assert-internal'; -// always import our Jest-specific helpers -import '@aws-cdk/assert-internal/jest'; +import { Match, Template } from '@aws-cdk/assertions'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as iam from '@aws-cdk/aws-iam'; @@ -40,13 +37,13 @@ describe('Example Resource', () => { test('creates a CFN WaitConditionHandle resource', () => { // you can simply assert that a resource of a given type // was generated in the resulting template - expect(stack).toHaveResource('AWS::CloudFormation::WaitConditionHandle'); + Template.fromStack(stack).resourceCountIs('AWS::CloudFormation::WaitConditionHandle', 1); }); describe('creates a CFN WaitCondition resource', () => { test('with count = 0 and timeout = 10', () => { // you can also assert the properties of the resulting resource - expect(stack).toHaveResource('AWS::CloudFormation::WaitCondition', { + Template.fromStack(stack).hasResourceProperties('AWS::CloudFormation::WaitCondition', { 'Count': 0, 'Timeout': '10', 'Handle': { @@ -59,19 +56,19 @@ describe('Example Resource', () => { 'Ref': 'ExampleResourceWaitConditionHandle9C53A8D3', }, // this is how you can check a given property is _not_ set - 'RandomProperty': ABSENT, + 'RandomProperty': Match.absentProperty(), }); }); test('with retention policy = Retain', () => { - // haveResource asserts _all_ properties of a resource, - // while haveResourceLike only those that you provide - expect(stack).toHaveResourceLike('AWS::CloudFormation::WaitCondition', { + // hasResource asserts _all_ properties of a resource, + // while hasResourceProperties only those within the 'Property' block + Template.fromStack(stack).hasResource('AWS::CloudFormation::WaitCondition', { 'DeletionPolicy': 'Retain', 'UpdateReplacePolicy': 'Retain', // by default, haveResource and haveResourceLike only assert the properties of a resource - // here's how you make them look at the entire resource definition - }, ResourcePart.CompleteDefinition); + }); }); }); @@ -91,11 +88,12 @@ describe('Example Resource', () => { exampleResource.grantRead(role); - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { 'PolicyDocument': { 'Statement': [ { 'Action': 's3:Get*', + 'Effect': 'Allow', 'Resource': { 'Fn::Join': ['', [ 'arn:', @@ -131,7 +129,7 @@ describe('Example Resource', () => { }); test('correctly fills out the subnetIds property of the created VPC endpoint', () => { - expect(stack).toHaveResourceLike('AWS::EC2::VPCEndpoint', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::VPCEndpoint', { 'SubnetIds': [ { 'Ref': 'VpcPrivateSubnet1Subnet536B997A' }, { 'Ref': 'VpcPrivateSubnet2Subnet3788AAA1' }, From 77dfa2f8546d03671b3304d2910a9c7e387ff6a8 Mon Sep 17 00:00:00 2001 From: Ben Chaimberg Date: Tue, 3 Aug 2021 11:11:26 -0700 Subject: [PATCH 06/99] chore: temporarily transfer @skinny85 module ownership (#15872) --- .github/workflows/issue-label-assign.yml | 116 +++++++++++------------ 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/.github/workflows/issue-label-assign.yml b/.github/workflows/issue-label-assign.yml index fe09e74b25e2e..bcf12f04a1ec6 100644 --- a/.github/workflows/issue-label-assign.yml +++ b/.github/workflows/issue-label-assign.yml @@ -21,23 +21,23 @@ jobs: [ {"keywords":["(cli)","(command line)"],"labels":["package/tools"],"assignees":["rix0rrr"]}, {"keywords":["(@aws-cdk/alexa-ask)","(alexa-ask)","(alexa ask)"],"labels":["@aws-cdk/alexa-ask"],"assignees":["madeline-k"]}, - {"keywords":["(@aws-cdk/app-delivery)","(app-delivery)","(app delivery)"],"labels":["@aws-cdk/app-delivery"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/app-delivery)","(app-delivery)","(app delivery)"],"labels":["@aws-cdk/app-delivery"],"assignees":["madeline-k"]}, {"keywords":["(@aws-cdk/assert)","(assert)"],"labels":["@aws-cdk/assert"],"assignees":["nija-at"]}, {"keywords":["(@aws-cdk/assets)","(assets)"],"labels":["@aws-cdk/assets"],"assignees":["eladb"]}, - {"keywords":["(@aws-cdk/aws-accessanalyzer)","(aws-accessanalyzer)","(accessanalyzer)","(access analyzer)"],"labels":["@aws-cdk/aws-accessanalyzer"],"assignees":["skinny85"]}, - {"keywords":["(@aws-cdk/aws-acmpca)","(aws-acmpca)","(acmpca)"],"labels":["@aws-cdk/aws-acmpca"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-accessanalyzer)","(aws-accessanalyzer)","(accessanalyzer)","(access analyzer)"],"labels":["@aws-cdk/aws-accessanalyzer"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-acmpca)","(aws-acmpca)","(acmpca)"],"labels":["@aws-cdk/aws-acmpca"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/aws-amazonmq)","(aws-amazonmq)","(amazonmq)","(amazon mq)","(amazon-mq)"],"labels":["@aws-cdk/aws-amazonmq"],"assignees":["otaviomacedo"]}, - {"keywords":["(@aws-cdk/aws-amplify)","(aws-amplify)","(amplify)"],"labels":["@aws-cdk/aws-amplify"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-amplify)","(aws-amplify)","(amplify)"],"labels":["@aws-cdk/aws-amplify"],"assignees":["madeline-k"]}, {"keywords":["(@aws-cdk/aws-apigateway)","(aws-apigateway)","(apigateway)","(api gateway)","(api-gateway)"],"labels":["@aws-cdk/aws-apigateway"],"assignees":["nija-at"]}, {"keywords":["(@aws-cdk/aws-apigatewayv2)","(aws-apigatewayv2)","(apigatewayv2)","(apigateway v2)","(api-gateway-v2)"],"labels":["@aws-cdk/aws-apigatewayv2"],"assignees":["nija-at"]}, {"keywords":["(@aws-cdk/aws-apigatewayv2-authorizers)","(aws-apigatewayv2-authorizers)","(apigatewayv2-authorizers)"],"labels":["@aws-cdk/aws-apigatewayv2-authorizers"],"assignees":["nija-at"]}, {"keywords":["(@aws-cdk/aws-apigatewayv2-integrations)","(aws-apigatewayv2-integrations)","(apigatewayv2-integrations)","(apigateway v2 integrations)","(api-gateway-v2-integrations)"],"labels":["@aws-cdk/aws-apigatewayv2-integrations"],"assignees":["nija-at"]}, {"keywords":["(@aws-cdk/aws-appconfig)","(aws-appconfig)","(appconfig)","(app config)","(app-config)"],"labels":["@aws-cdk/aws-appconfig"],"assignees":["rix0rrr"]}, - {"keywords":["(@aws-cdk/aws-appflow)","(aws-appflow)","(appflow)","(app flow)","(app-flow)"],"labels":["@aws-cdk/aws-appflow"],"assignees":["skinny85"]}, - {"keywords":["(@aws-cdk/aws-appintegrations)","(aws-appintegrations)","(appintegrations)"],"labels":["@aws-cdk/aws-appintegrations"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-appflow)","(aws-appflow)","(appflow)","(app flow)","(app-flow)"],"labels":["@aws-cdk/aws-appflow"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-appintegrations)","(aws-appintegrations)","(appintegrations)"],"labels":["@aws-cdk/aws-appintegrations"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/aws-applicationautoscaling)","(aws-applicationautoscaling)","(applicationautoscaling)","(application autoscaling)","(application-autoscaling)"],"labels":["@aws-cdk/aws-applicationautoscaling"],"assignees":["rix0rrr"]}, {"keywords":["(@aws-cdk/aws-applicationinsights)","(aws-applicationinsights)","(applicationinsights)","(application insights)","(application-insights)"],"labels":["@aws-cdk/aws-applicationinsights"],"assignees":["njlynch"]}, - {"keywords":["(@aws-cdk/aws-appmesh)","(aws-appmesh)","(appmesh)","(app mesh)","(app-mesh)"],"labels":["@aws-cdk/aws-appmesh"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-appmesh)","(aws-appmesh)","(appmesh)","(app mesh)","(app-mesh)"],"labels":["@aws-cdk/aws-appmesh"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/aws-appstream)","(aws-appstream)","(appstream)","(app stream)","(app-stream)"],"labels":["@aws-cdk/aws-appstream"],"assignees":["madeline-k"]}, {"keywords":["(@aws-cdk/aws-appsync)","(aws-appsync)","(appsync)","(app sync)","(app-sync)"],"labels":["@aws-cdk/aws-appsync"],"assignees":["otaviomacedo"]}, {"keywords":["(@aws-cdk/aws-athena)","(aws-athena)","(athena)"],"labels":["@aws-cdk/aws-athena"],"assignees":["BenChaimberg"]}, @@ -54,7 +54,7 @@ jobs: {"keywords":["(@aws-cdk/aws-ce)","(aws-ce)","(ce)"],"labels":["@aws-cdk/aws-ce"],"assignees":["njlynch"]}, {"keywords":["(@aws-cdk/aws-certificatemanager)","(aws-certificatemanager)","(certificatemanager)","(certificate manager)","(certificate-manager)","(acm)"],"labels":["@aws-cdk/aws-certificatemanager"],"assignees":["njlynch"]}, {"keywords":["(@aws-cdk/aws-chatbot)","(aws-chatbot)","(chatbot)"],"labels":["@aws-cdk/aws-chatbot"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-cloud9)","(aws-cloud9)","(cloud9)","(cloud 9)"],"labels":["@aws-cdk/aws-cloud9"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-cloud9)","(aws-cloud9)","(cloud9)","(cloud 9)"],"labels":["@aws-cdk/aws-cloud9"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/aws-cloudformation)","(aws-cloudformation)","(cloudformation)","(cloud formation)"],"labels":["@aws-cdk/aws-cloudformation"],"assignees":["rix0rrr"]}, {"keywords":["(@aws-cdk/aws-cloudfront)","(aws-cloudfront)","(cloudfront)","(cloud front)"],"labels":["@aws-cdk/aws-cloudfront"],"assignees":["njlynch"]}, {"keywords":["(@aws-cdk/aws-cloudfront-origins)","(aws-cloudfront-origins)","(cloudfront-origins)","(cloudfront origins)"],"labels":["@aws-cdk/aws-cloudfront-origins"],"assignees":["njlynch"]}, @@ -62,31 +62,31 @@ jobs: {"keywords":["(@aws-cdk/aws-cloudwatch)","(aws-cloudwatch)","(cloudwatch)","(cloud watch)"],"labels":["@aws-cdk/aws-cloudwatch"],"assignees":["madeline-k"]}, {"keywords":["(@aws-cdk/aws-cloudwatch-actions)","(aws-cloudwatch-actions)","(cloudwatch-actions)","(cloudwatch actions)"],"labels":["@aws-cdk/aws-cloudwatch-actions"],"assignees":["madeline-k"]}, {"keywords":["(@aws-cdk/aws-codeartifact)","(aws-codeartifact)","(codeartifact)","(code artifact)","(code-artifact)"],"labels":["@aws-cdk/aws-codeartifact"],"assignees":["njlynch"]}, - {"keywords":["(@aws-cdk/aws-codebuild)","(aws-codebuild)","(codebuild)","(code build)","(code-build)"],"labels":["@aws-cdk/aws-codebuild"],"assignees":["skinny85"]}, - {"keywords":["(@aws-cdk/aws-codecommit)","(aws-codecommit)","(codecommit)","(code commit)", "(code-commit)"],"labels":["@aws-cdk/aws-codecommit"],"assignees":["skinny85"]}, - {"keywords":["(@aws-cdk/aws-codedeploy)","(aws-codedeploy)","(codedeploy)","(code deploy)","(code-deploy)"],"labels":["@aws-cdk/aws-codedeploy"],"assignees":["skinny85"]}, - {"keywords":["(@aws-cdk/aws-codeguruprofiler)","(aws-codeguruprofiler)","(codeguruprofiler)","(codeguru profiler)","(codeguru-profiler)"],"labels":["@aws-cdk/aws-codeguruprofiler"],"assignees":["skinny85"]}, - {"keywords":["(@aws-cdk/aws-codegurureviewer)","(aws-codegurureviewer)","(codegurureviewer)","(codeguru reviewer)","(codeguru-reviewer)"],"labels":["@aws-cdk/aws-codegurureviewer"],"assignees":["skinny85"]}, - {"keywords":["(@aws-cdk/aws-codepipeline)","(aws-codepipeline)","(codepipeline)","(code pipeline)","(code-pipeline)"],"labels":["@aws-cdk/aws-codepipeline"],"assignees":["skinny85"]}, - {"keywords":["(@aws-cdk/aws-codepipeline-actions)","(aws-codepipeline-actions)","(codepipeline-actions)","(codepipeline actions)"],"labels":["@aws-cdk/aws-codepipeline-actions"],"assignees":["skinny85"]}, - {"keywords":["(@aws-cdk/aws-codestar)","(aws-codestar)","(codestar)"],"labels":["@aws-cdk/aws-codestar"],"assignees":["skinny85"]}, - {"keywords":["(@aws-cdk/aws-codestarconnections)","(aws-codestarconnections)","(codestarconnections)","(codestar connections)","(codestar-connections)"],"labels":["@aws-cdk/aws-codestarconnections"],"assignees":["skinny85"]}, - {"keywords":["(@aws-cdk/aws-codestarnotifications)","(aws-codestarnotifications)","(codestarnotifications)","(codestar notifications)","(codestar-notifications)"],"labels":["@aws-cdk/aws-codestarnotifications"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-codebuild)","(aws-codebuild)","(codebuild)","(code build)","(code-build)"],"labels":["@aws-cdk/aws-codebuild"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-codecommit)","(aws-codecommit)","(codecommit)","(code commit)", "(code-commit)"],"labels":["@aws-cdk/aws-codecommit"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-codedeploy)","(aws-codedeploy)","(codedeploy)","(code deploy)","(code-deploy)"],"labels":["@aws-cdk/aws-codedeploy"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-codeguruprofiler)","(aws-codeguruprofiler)","(codeguruprofiler)","(codeguru profiler)","(codeguru-profiler)"],"labels":["@aws-cdk/aws-codeguruprofiler"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-codegurureviewer)","(aws-codegurureviewer)","(codegurureviewer)","(codeguru reviewer)","(codeguru-reviewer)"],"labels":["@aws-cdk/aws-codegurureviewer"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-codepipeline)","(aws-codepipeline)","(codepipeline)","(code pipeline)","(code-pipeline)"],"labels":["@aws-cdk/aws-codepipeline"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-codepipeline-actions)","(aws-codepipeline-actions)","(codepipeline-actions)","(codepipeline actions)"],"labels":["@aws-cdk/aws-codepipeline-actions"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-codestar)","(aws-codestar)","(codestar)"],"labels":["@aws-cdk/aws-codestar"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-codestarconnections)","(aws-codestarconnections)","(codestarconnections)","(codestar connections)","(codestar-connections)"],"labels":["@aws-cdk/aws-codestarconnections"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-codestarnotifications)","(aws-codestarnotifications)","(codestarnotifications)","(codestar notifications)","(codestar-notifications)"],"labels":["@aws-cdk/aws-codestarnotifications"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/aws-cognito)","(aws-cognito)","(cognito)"],"labels":["@aws-cdk/aws-cognito"],"assignees":["nija-at"]}, {"keywords":["(@aws-cdk/aws-config)","(aws-config)","(config)"],"labels":["@aws-cdk/aws-config"],"assignees":["rix0rrr"]}, {"keywords":["(@aws-cdk/aws-customerprofiles)","(aws-customerprofiles)","(customerprofiles)"],"labels":["@aws-cdk/aws-customerprofiles"],"assignees":["otaviomacedo"]}, {"keywords":["(@aws-cdk/aws-databrew)","(aws-databrew)","(databrew)"],"labels":["@aws-cdk/aws-databrew"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/aws-datapipeline)","(aws-datapipeline)","(datapipeline)","(data pipeline)","(data-pipeline)"],"labels":["@aws-cdk/aws-datapipeline"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/aws-datasync)","(aws-datasync)","(datasync)"],"labels":["@aws-cdk/aws-datasync"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-dax)","(aws-dax)","(dax)"],"labels":["@aws-cdk/aws-dax"],"assignees":["skinny85"]}, - {"keywords":["(@aws-cdk/aws-detective)","(aws-detective)","(detective)"],"labels":["@aws-cdk/aws-detective"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-dax)","(aws-dax)","(dax)"],"labels":["@aws-cdk/aws-dax"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-detective)","(aws-detective)","(detective)"],"labels":["@aws-cdk/aws-detective"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/aws-devopsguru)","(aws-devopsguru)","(devopsguru)"],"labels":["@aws-cdk/aws-devopsguru"],"assignees":["nija-at"]}, {"keywords":["(@aws-cdk/aws-directoryservice)","(aws-directoryservice)","(directoryservice)","(directory service)","(directory-service)"],"labels":["@aws-cdk/aws-directoryservice"],"assignees":["rix0rrr"]}, {"keywords":["(@aws-cdk/aws-dlm)","(aws-dlm)","(dlm)"],"labels":["@aws-cdk/aws-dlm"],"assignees":["njlynch"]}, {"keywords":["(@aws-cdk/aws-dms)","(aws-dms)","(dms)"],"labels":["@aws-cdk/aws-dms"],"assignees":["njlynch"]}, - {"keywords":["(@aws-cdk/aws-docdb)","(aws-docdb)","(docdb)","(doc db)","(doc-db)"],"labels":["@aws-cdk/aws-docdb"],"assignees":["skinny85"]}, - {"keywords":["(@aws-cdk/aws-dynamodb)","(aws-dynamodb)","(dynamodb)","(dynamo db)","(dynamo-db)"],"labels":["@aws-cdk/aws-dynamodb"],"assignees":["skinny85"]}, - {"keywords":["(@aws-cdk/aws-dynamodb-global)","(aws-dynamodb-global)","(dynamodb-global)","(dynamodb global)"],"labels":["@aws-cdk/aws-dynamodb-global"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-docdb)","(aws-docdb)","(docdb)","(doc db)","(doc-db)"],"labels":["@aws-cdk/aws-docdb"],"assignees":["madeline-k"]}, + {"keywords":["(@aws-cdk/aws-dynamodb)","(aws-dynamodb)","(dynamodb)","(dynamo db)","(dynamo-db)"],"labels":["@aws-cdk/aws-dynamodb"],"assignees":["madeline-k"]}, + {"keywords":["(@aws-cdk/aws-dynamodb-global)","(aws-dynamodb-global)","(dynamodb-global)","(dynamodb global)"],"labels":["@aws-cdk/aws-dynamodb-global"],"assignees":["madeline-k"]}, {"keywords":["(@aws-cdk/aws-ec2)","(aws-ec2)","(ec2)","(vpc)"],"labels":["@aws-cdk/aws-ec2"],"assignees":["njlynch"]}, {"keywords":["(@aws-cdk/aws-ecr)","(aws-ecr)","(ecr)"],"labels":["@aws-cdk/aws-ecr"],"assignees":["madeline-k"]}, {"keywords":["(@aws-cdk/aws-ecr-assets)","(aws-ecr-assets)","(ecr-assets)","(ecr assets)","(ecrassets)"],"labels":["@aws-cdk/aws-ecr-assets"],"assignees":["eladb"]}, @@ -96,7 +96,7 @@ jobs: {"keywords":["(@aws-cdk/aws-eks)","(aws-eks)","(eks)"],"labels":["@aws-cdk/aws-eks"],"assignees":["otaviomacedo"]}, {"keywords":["(@aws-cdk/aws-eks-legacy)","(aws-eks-legacy)","(eks-legacy)"],"labels":["@aws-cdk/aws-eks-legacy"],"assignees":["otaviomacedo"]}, {"keywords":["(@aws-cdk/aws-elasticache)","(aws-elasticache)","(elasticache)","(elastic cache)","(elastic-cache)"],"labels":["@aws-cdk/aws-elasticache"],"assignees":["otaviomacedo"]}, - {"keywords":["(@aws-cdk/aws-elasticbeanstalk)","(aws-elasticbeanstalk)","(elasticbeanstalk)","(elastic beanstalk)","(elastic-beanstalk)"],"labels":["@aws-cdk/aws-elasticbeanstalk"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-elasticbeanstalk)","(aws-elasticbeanstalk)","(elasticbeanstalk)","(elastic beanstalk)","(elastic-beanstalk)"],"labels":["@aws-cdk/aws-elasticbeanstalk"],"assignees":["madeline-k"]}, {"keywords":["(@aws-cdk/aws-elasticloadbalancing)","(aws-elasticloadbalancing)","(elasticloadbalancing)","(elastic loadbalancing)","(elastic-loadbalancing)","(elb)"],"labels":["@aws-cdk/aws-elasticloadbalancing"],"assignees":["njlynch"]}, {"keywords":["(@aws-cdk/aws-elasticloadbalancingv2)","(aws-elasticloadbalancingv2)","(elasticloadbalancingv2)","(elastic-loadbalancing-v2)","(elbv2)","(elb v2)"],"labels":["@aws-cdk/aws-elasticloadbalancingv2"],"assignees":["njlynch"]}, {"keywords":["(@aws-cdk/aws-elasticloadbalancingv2-actions)","(aws-elasticloadbalancingv2-actions)","(elasticloadbalancingv2-actions)"],"labels":["@aws-cdk/aws-elasticloadbalancingv2-actions"],"assignees":["njlynch"]}, @@ -106,7 +106,7 @@ jobs: {"keywords":["(@aws-cdk/aws-emrcontainers)","(aws-emrcontainers)","(emrcontainers)"],"labels":["@aws-cdk/aws-emrcontainers"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/aws-events)","(aws-events)","(events)","(eventbridge)","(event-bridge)"],"labels":["@aws-cdk/aws-events"],"assignees":["rix0rrr"]}, {"keywords":["(@aws-cdk/aws-events-targets)","(aws-events-targets)","(events-targets)","(events targets)"],"labels":["@aws-cdk/aws-events-targets"],"assignees":["rix0rrr"]}, - {"keywords":["(@aws-cdk/aws-eventschemas)","(aws-eventschemas)","(eventschemas)","(event schemas)"],"labels":["@aws-cdk/aws-eventschemas"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-eventschemas)","(aws-eventschemas)","(eventschemas)","(event schemas)"],"labels":["@aws-cdk/aws-eventschemas"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/aws-finspace)","(aws-finspace)","(finspace)"],"labels":["@aws-cdk/aws-finspace"],"assignees":["njlynch"]}, {"keywords":["(@aws-cdk/aws-fis)","(aws-fis)","(fis)"],"labels":["@aws-cdk/aws-fis"],"assignees":["njlynch"]}, {"keywords":["(@aws-cdk/aws-fms)","(aws-fms)","(fms)"],"labels":["@aws-cdk/aws-fms"],"assignees":["rix0rrr"]}, @@ -116,23 +116,23 @@ jobs: {"keywords":["(@aws-cdk/aws-globalaccelerator)","(aws-globalaccelerator)","(globalaccelerator)","(global accelerator)","(global-accelerator)"],"labels":["@aws-cdk/aws-globalaccelerator"],"assignees":["rix0rrr"]}, {"keywords":["(@aws-cdk/aws-globalaccelerator-endpoints)","(aws-globalaccelerator-endpoints)","(globalaccelerator-endpoints)"],"labels":["@aws-cdk/aws-globalaccelerator-endpoints"],"assignees":["rix0rrr"]}, {"keywords":["(@aws-cdk/aws-glue)","(aws-glue)","(glue)"],"labels":["@aws-cdk/aws-glue"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-greengrass)","(aws-greengrass)","(greengrass)","(green grass)","(green-grass)"],"labels":["@aws-cdk/aws-greengrass"],"assignees":["skinny85"]}, - {"keywords":["(@aws-cdk/aws-greengrassv2)","(aws-greengrassv2)","(greengrassv2)"],"labels":["@aws-cdk/aws-greengrassv2"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-greengrass)","(aws-greengrass)","(greengrass)","(green grass)","(green-grass)"],"labels":["@aws-cdk/aws-greengrass"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-greengrassv2)","(aws-greengrassv2)","(greengrassv2)"],"labels":["@aws-cdk/aws-greengrassv2"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/aws-groundstation)","(aws-groundstation)","(groundstation)"],"labels":["@aws-cdk/aws-groundstation"],"assignees":["rix0rrr"]}, {"keywords":["(@aws-cdk/aws-guardduty)","(aws-guardduty)","(guardduty)","(guard duty)","(guard-duty)"],"labels":["@aws-cdk/aws-guardduty"],"assignees":["rix0rrr"]}, {"keywords":["(@aws-cdk/aws-iam)","(aws-iam)","(iam)"],"labels":["@aws-cdk/aws-iam"],"assignees":["rix0rrr"]}, - {"keywords":["(@aws-cdk/aws-imagebuilder)","(aws-imagebuilder)","(imagebuilder)","(image builder)","(image-builder)"],"labels":["@aws-cdk/aws-imagebuilder"],"assignees":["skinny85"]}, - {"keywords":["(@aws-cdk/aws-inspector)","(aws-inspector)","(inspector)"],"labels":["@aws-cdk/aws-inspector"],"assignees":["skinny85"]}, - {"keywords":["(@aws-cdk/aws-iot)","(aws-iot)","(iot)"],"labels":["@aws-cdk/aws-iot"],"assignees":["skinny85"]}, - {"keywords":["(@aws-cdk/aws-iot1click)","(aws-iot1click)","(iot1click)","(iot 1click)"],"labels":["@aws-cdk/aws-iot1click"],"assignees":["skinny85"]}, - {"keywords":["(@aws-cdk/aws-iotanalytics)","(aws-iotanalytics)","(iotanalytics)","(iot analytics)","(iot-analytics)"],"labels":["@aws-cdk/aws-iotanalytics"],"assignees":["skinny85"]}, - {"keywords":["(@aws-cdk/aws-iotevents)","(aws-iotevents)","(iotevents)","(iot events)","(iot-events)"],"labels":["@aws-cdk/aws-iotevents"],"assignees":["skinny85"]}, - {"keywords":["(@aws-cdk/aws-iotfleethub)","(aws-iotfleethub)","(iotfleethub)"],"labels":["@aws-cdk/aws-iotfleethub"],"assignees":["skinny85"]}, - {"keywords":["(@aws-cdk/aws-iotsitewise)","(aws-iotsitewise)","(iotsitewise)","(iot sitewise)","(iot-sitewise)","(iot-site-wise)","(iot site wise)"],"labels":["@aws-cdk/aws-iotsitewise"],"assignees":["skinny85"]}, - {"keywords":["(@aws-cdk/aws-iotthingsgraph)","(aws-iotthingsgraph)","(iotthingsgraph)","(iot things graph)","(iot-things-graph)"],"labels":["@aws-cdk/aws-iotthingsgraph"],"assignees":["skinny85"]}, - {"keywords":["(@aws-cdk/aws-iotwireless)","(aws-iotwireless)","(iotwireless)"],"labels":["@aws-cdk/aws-iotwireless"],"assignees":["skinny85"]}, - {"keywords":["(@aws-cdk/aws-ivs)","(aws-ivs)","(Interactive Video Service)","(ivs)"],"labels":["@aws-cdk/aws-ivs"],"assignees":["skinny85"]}, - {"keywords":["(@aws-cdk/aws-kendra)","(aws-kendra)","(kendra)"],"labels":["@aws-cdk/aws-kendra"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-imagebuilder)","(aws-imagebuilder)","(imagebuilder)","(image builder)","(image-builder)"],"labels":["@aws-cdk/aws-imagebuilder"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-inspector)","(aws-inspector)","(inspector)"],"labels":["@aws-cdk/aws-inspector"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-iot)","(aws-iot)","(iot)"],"labels":["@aws-cdk/aws-iot"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-iot1click)","(aws-iot1click)","(iot1click)","(iot 1click)"],"labels":["@aws-cdk/aws-iot1click"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-iotanalytics)","(aws-iotanalytics)","(iotanalytics)","(iot analytics)","(iot-analytics)"],"labels":["@aws-cdk/aws-iotanalytics"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-iotevents)","(aws-iotevents)","(iotevents)","(iot events)","(iot-events)"],"labels":["@aws-cdk/aws-iotevents"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-iotfleethub)","(aws-iotfleethub)","(iotfleethub)"],"labels":["@aws-cdk/aws-iotfleethub"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-iotsitewise)","(aws-iotsitewise)","(iotsitewise)","(iot sitewise)","(iot-sitewise)","(iot-site-wise)","(iot site wise)"],"labels":["@aws-cdk/aws-iotsitewise"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-iotthingsgraph)","(aws-iotthingsgraph)","(iotthingsgraph)","(iot things graph)","(iot-things-graph)"],"labels":["@aws-cdk/aws-iotthingsgraph"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-iotwireless)","(aws-iotwireless)","(iotwireless)"],"labels":["@aws-cdk/aws-iotwireless"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-ivs)","(aws-ivs)","(Interactive Video Service)","(ivs)"],"labels":["@aws-cdk/aws-ivs"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-kendra)","(aws-kendra)","(kendra)"],"labels":["@aws-cdk/aws-kendra"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/aws-kinesis)","(aws-kinesis)","(kinesis)"],"labels":["@aws-cdk/aws-kinesis"],"assignees":["otaviomacedo"]}, {"keywords":["(@aws-cdk/aws-kinesisanalytics)","(aws-kinesisanalytics)","(kinesisanalytics)","(kinesis analytics)","(kinesis-analytics)"],"labels":["@aws-cdk/aws-kinesisanalytics"],"assignees":["otaviomacedo"]}, {"keywords":["(@aws-cdk/aws-kinesisanalytics-flink)","(aws-kinesisanalytics-flink)","(kinesisanalytics-flink)"],"labels":["@aws-cdk/aws-kinesisanalytics-flink"],"assignees":["otaviomacedo"]}, @@ -151,27 +151,27 @@ jobs: {"keywords":["(@aws-cdk/aws-lookoutmetrics)","(aws-lookoutmetrics)","(lookoutmetrics)"],"labels":["@aws-cdk/aws-lookoutmetrics"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/aws-lookoutvision)","(aws-lookoutvision)","(lookoutvision)"],"labels":["@aws-cdk/aws-lookoutvision"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/aws-macie)","(aws-macie)","(macie)"],"labels":["@aws-cdk/aws-macie"],"assignees":["njlynch"]}, - {"keywords":["(@aws-cdk/aws-managedblockchain)","(aws-managedblockchain)","(managedblockchain)","(managed blockchain)","(managed-blockchain)"],"labels":["@aws-cdk/aws-managedblockchain"],"assignees":["skinny85"]}, - {"keywords":["(@aws-cdk/aws-mediaconnect)","(aws-mediaconnect)","(mediaconnect)"],"labels":["@aws-cdk/aws-mediaconnect"],"assignees":["skinny85"]}, - {"keywords":["(@aws-cdk/aws-mediaconvert)","(aws-mediaconvert)","(mediaconvert)","(media convert)","(media-convert)"],"labels":["@aws-cdk/aws-mediaconvert"],"assignees":["skinny85"]}, - {"keywords":["(@aws-cdk/aws-medialive)","(aws-medialive)","(medialive)","(media live)","(media-live)"],"labels":["@aws-cdk/aws-medialive"],"assignees":["skinny85"]}, - {"keywords":["(@aws-cdk/aws-mediastore)","(aws-mediastore)","(mediastore)","(media store)","(media-store)"],"labels":["@aws-cdk/aws-mediastore"],"assignees":["skinny85"]}, - {"keywords":["(@aws-cdk/aws-mediapackage)","(aws-mediapackage)","(mediapackage)","(media package)","(media-package)"],"labels":["@aws-cdk/aws-mediapackage"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-managedblockchain)","(aws-managedblockchain)","(managedblockchain)","(managed blockchain)","(managed-blockchain)"],"labels":["@aws-cdk/aws-managedblockchain"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-mediaconnect)","(aws-mediaconnect)","(mediaconnect)"],"labels":["@aws-cdk/aws-mediaconnect"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-mediaconvert)","(aws-mediaconvert)","(mediaconvert)","(media convert)","(media-convert)"],"labels":["@aws-cdk/aws-mediaconvert"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-medialive)","(aws-medialive)","(medialive)","(media live)","(media-live)"],"labels":["@aws-cdk/aws-medialive"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-mediastore)","(aws-mediastore)","(mediastore)","(media store)","(media-store)"],"labels":["@aws-cdk/aws-mediastore"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-mediapackage)","(aws-mediapackage)","(mediapackage)","(media package)","(media-package)"],"labels":["@aws-cdk/aws-mediapackage"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/aws-msk)","(aws-msk)","(msk)"],"labels":["@aws-cdk/aws-msk"],"assignees":["otaviomacedo"]}, {"keywords":["(@aws-cdk/aws-mwaa)","(aws-mwaa)","(mwaa)"],"labels":["@aws-cdk/aws-mwaa"],"assignees":["rix0rrr"]}, {"keywords":["(@aws-cdk/aws-neptune)","(aws-neptune)","(neptune)"],"labels":["@aws-cdk/aws-neptune"],"assignees":["njlynch"]}, - {"keywords":["(@aws-cdk/aws-networkfirewall)","(aws-networkfirewall)","(networkfirewall)"],"labels":["@aws-cdk/aws-networkfirewall"],"assignees":["skinny85"]}, - {"keywords":["(@aws-cdk/aws-networkmanager)","(aws-networkmanager)","(networkmanager)","(network manager)","(network-manager)"],"labels":["@aws-cdk/aws-networkmanager"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-networkfirewall)","(aws-networkfirewall)","(networkfirewall)"],"labels":["@aws-cdk/aws-networkfirewall"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-networkmanager)","(aws-networkmanager)","(networkmanager)","(network manager)","(network-manager)"],"labels":["@aws-cdk/aws-networkmanager"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/aws-nimblestudio)","(aws-nimblestudio)","(nimblestudio)"],"labels":["@aws-cdk/aws-nimblestudio"],"assignees":["madeline-k"]}, {"keywords":["(@aws-cdk/aws-opsworks)","(aws-opsworks)","(opsworks)","(ops works)","(ops-works)"],"labels":["@aws-cdk/aws-opsworks"],"assignees":["madeline-k"]}, {"keywords":["(@aws-cdk/aws-opsworkscm)","(aws-opsworkscm)","(opsworkscm)","(opsworks cm)","(opsworks-cm)"],"labels":["@aws-cdk/aws-opsworkscm"],"assignees":["madeline-k"]}, {"keywords":["(@aws-cdk/aws-personalize)","(aws-personalize)","(personalize)"],"labels":["@aws-cdk/aws-personalize"],"assignees":["njlynch"]}, {"keywords":["(@aws-cdk/aws-pinpoint)","(aws-pinpoint)","(pinpoint)"],"labels":["@aws-cdk/aws-pinpoint"],"assignees":["otaviomacedo"]}, {"keywords":["(@aws-cdk/aws-pinpointemail)","(aws-pinpointemail)","(pinpointemail)","(pinpoint email)","(pinpoint-email)"],"labels":["@aws-cdk/aws-pinpointemail"],"assignees":["otaviomacedo"]}, - {"keywords":["(@aws-cdk/aws-qldb)","(aws-qldb)","(qldb)"],"labels":["@aws-cdk/aws-qldb"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-qldb)","(aws-qldb)","(qldb)"],"labels":["@aws-cdk/aws-qldb"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/aws-quicksight)","(aws-quicksight)","(quicksight)"],"labels":["@aws-cdk/aws-quicksight"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/aws-ram)","(aws-ram)","(ram)"],"labels":["@aws-cdk/aws-ram"],"assignees":["madeline-k"]}, - {"keywords":["(@aws-cdk/aws-rds)","(aws-rds)","(rds)"],"labels":["@aws-cdk/aws-rds"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-rds)","(aws-rds)","(rds)"],"labels":["@aws-cdk/aws-rds"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/aws-redshift)","(aws-redshift)","(redshift)","(red shift)","(red-shift)"],"labels":["@aws-cdk/aws-redshift"],"assignees":["njlynch"]}, {"keywords":["(@aws-cdk/aws-resourcegroups)","(aws-resourcegroups)","(resourcegroups)","(resource groups)","(resource-groups)"],"labels":["@aws-cdk/aws-resourcegroups"],"assignees":["madeline-k"]}, {"keywords":["(@aws-cdk/aws-robomaker)","(aws-robomaker)","(robomaker)","(robo maker)","(robo-maker)"],"labels":["@aws-cdk/aws-robomaker"],"assignees":["njlynch"]}, @@ -189,9 +189,9 @@ jobs: {"keywords":["(@aws-cdk/aws-sam)","(aws-sam)","(sam)"],"labels":["@aws-cdk/aws-sam"],"assignees":["njlynch"]}, {"keywords":["(@aws-cdk/aws-sdb)","(aws-sdb)","(sdb)"],"labels":["@aws-cdk/aws-sdb"],"assignees":["njlynch"]}, {"keywords":["(@aws-cdk/aws-secretsmanager)","(aws-secretsmanager)","(secretsmanager)","(secrets manager)","(secrets-manager)"],"labels":["@aws-cdk/aws-secretsmanager"],"assignees":["njlynch"]}, - {"keywords":["(@aws-cdk/aws-securityhub)","(aws-securityhub)","(securityhub)","(security hub)","(security-hub)"],"labels":["@aws-cdk/aws-securityhub"],"assignees":["skinny85"]}, - {"keywords":["(@aws-cdk/aws-servicecatalog)","(aws-servicecatalog)","(servicecatalog)","(service catalog)","(service-catalog)"],"labels":["@aws-cdk/aws-servicecatalog"],"assignees":["skinny85"]}, - {"keywords":["(@aws-cdk/aws-servicecatalogappregistry)","(aws-servicecatalogappregistry)","(servicecatalogappregistry)"],"labels":["@aws-cdk/aws-servicecatalogappregistry"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-securityhub)","(aws-securityhub)","(securityhub)","(security hub)","(security-hub)"],"labels":["@aws-cdk/aws-securityhub"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-servicecatalog)","(aws-servicecatalog)","(servicecatalog)","(service catalog)","(service-catalog)"],"labels":["@aws-cdk/aws-servicecatalog"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-servicecatalogappregistry)","(aws-servicecatalogappregistry)","(servicecatalogappregistry)"],"labels":["@aws-cdk/aws-servicecatalogappregistry"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/aws-servicediscovery)","(aws-servicediscovery)","(servicediscovery)","(service discovery)","(service-discovery)"],"labels":["@aws-cdk/aws-servicediscovery"],"assignees":["madeline-k"]}, {"keywords":["(@aws-cdk/aws-ses)","(aws-ses)","(ses)"],"labels":["@aws-cdk/aws-ses"],"assignees":["otaviomacedo"]}, {"keywords":["(@aws-cdk/aws-ses-actions)","(aws-ses-actions)","(ses-actions)","(ses actions)"],"labels":["@aws-cdk/aws-ses-actions"],"assignees":["otaviomacedo"]}, @@ -200,11 +200,11 @@ jobs: {"keywords":["(@aws-cdk/aws-sns-subscriptions)","(aws-sns-subscriptions)","(sns-subscriptions)","(sns subscriptions)"],"labels":["@aws-cdk/aws-sns-subscriptions"],"assignees":["njlynch"]}, {"keywords":["(@aws-cdk/aws-sqs)","(aws-sqs)","(sqs)"],"labels":["@aws-cdk/aws-sqs"],"assignees":["njlynch"]}, {"keywords":["(@aws-cdk/aws-ssm)","(aws-ssm)","(ssm)"],"labels":["@aws-cdk/aws-ssm"],"assignees":["njlynch"]}, - {"keywords":["(@aws-cdk/aws-sso)","(aws-sso)","(sso)"],"labels":["@aws-cdk/aws-sso"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-sso)","(aws-sso)","(sso)"],"labels":["@aws-cdk/aws-sso"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/aws-stepfunctions)","(aws-stepfunctions)","(stepfunctions)","(step functions)","(step-functions)"],"labels":["@aws-cdk/aws-stepfunctions"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/aws-stepfunctions-tasks)","(aws-stepfunctions-tasks)","(stepfunctions-tasks)","(stepfunctions tasks)"],"labels":["@aws-cdk/aws-stepfunctions-tasks"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/aws-synthetics)","(aws-synthetics)","(synthetics)"],"labels":["@aws-cdk/aws-synthetics"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-timestream)","(aws-timestream)","(timestream)"],"labels":["@aws-cdk/aws-timestream"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-timestream)","(aws-timestream)","(timestream)"],"labels":["@aws-cdk/aws-timestream"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/aws-transfer)","(aws-transfer)","(transfer)"],"labels":["@aws-cdk/aws-transfer"],"assignees":["otaviomacedo"]}, {"keywords":["(@aws-cdk/aws-waf)","(aws-waf)","(waf)"],"labels":["@aws-cdk/aws-waf"],"assignees":["njlynch"]}, {"keywords":["(@aws-cdk/aws-wafregional)","(aws-wafregional)","(wafregional)","(waf regional)","(waf-regional)"],"labels":["@aws-cdk/aws-wafregional"],"assignees":["njlynch"]}, @@ -213,16 +213,16 @@ jobs: {"keywords":["(@aws-cdk/aws-xray)","(aws-xray)","(xray)"],"labels":["@aws-cdk/aws-xray"],"assignees":["nija-at"]}, {"keywords":["(@aws-cdk/cfnspec)","(cfnspec)","(cfn spec)","(cfn-spec)"],"labels":["@aws-cdk/cfnspec"],"assignees":["rix0rrr"]}, {"keywords":["(@aws-cdk/cloud-assembly-schema)","(cloud-assembly-schema)","(cloud assembly schema)"],"labels":["@aws-cdk/cloud-assembly-schema"],"assignees":["rix0rrr"]}, - {"keywords":["(@aws-cdk/cloudformation-diff)","(cloudformation-diff)","(cloudformation diff)","(cfn diff)"],"labels":["@aws-cdk/cloudformation-diff"],"assignees":["skinny85"]}, - {"keywords":["(@aws-cdk/cloudformation-include)","(cloudformation-include)","(cloudformation include)","(cfn include)","(cfn-include)"],"labels":["@aws-cdk/cloudformation-include"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/cloudformation-diff)","(cloudformation-diff)","(cloudformation diff)","(cfn diff)"],"labels":["@aws-cdk/cloudformation-diff"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/cloudformation-include)","(cloudformation-include)","(cloudformation include)","(cfn include)","(cfn-include)"],"labels":["@aws-cdk/cloudformation-include"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/core)","(core)"],"labels":["@aws-cdk/core"],"assignees":["rix0rrr"]}, {"keywords":["(@aws-cdk/custom-resources)","(custom-resources)","(custom resources)"],"labels":["@aws-cdk/custom-resources"],"assignees":["rix0rrr"]}, {"keywords":["(@aws-cdk/cx-api)","(cx-api)","(cx api)"],"labels":["@aws-cdk/cx-api"],"assignees":["rix0rrr"]}, {"keywords":["(@aws-cdk/aws-lambda-layer-awscli)","(aws-lambda-layer-awscli)","(lambda-layer-awscli)"],"labels":["@aws-cdk/aws-lambda-layer-awscli"],"assignees":["rix0rrr"]}, {"keywords":["(@aws-cdk/aws-lambda-layer-kubectl)","(aws-lambda-layer-kubectl)","(lambda-layer-kubectl)"],"labels":["@aws-cdk/aws-lambda-layer-kubectl"],"assignees":["eladb"]}, {"keywords":["(@aws-cdk/pipelines)","(pipelines)","(cdk pipelines)","(cdk-pipelines)"],"labels":["@aws-cdk/pipelines"],"assignees":["rix0rrr"]}, - {"keywords":["(@aws-cdk/region-info)","(region-info)","(region info)"],"labels":["@aws-cdk/region-info"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/region-info)","(region-info)","(region info)"],"labels":["@aws-cdk/region-info"],"assignees":["BenChaimberg"]}, {"keywords":["(aws-cdk-lib)","(cdk-v2)", "(v2)", "(ubergen)"],"labels":["aws-cdk-lib"],"assignees":["nija-at"]}, {"keywords":["(monocdk)","(monocdk-experiment)"],"labels":["monocdk"],"assignees":["nija-at"]}, - {"keywords":["(@aws-cdk/yaml-cfn)","(aws-yaml-cfn)","(yaml-cfn)"],"labels":["@aws-cdk/aws-yaml-cfn"],"assignees":["skinny85"]} + {"keywords":["(@aws-cdk/yaml-cfn)","(aws-yaml-cfn)","(yaml-cfn)"],"labels":["@aws-cdk/aws-yaml-cfn"],"assignees":["BenChaimberg"]} ] From ee191961a8b057a0585e731a67c15a7edd59c79e Mon Sep 17 00:00:00 2001 From: Otavio Macedo Date: Wed, 4 Aug 2021 10:26:15 +0100 Subject: [PATCH 07/99] fix(s3): notifications are broken in some regions (#15884) Happens because `python3.8` doesn't support inline code (i.e `ZipFile`) in some regions. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../aws-lambda-event-sources/test/integ.s3.expected.json | 2 +- .../aws-s3-notifications/test/integ.notifications.expected.json | 2 +- .../test/lambda/integ.bucket-notifications.expected.json | 2 +- .../test/sns/integ.sns-bucket-notifications.expected.json | 2 +- .../test/sqs/integ.bucket-notifications.expected.json | 2 +- .../notifications-resource/notifications-resource-handler.ts | 2 +- .../aws-s3/test/notifications-resource-handler/Dockerfile | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/integ.s3.expected.json b/packages/@aws-cdk/aws-lambda-event-sources/test/integ.s3.expected.json index 7425814364cff..ff71167d19f9e 100644 --- a/packages/@aws-cdk/aws-lambda-event-sources/test/integ.s3.expected.json +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/integ.s3.expected.json @@ -186,7 +186,7 @@ "Arn" ] }, - "Runtime": "python3.8", + "Runtime": "python3.7", "Timeout": 300 }, "DependsOn": [ diff --git a/packages/@aws-cdk/aws-s3-notifications/test/integ.notifications.expected.json b/packages/@aws-cdk/aws-s3-notifications/test/integ.notifications.expected.json index c24d991f31ed5..9026931306ab4 100644 --- a/packages/@aws-cdk/aws-s3-notifications/test/integ.notifications.expected.json +++ b/packages/@aws-cdk/aws-s3-notifications/test/integ.notifications.expected.json @@ -256,7 +256,7 @@ "Arn" ] }, - "Runtime": "python3.8", + "Runtime": "python3.7", "Timeout": 300 }, "DependsOn": [ diff --git a/packages/@aws-cdk/aws-s3-notifications/test/lambda/integ.bucket-notifications.expected.json b/packages/@aws-cdk/aws-s3-notifications/test/lambda/integ.bucket-notifications.expected.json index 42d6d71d603bc..731effea95a53 100644 --- a/packages/@aws-cdk/aws-s3-notifications/test/lambda/integ.bucket-notifications.expected.json +++ b/packages/@aws-cdk/aws-s3-notifications/test/lambda/integ.bucket-notifications.expected.json @@ -246,7 +246,7 @@ "Arn" ] }, - "Runtime": "python3.8", + "Runtime": "python3.7", "Timeout": 300 }, "DependsOn": [ diff --git a/packages/@aws-cdk/aws-s3-notifications/test/sns/integ.sns-bucket-notifications.expected.json b/packages/@aws-cdk/aws-s3-notifications/test/sns/integ.sns-bucket-notifications.expected.json index 74d8086ffe175..47f2a8ea6e0ce 100644 --- a/packages/@aws-cdk/aws-s3-notifications/test/sns/integ.sns-bucket-notifications.expected.json +++ b/packages/@aws-cdk/aws-s3-notifications/test/sns/integ.sns-bucket-notifications.expected.json @@ -204,7 +204,7 @@ "Arn" ] }, - "Runtime": "python3.8", + "Runtime": "python3.7", "Timeout": 300 }, "DependsOn": [ diff --git a/packages/@aws-cdk/aws-s3-notifications/test/sqs/integ.bucket-notifications.expected.json b/packages/@aws-cdk/aws-s3-notifications/test/sqs/integ.bucket-notifications.expected.json index dee0ec6922ed7..229b916beac4b 100644 --- a/packages/@aws-cdk/aws-s3-notifications/test/sqs/integ.bucket-notifications.expected.json +++ b/packages/@aws-cdk/aws-s3-notifications/test/sqs/integ.bucket-notifications.expected.json @@ -193,7 +193,7 @@ "Arn" ] }, - "Runtime": "python3.8", + "Runtime": "python3.7", "Timeout": 300 }, "DependsOn": [ diff --git a/packages/@aws-cdk/aws-s3/lib/notifications-resource/notifications-resource-handler.ts b/packages/@aws-cdk/aws-s3/lib/notifications-resource/notifications-resource-handler.ts index 296bebe265374..c093487a8f105 100644 --- a/packages/@aws-cdk/aws-s3/lib/notifications-resource/notifications-resource-handler.ts +++ b/packages/@aws-cdk/aws-s3/lib/notifications-resource/notifications-resource-handler.ts @@ -87,7 +87,7 @@ export class NotificationsResourceHandler extends Construct { Code: { ZipFile: fs.readFileSync(path.join(__dirname, 'lambda/index.py'), 'utf8') }, Handler: 'index.handler', Role: this.role.roleArn, - Runtime: 'python3.8', + Runtime: 'python3.7', Timeout: 300, }, }); diff --git a/packages/@aws-cdk/aws-s3/test/notifications-resource-handler/Dockerfile b/packages/@aws-cdk/aws-s3/test/notifications-resource-handler/Dockerfile index 916f369bcd353..50dc41b3e6722 100644 --- a/packages/@aws-cdk/aws-s3/test/notifications-resource-handler/Dockerfile +++ b/packages/@aws-cdk/aws-s3/test/notifications-resource-handler/Dockerfile @@ -1,4 +1,4 @@ -FROM public.ecr.aws/lambda/python:3.8 +FROM public.ecr.aws/lambda/python:3.7 ADD . /opt/lambda WORKDIR /opt/lambda From 60e6b4186680af98b538a21e82146fb0a0e84f33 Mon Sep 17 00:00:00 2001 From: AWS CDK Automation <43080478+aws-cdk-automation@users.noreply.github.com> Date: Wed, 4 Aug 2021 13:25:47 +0300 Subject: [PATCH 08/99] feat(cfnspec): cloudformation spec v39.8.0 (#15885) Co-authored-by: AWS CDK Team Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- .../aws-route53recoverycontrol/.eslintrc.js | 3 + .../aws-route53recoverycontrol/.gitignore | 19 + .../aws-route53recoverycontrol/.npmignore | 29 + .../aws-route53recoverycontrol/LICENSE | 201 +++++ .../aws-route53recoverycontrol/NOTICE | 2 + .../aws-route53recoverycontrol/README.md | 20 + .../aws-route53recoverycontrol/jest.config.js | 2 + .../aws-route53recoverycontrol/lib/index.ts | 2 + .../aws-route53recoverycontrol/package.json | 103 +++ .../test/route53recoverycontrol.test.ts | 6 + .../aws-route53recoveryreadiness/.eslintrc.js | 3 + .../aws-route53recoveryreadiness/.gitignore | 19 + .../aws-route53recoveryreadiness/.npmignore | 29 + .../aws-route53recoveryreadiness/LICENSE | 201 +++++ .../aws-route53recoveryreadiness/NOTICE | 2 + .../aws-route53recoveryreadiness/README.md | 20 + .../jest.config.js | 2 + .../aws-route53recoveryreadiness/lib/index.ts | 2 + .../aws-route53recoveryreadiness/package.json | 103 +++ .../test/route53recoveryreadiness.test.ts | 6 + packages/@aws-cdk/cfnspec/CHANGELOG.md | 95 +++ packages/@aws-cdk/cfnspec/cfn.version | 2 +- ...0_CloudFormationResourceSpecification.json | 722 +++++++++++++++++- .../cloudformation-include/package.json | 4 + packages/aws-cdk-lib/package.json | 2 + packages/decdk/package.json | 2 + packages/monocdk/package.json | 2 + 27 files changed, 1583 insertions(+), 20 deletions(-) create mode 100644 packages/@aws-cdk/aws-route53recoverycontrol/.eslintrc.js create mode 100644 packages/@aws-cdk/aws-route53recoverycontrol/.gitignore create mode 100644 packages/@aws-cdk/aws-route53recoverycontrol/.npmignore create mode 100644 packages/@aws-cdk/aws-route53recoverycontrol/LICENSE create mode 100644 packages/@aws-cdk/aws-route53recoverycontrol/NOTICE create mode 100644 packages/@aws-cdk/aws-route53recoverycontrol/README.md create mode 100644 packages/@aws-cdk/aws-route53recoverycontrol/jest.config.js create mode 100644 packages/@aws-cdk/aws-route53recoverycontrol/lib/index.ts create mode 100644 packages/@aws-cdk/aws-route53recoverycontrol/package.json create mode 100644 packages/@aws-cdk/aws-route53recoverycontrol/test/route53recoverycontrol.test.ts create mode 100644 packages/@aws-cdk/aws-route53recoveryreadiness/.eslintrc.js create mode 100644 packages/@aws-cdk/aws-route53recoveryreadiness/.gitignore create mode 100644 packages/@aws-cdk/aws-route53recoveryreadiness/.npmignore create mode 100644 packages/@aws-cdk/aws-route53recoveryreadiness/LICENSE create mode 100644 packages/@aws-cdk/aws-route53recoveryreadiness/NOTICE create mode 100644 packages/@aws-cdk/aws-route53recoveryreadiness/README.md create mode 100644 packages/@aws-cdk/aws-route53recoveryreadiness/jest.config.js create mode 100644 packages/@aws-cdk/aws-route53recoveryreadiness/lib/index.ts create mode 100644 packages/@aws-cdk/aws-route53recoveryreadiness/package.json create mode 100644 packages/@aws-cdk/aws-route53recoveryreadiness/test/route53recoveryreadiness.test.ts diff --git a/packages/@aws-cdk/aws-route53recoverycontrol/.eslintrc.js b/packages/@aws-cdk/aws-route53recoverycontrol/.eslintrc.js new file mode 100644 index 0000000000000..61dd8dd001f63 --- /dev/null +++ b/packages/@aws-cdk/aws-route53recoverycontrol/.eslintrc.js @@ -0,0 +1,3 @@ +const baseConfig = require('cdk-build-tools/config/eslintrc'); +baseConfig.parserOptions.project = __dirname + '/tsconfig.json'; +module.exports = baseConfig; diff --git a/packages/@aws-cdk/aws-route53recoverycontrol/.gitignore b/packages/@aws-cdk/aws-route53recoverycontrol/.gitignore new file mode 100644 index 0000000000000..62ebc95d75ce6 --- /dev/null +++ b/packages/@aws-cdk/aws-route53recoverycontrol/.gitignore @@ -0,0 +1,19 @@ +*.js +*.js.map +*.d.ts +tsconfig.json +node_modules +*.generated.ts +dist +.jsii + +.LAST_BUILD +.nyc_output +coverage +.nycrc +.LAST_PACKAGE +*.snk +nyc.config.js +!.eslintrc.js +!jest.config.js +junit.xml diff --git a/packages/@aws-cdk/aws-route53recoverycontrol/.npmignore b/packages/@aws-cdk/aws-route53recoverycontrol/.npmignore new file mode 100644 index 0000000000000..f931fede67c44 --- /dev/null +++ b/packages/@aws-cdk/aws-route53recoverycontrol/.npmignore @@ -0,0 +1,29 @@ +# 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 diff --git a/packages/@aws-cdk/aws-route53recoverycontrol/LICENSE b/packages/@aws-cdk/aws-route53recoverycontrol/LICENSE new file mode 100644 index 0000000000000..28e4bdcec77ec --- /dev/null +++ b/packages/@aws-cdk/aws-route53recoverycontrol/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-route53recoverycontrol/NOTICE b/packages/@aws-cdk/aws-route53recoverycontrol/NOTICE new file mode 100644 index 0000000000000..5fc3826926b5b --- /dev/null +++ b/packages/@aws-cdk/aws-route53recoverycontrol/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-route53recoverycontrol/README.md b/packages/@aws-cdk/aws-route53recoverycontrol/README.md new file mode 100644 index 0000000000000..9a4113847129c --- /dev/null +++ b/packages/@aws-cdk/aws-route53recoverycontrol/README.md @@ -0,0 +1,20 @@ +# AWS::Route53RecoveryControl Construct Library + + +--- + +![cfn-resources: Stable](https://img.shields.io/badge/cfn--resources-stable-success.svg?style=for-the-badge) + +> All classes with the `Cfn` prefix in this module ([CFN Resources]) are always stable and safe to use. +> +> [CFN Resources]: https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib + +--- + + + +This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project. + +```ts +import route53recoverycontrol = require('@aws-cdk/aws-route53recoverycontrol'); +``` diff --git a/packages/@aws-cdk/aws-route53recoverycontrol/jest.config.js b/packages/@aws-cdk/aws-route53recoverycontrol/jest.config.js new file mode 100644 index 0000000000000..54e28beb9798b --- /dev/null +++ b/packages/@aws-cdk/aws-route53recoverycontrol/jest.config.js @@ -0,0 +1,2 @@ +const baseConfig = require('cdk-build-tools/config/jest.config'); +module.exports = baseConfig; diff --git a/packages/@aws-cdk/aws-route53recoverycontrol/lib/index.ts b/packages/@aws-cdk/aws-route53recoverycontrol/lib/index.ts new file mode 100644 index 0000000000000..ca032e47c0b98 --- /dev/null +++ b/packages/@aws-cdk/aws-route53recoverycontrol/lib/index.ts @@ -0,0 +1,2 @@ +// AWS::Route53RecoveryControl CloudFormation Resources: +export * from './route53recoverycontrol.generated'; diff --git a/packages/@aws-cdk/aws-route53recoverycontrol/package.json b/packages/@aws-cdk/aws-route53recoverycontrol/package.json new file mode 100644 index 0000000000000..8ceaa50512b21 --- /dev/null +++ b/packages/@aws-cdk/aws-route53recoverycontrol/package.json @@ -0,0 +1,103 @@ +{ + "name": "@aws-cdk/aws-route53recoverycontrol", + "version": "0.0.0", + "description": "The CDK Construct Library for AWS::Route53RecoveryControl", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "jsii": { + "outdir": "dist", + "projectReferences": true, + "targets": { + "dotnet": { + "namespace": "Amazon.CDK.AWS.Route53RecoveryControl", + "packageId": "Amazon.CDK.AWS.Route53RecoveryControl", + "signAssembly": true, + "assemblyOriginatorKeyFile": "../../key.snk", + "iconUrl": "https://raw.githubusercontent.com/aws/aws-cdk/master/logo/default-256-dark.png" + }, + "java": { + "package": "software.amazon.awscdk.services.route53recoverycontrol", + "maven": { + "groupId": "software.amazon.awscdk", + "artifactId": "route53recoverycontrol" + } + }, + "python": { + "classifiers": [ + "Framework :: AWS CDK", + "Framework :: AWS CDK :: 1" + ], + "distName": "aws-cdk.aws-route53recoverycontrol", + "module": "aws_cdk.aws_route53recoverycontrol" + } + } + }, + "repository": { + "type": "git", + "url": "https://github.com/aws/aws-cdk.git", + "directory": "packages/@aws-cdk/aws-route53recoverycontrol" + }, + "homepage": "https://github.com/aws/aws-cdk", + "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", + "cfn2ts": "cfn2ts", + "build+test": "yarn build && yarn test", + "build+test+package": "yarn build+test && yarn package", + "compat": "cdk-compat", + "gen": "cfn2ts", + "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": { + "cloudformation": "AWS::Route53RecoveryControl", + "jest": true, + "env": { + "AWSLINT_BASE_CONSTRUCT": "true" + } + }, + "keywords": [ + "aws", + "cdk", + "constructs", + "AWS::Route53RecoveryControl", + "aws-route53recoverycontrol" + ], + "author": { + "name": "Amazon Web Services", + "url": "https://aws.amazon.com", + "organization": true + }, + "license": "Apache-2.0", + "devDependencies": { + "@types/jest": "^26.0.22", + "@aws-cdk/assertions": "0.0.0", + "cdk-build-tools": "0.0.0", + "cfn2ts": "0.0.0", + "pkglint": "0.0.0" + }, + "dependencies": { + "@aws-cdk/core": "0.0.0" + }, + "peerDependencies": { + "@aws-cdk/core": "0.0.0" + }, + "engines": { + "node": ">= 10.13.0 <13 || >=13.7.0" + }, + "stability": "experimental", + "maturity": "cfn-only", + "awscdkio": { + "announce": false + }, + "publishConfig": { + "tag": "latest" + } +} diff --git a/packages/@aws-cdk/aws-route53recoverycontrol/test/route53recoverycontrol.test.ts b/packages/@aws-cdk/aws-route53recoverycontrol/test/route53recoverycontrol.test.ts new file mode 100644 index 0000000000000..465c7bdea0693 --- /dev/null +++ b/packages/@aws-cdk/aws-route53recoverycontrol/test/route53recoverycontrol.test.ts @@ -0,0 +1,6 @@ +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-route53recoveryreadiness/.eslintrc.js b/packages/@aws-cdk/aws-route53recoveryreadiness/.eslintrc.js new file mode 100644 index 0000000000000..61dd8dd001f63 --- /dev/null +++ b/packages/@aws-cdk/aws-route53recoveryreadiness/.eslintrc.js @@ -0,0 +1,3 @@ +const baseConfig = require('cdk-build-tools/config/eslintrc'); +baseConfig.parserOptions.project = __dirname + '/tsconfig.json'; +module.exports = baseConfig; diff --git a/packages/@aws-cdk/aws-route53recoveryreadiness/.gitignore b/packages/@aws-cdk/aws-route53recoveryreadiness/.gitignore new file mode 100644 index 0000000000000..62ebc95d75ce6 --- /dev/null +++ b/packages/@aws-cdk/aws-route53recoveryreadiness/.gitignore @@ -0,0 +1,19 @@ +*.js +*.js.map +*.d.ts +tsconfig.json +node_modules +*.generated.ts +dist +.jsii + +.LAST_BUILD +.nyc_output +coverage +.nycrc +.LAST_PACKAGE +*.snk +nyc.config.js +!.eslintrc.js +!jest.config.js +junit.xml diff --git a/packages/@aws-cdk/aws-route53recoveryreadiness/.npmignore b/packages/@aws-cdk/aws-route53recoveryreadiness/.npmignore new file mode 100644 index 0000000000000..f931fede67c44 --- /dev/null +++ b/packages/@aws-cdk/aws-route53recoveryreadiness/.npmignore @@ -0,0 +1,29 @@ +# 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 diff --git a/packages/@aws-cdk/aws-route53recoveryreadiness/LICENSE b/packages/@aws-cdk/aws-route53recoveryreadiness/LICENSE new file mode 100644 index 0000000000000..28e4bdcec77ec --- /dev/null +++ b/packages/@aws-cdk/aws-route53recoveryreadiness/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-route53recoveryreadiness/NOTICE b/packages/@aws-cdk/aws-route53recoveryreadiness/NOTICE new file mode 100644 index 0000000000000..5fc3826926b5b --- /dev/null +++ b/packages/@aws-cdk/aws-route53recoveryreadiness/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-route53recoveryreadiness/README.md b/packages/@aws-cdk/aws-route53recoveryreadiness/README.md new file mode 100644 index 0000000000000..fd92f9a6d4954 --- /dev/null +++ b/packages/@aws-cdk/aws-route53recoveryreadiness/README.md @@ -0,0 +1,20 @@ +# AWS::Route53RecoveryReadiness Construct Library + + +--- + +![cfn-resources: Stable](https://img.shields.io/badge/cfn--resources-stable-success.svg?style=for-the-badge) + +> All classes with the `Cfn` prefix in this module ([CFN Resources]) are always stable and safe to use. +> +> [CFN Resources]: https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib + +--- + + + +This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project. + +```ts +import route53recoveryreadiness = require('@aws-cdk/aws-route53recoveryreadiness'); +``` diff --git a/packages/@aws-cdk/aws-route53recoveryreadiness/jest.config.js b/packages/@aws-cdk/aws-route53recoveryreadiness/jest.config.js new file mode 100644 index 0000000000000..54e28beb9798b --- /dev/null +++ b/packages/@aws-cdk/aws-route53recoveryreadiness/jest.config.js @@ -0,0 +1,2 @@ +const baseConfig = require('cdk-build-tools/config/jest.config'); +module.exports = baseConfig; diff --git a/packages/@aws-cdk/aws-route53recoveryreadiness/lib/index.ts b/packages/@aws-cdk/aws-route53recoveryreadiness/lib/index.ts new file mode 100644 index 0000000000000..92d4e5587a6c6 --- /dev/null +++ b/packages/@aws-cdk/aws-route53recoveryreadiness/lib/index.ts @@ -0,0 +1,2 @@ +// AWS::Route53RecoveryReadiness CloudFormation Resources: +export * from './route53recoveryreadiness.generated'; diff --git a/packages/@aws-cdk/aws-route53recoveryreadiness/package.json b/packages/@aws-cdk/aws-route53recoveryreadiness/package.json new file mode 100644 index 0000000000000..afa6c384f2f7b --- /dev/null +++ b/packages/@aws-cdk/aws-route53recoveryreadiness/package.json @@ -0,0 +1,103 @@ +{ + "name": "@aws-cdk/aws-route53recoveryreadiness", + "version": "0.0.0", + "description": "The CDK Construct Library for AWS::Route53RecoveryReadiness", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "jsii": { + "outdir": "dist", + "projectReferences": true, + "targets": { + "dotnet": { + "namespace": "Amazon.CDK.AWS.Route53RecoveryReadiness", + "packageId": "Amazon.CDK.AWS.Route53RecoveryReadiness", + "signAssembly": true, + "assemblyOriginatorKeyFile": "../../key.snk", + "iconUrl": "https://raw.githubusercontent.com/aws/aws-cdk/master/logo/default-256-dark.png" + }, + "java": { + "package": "software.amazon.awscdk.services.route53recoveryreadiness", + "maven": { + "groupId": "software.amazon.awscdk", + "artifactId": "route53recoveryreadiness" + } + }, + "python": { + "classifiers": [ + "Framework :: AWS CDK", + "Framework :: AWS CDK :: 1" + ], + "distName": "aws-cdk.aws-route53recoveryreadiness", + "module": "aws_cdk.aws_route53recoveryreadiness" + } + } + }, + "repository": { + "type": "git", + "url": "https://github.com/aws/aws-cdk.git", + "directory": "packages/@aws-cdk/aws-route53recoveryreadiness" + }, + "homepage": "https://github.com/aws/aws-cdk", + "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", + "cfn2ts": "cfn2ts", + "build+test": "yarn build && yarn test", + "build+test+package": "yarn build+test && yarn package", + "compat": "cdk-compat", + "gen": "cfn2ts", + "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": { + "cloudformation": "AWS::Route53RecoveryReadiness", + "jest": true, + "env": { + "AWSLINT_BASE_CONSTRUCT": "true" + } + }, + "keywords": [ + "aws", + "cdk", + "constructs", + "AWS::Route53RecoveryReadiness", + "aws-route53recoveryreadiness" + ], + "author": { + "name": "Amazon Web Services", + "url": "https://aws.amazon.com", + "organization": true + }, + "license": "Apache-2.0", + "devDependencies": { + "@types/jest": "^26.0.22", + "@aws-cdk/assertions": "0.0.0", + "cdk-build-tools": "0.0.0", + "cfn2ts": "0.0.0", + "pkglint": "0.0.0" + }, + "dependencies": { + "@aws-cdk/core": "0.0.0" + }, + "peerDependencies": { + "@aws-cdk/core": "0.0.0" + }, + "engines": { + "node": ">= 10.13.0 <13 || >=13.7.0" + }, + "stability": "experimental", + "maturity": "cfn-only", + "awscdkio": { + "announce": false + }, + "publishConfig": { + "tag": "latest" + } +} diff --git a/packages/@aws-cdk/aws-route53recoveryreadiness/test/route53recoveryreadiness.test.ts b/packages/@aws-cdk/aws-route53recoveryreadiness/test/route53recoveryreadiness.test.ts new file mode 100644 index 0000000000000..465c7bdea0693 --- /dev/null +++ b/packages/@aws-cdk/aws-route53recoveryreadiness/test/route53recoveryreadiness.test.ts @@ -0,0 +1,6 @@ +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/cfnspec/CHANGELOG.md b/packages/@aws-cdk/cfnspec/CHANGELOG.md index 2e7ba5e22bf56..cbadd0a7eda90 100644 --- a/packages/@aws-cdk/cfnspec/CHANGELOG.md +++ b/packages/@aws-cdk/cfnspec/CHANGELOG.md @@ -1,3 +1,98 @@ +# CloudFormation Resource Specification v39.8.0 + +## New Resource Types + +* AWS::Route53RecoveryControl::Cluster +* AWS::Route53RecoveryControl::ControlPanel +* AWS::Route53RecoveryControl::RoutingControl +* AWS::Route53RecoveryControl::SafetyRule +* AWS::Route53RecoveryReadiness::Cell +* AWS::Route53RecoveryReadiness::ReadinessCheck +* AWS::Route53RecoveryReadiness::RecoveryGroup +* AWS::Route53RecoveryReadiness::ResourceSet + +## Attribute Changes + + +## Property Changes + +* AWS::DataBrew::Job DatabaseOutputs (__added__) +* AWS::DataBrew::Job ProfileConfiguration (__added__) +* AWS::DataSync::LocationNFS MountOptions.UpdateType (__changed__) + * Old: Immutable + * New: Mutable +* AWS::DataSync::LocationNFS OnPremConfig.UpdateType (__changed__) + * Old: Immutable + * New: Mutable +* AWS::DataSync::LocationNFS Subdirectory.UpdateType (__changed__) + * Old: Immutable + * New: Mutable +* AWS::DataSync::LocationObjectStorage AccessKey.UpdateType (__changed__) + * Old: Immutable + * New: Mutable +* AWS::DataSync::LocationObjectStorage AgentArns.UpdateType (__changed__) + * Old: Immutable + * New: Mutable +* AWS::DataSync::LocationObjectStorage SecretKey.UpdateType (__changed__) + * Old: Immutable + * New: Mutable +* AWS::DataSync::LocationObjectStorage ServerPort.UpdateType (__changed__) + * Old: Immutable + * New: Mutable +* AWS::DataSync::LocationObjectStorage ServerProtocol.UpdateType (__changed__) + * Old: Immutable + * New: Mutable +* AWS::DataSync::LocationObjectStorage Subdirectory.UpdateType (__changed__) + * Old: Immutable + * New: Mutable +* AWS::DataSync::LocationSMB AgentArns.UpdateType (__changed__) + * Old: Immutable + * New: Mutable +* AWS::DataSync::LocationSMB Domain.UpdateType (__changed__) + * Old: Immutable + * New: Mutable +* AWS::DataSync::LocationSMB MountOptions.UpdateType (__changed__) + * Old: Immutable + * New: Mutable +* AWS::DataSync::LocationSMB Password.UpdateType (__changed__) + * Old: Immutable + * New: Mutable +* AWS::DataSync::LocationSMB Subdirectory.UpdateType (__changed__) + * Old: Immutable + * New: Mutable +* AWS::DataSync::LocationSMB User.UpdateType (__changed__) + * Old: Immutable + * New: Mutable +* AWS::S3Outposts::Endpoint AccessType (__added__) +* AWS::S3Outposts::Endpoint CustomerOwnedIpv4Pool (__added__) + +## Property Type Changes + +* AWS::DLM::LifecyclePolicy.CrossRegionCopyDeprecateRule (__added__) +* AWS::DLM::LifecyclePolicy.DeprecateRule (__added__) +* AWS::DataBrew::Job.ColumnSelector (__added__) +* AWS::DataBrew::Job.ColumnStatisticsConfiguration (__added__) +* AWS::DataBrew::Job.DatabaseOutput (__added__) +* AWS::DataBrew::Job.ParameterMap (__added__) +* AWS::DataBrew::Job.ProfileConfiguration (__added__) +* AWS::DataBrew::Job.StatisticOverride (__added__) +* AWS::DataBrew::Job.StatisticsConfiguration (__added__) +* AWS::FSx::FileSystem.AuditLogConfiguration (__added__) +* AWS::DLM::LifecyclePolicy.CrossRegionCopyRule DeprecateRule (__added__) +* AWS::DLM::LifecyclePolicy.Schedule DeprecateRule (__added__) +* AWS::DataSync::LocationNFS.MountOptions Version.UpdateType (__changed__) + * Old: Immutable + * New: Mutable +* AWS::DataSync::LocationNFS.OnPremConfig AgentArns.UpdateType (__changed__) + * Old: Immutable + * New: Mutable +* AWS::DataSync::LocationSMB.MountOptions Version.UpdateType (__changed__) + * Old: Immutable + * New: Mutable +* AWS::DataSync::Task.Options SecurityDescriptorCopyFlags (__added__) +* AWS::FSx::FileSystem.WindowsConfiguration AuditLogConfiguration (__added__) + + # CloudFormation Resource Specification v39.7.0 ## New Resource Types diff --git a/packages/@aws-cdk/cfnspec/cfn.version b/packages/@aws-cdk/cfnspec/cfn.version index ac8cf4b235806..212ba4596ef15 100644 --- a/packages/@aws-cdk/cfnspec/cfn.version +++ b/packages/@aws-cdk/cfnspec/cfn.version @@ -1 +1 @@ -39.7.0 +39.8.0 diff --git a/packages/@aws-cdk/cfnspec/spec-source/000_CloudFormationResourceSpecification.json b/packages/@aws-cdk/cfnspec/spec-source/000_CloudFormationResourceSpecification.json index 7ea26213ba6ce..5e6a900098e55 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/000_CloudFormationResourceSpecification.json +++ b/packages/@aws-cdk/cfnspec/spec-source/000_CloudFormationResourceSpecification.json @@ -15572,6 +15572,23 @@ } } }, + "AWS::DLM::LifecyclePolicy.CrossRegionCopyDeprecateRule": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dlm-lifecyclepolicy-crossregioncopydeprecaterule.html", + "Properties": { + "Interval": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dlm-lifecyclepolicy-crossregioncopydeprecaterule.html#cfn-dlm-lifecyclepolicy-crossregioncopydeprecaterule-interval", + "PrimitiveType": "Integer", + "Required": true, + "UpdateType": "Mutable" + }, + "IntervalUnit": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dlm-lifecyclepolicy-crossregioncopydeprecaterule.html#cfn-dlm-lifecyclepolicy-crossregioncopydeprecaterule-intervalunit", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } + }, "AWS::DLM::LifecyclePolicy.CrossRegionCopyRetainRule": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dlm-lifecyclepolicy-crossregioncopyretainrule.html", "Properties": { @@ -15604,6 +15621,12 @@ "Required": false, "UpdateType": "Mutable" }, + "DeprecateRule": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dlm-lifecyclepolicy-crossregioncopyrule.html#cfn-dlm-lifecyclepolicy-crossregioncopyrule-deprecaterule", + "Required": false, + "Type": "CrossRegionCopyDeprecateRule", + "UpdateType": "Mutable" + }, "Encrypted": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dlm-lifecyclepolicy-crossregioncopyrule.html#cfn-dlm-lifecyclepolicy-crossregioncopyrule-encrypted", "PrimitiveType": "Boolean", @@ -15630,6 +15653,29 @@ } } }, + "AWS::DLM::LifecyclePolicy.DeprecateRule": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dlm-lifecyclepolicy-deprecaterule.html", + "Properties": { + "Count": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dlm-lifecyclepolicy-deprecaterule.html#cfn-dlm-lifecyclepolicy-deprecaterule-count", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + }, + "Interval": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dlm-lifecyclepolicy-deprecaterule.html#cfn-dlm-lifecyclepolicy-deprecaterule-interval", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + }, + "IntervalUnit": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dlm-lifecyclepolicy-deprecaterule.html#cfn-dlm-lifecyclepolicy-deprecaterule-intervalunit", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, "AWS::DLM::LifecyclePolicy.EncryptionConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dlm-lifecyclepolicy-encryptionconfiguration.html", "Properties": { @@ -15838,6 +15884,12 @@ "Type": "List", "UpdateType": "Mutable" }, + "DeprecateRule": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dlm-lifecyclepolicy-schedule.html#cfn-dlm-lifecyclepolicy-schedule-deprecaterule", + "Required": false, + "Type": "DeprecateRule", + "UpdateType": "Mutable" + }, "FastRestoreRule": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dlm-lifecyclepolicy-schedule.html#cfn-dlm-lifecyclepolicy-schedule-fastrestorerule", "Required": false, @@ -16633,6 +16685,41 @@ } } }, + "AWS::DataBrew::Job.ColumnSelector": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-databrew-job-columnselector.html", + "Properties": { + "Name": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-databrew-job-columnselector.html#cfn-databrew-job-columnselector-name", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "Regex": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-databrew-job-columnselector.html#cfn-databrew-job-columnselector-regex", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, + "AWS::DataBrew::Job.ColumnStatisticsConfiguration": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-databrew-job-columnstatisticsconfiguration.html", + "Properties": { + "Selectors": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-databrew-job-columnstatisticsconfiguration.html#cfn-databrew-job-columnstatisticsconfiguration-selectors", + "ItemType": "ColumnSelector", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "Statistics": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-databrew-job-columnstatisticsconfiguration.html#cfn-databrew-job-columnstatisticsconfiguration-statistics", + "Required": true, + "Type": "StatisticsConfiguration", + "UpdateType": "Mutable" + } + } + }, "AWS::DataBrew::Job.CsvOutputOptions": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-databrew-job-csvoutputoptions.html", "Properties": { @@ -16685,6 +16772,29 @@ } } }, + "AWS::DataBrew::Job.DatabaseOutput": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-databrew-job-databaseoutput.html", + "Properties": { + "DatabaseOptions": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-databrew-job-databaseoutput.html#cfn-databrew-job-databaseoutput-databaseoptions", + "Required": true, + "Type": "DatabaseTableOutputOptions", + "UpdateType": "Mutable" + }, + "DatabaseOutputMode": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-databrew-job-databaseoutput.html#cfn-databrew-job-databaseoutput-databaseoutputmode", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "GlueConnectionName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-databrew-job-databaseoutput.html#cfn-databrew-job-databaseoutput-glueconnectionname", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } + }, "AWS::DataBrew::Job.DatabaseTableOutputOptions": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-databrew-job-databasetableoutputoptions.html", "Properties": { @@ -16790,6 +16900,34 @@ } } }, + "AWS::DataBrew::Job.ParameterMap": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-databrew-job-parametermap.html" + }, + "AWS::DataBrew::Job.ProfileConfiguration": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-databrew-job-profileconfiguration.html", + "Properties": { + "ColumnStatisticsConfigurations": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-databrew-job-profileconfiguration.html#cfn-databrew-job-profileconfiguration-columnstatisticsconfigurations", + "ItemType": "ColumnStatisticsConfiguration", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "DatasetStatisticsConfiguration": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-databrew-job-profileconfiguration.html#cfn-databrew-job-profileconfiguration-datasetstatisticsconfiguration", + "Required": false, + "Type": "StatisticsConfiguration", + "UpdateType": "Mutable" + }, + "ProfileColumns": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-databrew-job-profileconfiguration.html#cfn-databrew-job-profileconfiguration-profilecolumns", + "ItemType": "ColumnSelector", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + } + } + }, "AWS::DataBrew::Job.Recipe": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-databrew-job-recipe.html", "Properties": { @@ -16835,6 +16973,42 @@ } } }, + "AWS::DataBrew::Job.StatisticOverride": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-databrew-job-statisticoverride.html", + "Properties": { + "Parameters": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-databrew-job-statisticoverride.html#cfn-databrew-job-statisticoverride-parameters", + "Required": true, + "Type": "ParameterMap", + "UpdateType": "Mutable" + }, + "Statistic": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-databrew-job-statisticoverride.html#cfn-databrew-job-statisticoverride-statistic", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } + }, + "AWS::DataBrew::Job.StatisticsConfiguration": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-databrew-job-statisticsconfiguration.html", + "Properties": { + "IncludedStatistics": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-databrew-job-statisticsconfiguration.html#cfn-databrew-job-statisticsconfiguration-includedstatistics", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "Overrides": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-databrew-job-statisticsconfiguration.html#cfn-databrew-job-statisticsconfiguration-overrides", + "ItemType": "StatisticOverride", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + } + } + }, "AWS::DataBrew::Project.Sample": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-databrew-project-sample.html", "Properties": { @@ -17734,7 +17908,7 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-datasync-locationnfs-mountoptions.html#cfn-datasync-locationnfs-mountoptions-version", "PrimitiveType": "String", "Required": false, - "UpdateType": "Immutable" + "UpdateType": "Mutable" } } }, @@ -17746,7 +17920,7 @@ "PrimitiveItemType": "String", "Required": true, "Type": "List", - "UpdateType": "Immutable" + "UpdateType": "Mutable" } } }, @@ -17768,7 +17942,7 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-datasync-locationsmb-mountoptions.html#cfn-datasync-locationsmb-mountoptions-version", "PrimitiveType": "String", "Required": false, - "UpdateType": "Immutable" + "UpdateType": "Mutable" } } }, @@ -17846,6 +18020,12 @@ "Required": false, "UpdateType": "Mutable" }, + "SecurityDescriptorCopyFlags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-datasync-task-options.html#cfn-datasync-task-options-securitydescriptorcopyflags", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, "TaskQueueing": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-datasync-task-options.html#cfn-datasync-task-options-taskqueueing", "PrimitiveType": "String", @@ -27165,6 +27345,29 @@ } } }, + "AWS::FSx::FileSystem.AuditLogConfiguration": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-fsx-filesystem-windowsconfiguration-auditlogconfiguration.html", + "Properties": { + "AuditLogDestination": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-fsx-filesystem-windowsconfiguration-auditlogconfiguration.html#cfn-fsx-filesystem-windowsconfiguration-auditlogconfiguration-auditlogdestination", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "FileAccessAuditLogLevel": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-fsx-filesystem-windowsconfiguration-auditlogconfiguration.html#cfn-fsx-filesystem-windowsconfiguration-auditlogconfiguration-fileaccessauditloglevel", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "FileShareAccessAuditLogLevel": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-fsx-filesystem-windowsconfiguration-auditlogconfiguration.html#cfn-fsx-filesystem-windowsconfiguration-auditlogconfiguration-fileshareaccessauditloglevel", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } + }, "AWS::FSx::FileSystem.LustreConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-fsx-filesystem-lustreconfiguration.html", "Properties": { @@ -27300,6 +27503,12 @@ "Type": "List", "UpdateType": "Mutable" }, + "AuditLogConfiguration": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-fsx-filesystem-windowsconfiguration.html#cfn-fsx-filesystem-windowsconfiguration-auditlogconfiguration", + "Required": false, + "Type": "AuditLogConfiguration", + "UpdateType": "Mutable" + }, "AutomaticBackupRetentionDays": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-fsx-filesystem-windowsconfiguration.html#cfn-fsx-filesystem-windowsconfiguration-automaticbackupretentiondays", "PrimitiveType": "Integer", @@ -52866,6 +53075,199 @@ } } }, + "AWS::Route53RecoveryControl::Cluster.ClusterEndpoint": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoverycontrol-cluster-clusterendpoint.html", + "Properties": { + "Endpoint": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoverycontrol-cluster-clusterendpoint.html#cfn-route53recoverycontrol-cluster-clusterendpoint-endpoint", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "Region": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoverycontrol-cluster-clusterendpoint.html#cfn-route53recoverycontrol-cluster-clusterendpoint-region", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, + "AWS::Route53RecoveryControl::SafetyRule.AssertionRule": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoverycontrol-safetyrule-assertionrule.html", + "Properties": { + "AssertedControls": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoverycontrol-safetyrule-assertionrule.html#cfn-route53recoverycontrol-safetyrule-assertionrule-assertedcontrols", + "PrimitiveItemType": "String", + "Required": true, + "Type": "List", + "UpdateType": "Mutable" + }, + "WaitPeriodMs": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoverycontrol-safetyrule-assertionrule.html#cfn-route53recoverycontrol-safetyrule-assertionrule-waitperiodms", + "PrimitiveType": "Integer", + "Required": true, + "UpdateType": "Mutable" + } + } + }, + "AWS::Route53RecoveryControl::SafetyRule.GatingRule": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoverycontrol-safetyrule-gatingrule.html", + "Properties": { + "GatingControls": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoverycontrol-safetyrule-gatingrule.html#cfn-route53recoverycontrol-safetyrule-gatingrule-gatingcontrols", + "PrimitiveItemType": "String", + "Required": true, + "Type": "List", + "UpdateType": "Mutable" + }, + "TargetControls": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoverycontrol-safetyrule-gatingrule.html#cfn-route53recoverycontrol-safetyrule-gatingrule-targetcontrols", + "PrimitiveItemType": "String", + "Required": true, + "Type": "List", + "UpdateType": "Mutable" + }, + "WaitPeriodMs": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoverycontrol-safetyrule-gatingrule.html#cfn-route53recoverycontrol-safetyrule-gatingrule-waitperiodms", + "PrimitiveType": "Integer", + "Required": true, + "UpdateType": "Mutable" + } + } + }, + "AWS::Route53RecoveryControl::SafetyRule.RuleConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoverycontrol-safetyrule-ruleconfig.html", + "Properties": { + "Inverted": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoverycontrol-safetyrule-ruleconfig.html#cfn-route53recoverycontrol-safetyrule-ruleconfig-inverted", + "PrimitiveType": "Boolean", + "Required": true, + "UpdateType": "Immutable" + }, + "Threshold": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoverycontrol-safetyrule-ruleconfig.html#cfn-route53recoverycontrol-safetyrule-ruleconfig-threshold", + "PrimitiveType": "Integer", + "Required": true, + "UpdateType": "Immutable" + }, + "Type": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoverycontrol-safetyrule-ruleconfig.html#cfn-route53recoverycontrol-safetyrule-ruleconfig-type", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + } + } + }, + "AWS::Route53RecoveryReadiness::ResourceSet.DNSTargetResource": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoveryreadiness-resourceset-dnstargetresource.html", + "Properties": { + "DomainName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoveryreadiness-resourceset-dnstargetresource.html#cfn-route53recoveryreadiness-resourceset-dnstargetresource-domainname", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "HostedZoneArn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoveryreadiness-resourceset-dnstargetresource.html#cfn-route53recoveryreadiness-resourceset-dnstargetresource-hostedzonearn", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "RecordSetId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoveryreadiness-resourceset-dnstargetresource.html#cfn-route53recoveryreadiness-resourceset-dnstargetresource-recordsetid", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "RecordType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoveryreadiness-resourceset-dnstargetresource.html#cfn-route53recoveryreadiness-resourceset-dnstargetresource-recordtype", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "TargetResource": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoveryreadiness-resourceset-dnstargetresource.html#cfn-route53recoveryreadiness-resourceset-dnstargetresource-targetresource", + "Required": false, + "Type": "TargetResource", + "UpdateType": "Mutable" + } + } + }, + "AWS::Route53RecoveryReadiness::ResourceSet.NLBResource": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoveryreadiness-resourceset-nlbresource.html", + "Properties": { + "Arn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoveryreadiness-resourceset-nlbresource.html#cfn-route53recoveryreadiness-resourceset-nlbresource-arn", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, + "AWS::Route53RecoveryReadiness::ResourceSet.R53ResourceRecord": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoveryreadiness-resourceset-r53resourcerecord.html", + "Properties": { + "DomainName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoveryreadiness-resourceset-r53resourcerecord.html#cfn-route53recoveryreadiness-resourceset-r53resourcerecord-domainname", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "RecordSetId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoveryreadiness-resourceset-r53resourcerecord.html#cfn-route53recoveryreadiness-resourceset-r53resourcerecord-recordsetid", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, + "AWS::Route53RecoveryReadiness::ResourceSet.Resource": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoveryreadiness-resourceset-resource.html", + "Properties": { + "ComponentId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoveryreadiness-resourceset-resource.html#cfn-route53recoveryreadiness-resourceset-resource-componentid", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "DnsTargetResource": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoveryreadiness-resourceset-resource.html#cfn-route53recoveryreadiness-resourceset-resource-dnstargetresource", + "Required": false, + "Type": "DNSTargetResource", + "UpdateType": "Mutable" + }, + "ReadinessScopes": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoveryreadiness-resourceset-resource.html#cfn-route53recoveryreadiness-resourceset-resource-readinessscopes", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "ResourceArn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoveryreadiness-resourceset-resource.html#cfn-route53recoveryreadiness-resourceset-resource-resourcearn", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, + "AWS::Route53RecoveryReadiness::ResourceSet.TargetResource": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoveryreadiness-resourceset-targetresource.html", + "Properties": { + "NLBResource": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoveryreadiness-resourceset-targetresource.html#cfn-route53recoveryreadiness-resourceset-targetresource-nlbresource", + "Required": false, + "Type": "NLBResource", + "UpdateType": "Mutable" + }, + "R53Resource": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoveryreadiness-resourceset-targetresource.html#cfn-route53recoveryreadiness-resourceset-targetresource-r53resource", + "Required": false, + "Type": "R53ResourceRecord", + "UpdateType": "Mutable" + } + } + }, "AWS::Route53Resolver::FirewallRuleGroup.FirewallRule": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53resolver-firewallrulegroup-firewallrule.html", "Properties": { @@ -61123,7 +61525,7 @@ } } }, - "ResourceSpecificationVersion": "39.7.0", + "ResourceSpecificationVersion": "39.8.0", "ResourceTypes": { "AWS::ACMPCA::Certificate": { "Attributes": { @@ -70946,6 +71348,13 @@ "Type": "List", "UpdateType": "Mutable" }, + "DatabaseOutputs": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-databrew-job.html#cfn-databrew-job-databaseoutputs", + "ItemType": "DatabaseOutput", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, "DatasetName": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-databrew-job.html#cfn-databrew-job-datasetname", "PrimitiveType": "String", @@ -71007,6 +71416,12 @@ "Type": "List", "UpdateType": "Mutable" }, + "ProfileConfiguration": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-databrew-job.html#cfn-databrew-job-profileconfiguration", + "Required": false, + "Type": "ProfileConfiguration", + "UpdateType": "Mutable" + }, "ProjectName": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-databrew-job.html#cfn-databrew-job-projectname", "PrimitiveType": "String", @@ -71376,13 +71791,13 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-datasync-locationnfs.html#cfn-datasync-locationnfs-mountoptions", "Required": false, "Type": "MountOptions", - "UpdateType": "Immutable" + "UpdateType": "Mutable" }, "OnPremConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-datasync-locationnfs.html#cfn-datasync-locationnfs-onpremconfig", "Required": true, "Type": "OnPremConfig", - "UpdateType": "Immutable" + "UpdateType": "Mutable" }, "ServerHostname": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-datasync-locationnfs.html#cfn-datasync-locationnfs-serverhostname", @@ -71394,7 +71809,7 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-datasync-locationnfs.html#cfn-datasync-locationnfs-subdirectory", "PrimitiveType": "String", "Required": true, - "UpdateType": "Immutable" + "UpdateType": "Mutable" }, "Tags": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-datasync-locationnfs.html#cfn-datasync-locationnfs-tags", @@ -71421,14 +71836,14 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-datasync-locationobjectstorage.html#cfn-datasync-locationobjectstorage-accesskey", "PrimitiveType": "String", "Required": false, - "UpdateType": "Immutable" + "UpdateType": "Mutable" }, "AgentArns": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-datasync-locationobjectstorage.html#cfn-datasync-locationobjectstorage-agentarns", "PrimitiveItemType": "String", "Required": true, "Type": "List", - "UpdateType": "Immutable" + "UpdateType": "Mutable" }, "BucketName": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-datasync-locationobjectstorage.html#cfn-datasync-locationobjectstorage-bucketname", @@ -71440,7 +71855,7 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-datasync-locationobjectstorage.html#cfn-datasync-locationobjectstorage-secretkey", "PrimitiveType": "String", "Required": false, - "UpdateType": "Immutable" + "UpdateType": "Mutable" }, "ServerHostname": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-datasync-locationobjectstorage.html#cfn-datasync-locationobjectstorage-serverhostname", @@ -71452,19 +71867,19 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-datasync-locationobjectstorage.html#cfn-datasync-locationobjectstorage-serverport", "PrimitiveType": "Integer", "Required": false, - "UpdateType": "Immutable" + "UpdateType": "Mutable" }, "ServerProtocol": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-datasync-locationobjectstorage.html#cfn-datasync-locationobjectstorage-serverprotocol", "PrimitiveType": "String", "Required": false, - "UpdateType": "Immutable" + "UpdateType": "Mutable" }, "Subdirectory": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-datasync-locationobjectstorage.html#cfn-datasync-locationobjectstorage-subdirectory", "PrimitiveType": "String", "Required": false, - "UpdateType": "Immutable" + "UpdateType": "Mutable" }, "Tags": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-datasync-locationobjectstorage.html#cfn-datasync-locationobjectstorage-tags", @@ -71537,25 +71952,25 @@ "PrimitiveItemType": "String", "Required": true, "Type": "List", - "UpdateType": "Immutable" + "UpdateType": "Mutable" }, "Domain": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-datasync-locationsmb.html#cfn-datasync-locationsmb-domain", "PrimitiveType": "String", "Required": false, - "UpdateType": "Immutable" + "UpdateType": "Mutable" }, "MountOptions": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-datasync-locationsmb.html#cfn-datasync-locationsmb-mountoptions", "Required": false, "Type": "MountOptions", - "UpdateType": "Immutable" + "UpdateType": "Mutable" }, "Password": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-datasync-locationsmb.html#cfn-datasync-locationsmb-password", "PrimitiveType": "String", "Required": true, - "UpdateType": "Immutable" + "UpdateType": "Mutable" }, "ServerHostname": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-datasync-locationsmb.html#cfn-datasync-locationsmb-serverhostname", @@ -71567,7 +71982,7 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-datasync-locationsmb.html#cfn-datasync-locationsmb-subdirectory", "PrimitiveType": "String", "Required": true, - "UpdateType": "Immutable" + "UpdateType": "Mutable" }, "Tags": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-datasync-locationsmb.html#cfn-datasync-locationsmb-tags", @@ -71581,7 +71996,7 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-datasync-locationsmb.html#cfn-datasync-locationsmb-user", "PrimitiveType": "String", "Required": true, - "UpdateType": "Immutable" + "UpdateType": "Mutable" } } }, @@ -93167,6 +93582,263 @@ } } }, + "AWS::Route53RecoveryControl::Cluster": { + "Attributes": { + "ClusterArn": { + "PrimitiveType": "String" + }, + "ClusterEndpoints": { + "ItemType": "ClusterEndpoint", + "Type": "List" + }, + "Status": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53recoverycontrol-cluster.html", + "Properties": { + "Name": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53recoverycontrol-cluster.html#cfn-route53recoverycontrol-cluster-name", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + } + } + }, + "AWS::Route53RecoveryControl::ControlPanel": { + "Attributes": { + "ControlPanelArn": { + "PrimitiveType": "String" + }, + "DefaultControlPanel": { + "PrimitiveType": "Boolean" + }, + "RoutingControlCount": { + "PrimitiveType": "Integer" + }, + "Status": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53recoverycontrol-controlpanel.html", + "Properties": { + "ClusterArn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53recoverycontrol-controlpanel.html#cfn-route53recoverycontrol-controlpanel-clusterarn", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "Name": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53recoverycontrol-controlpanel.html#cfn-route53recoverycontrol-controlpanel-name", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } + }, + "AWS::Route53RecoveryControl::RoutingControl": { + "Attributes": { + "RoutingControlArn": { + "PrimitiveType": "String" + }, + "Status": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53recoverycontrol-routingcontrol.html", + "Properties": { + "ClusterArn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53recoverycontrol-routingcontrol.html#cfn-route53recoverycontrol-routingcontrol-clusterarn", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "ControlPanelArn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53recoverycontrol-routingcontrol.html#cfn-route53recoverycontrol-routingcontrol-controlpanelarn", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "Name": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53recoverycontrol-routingcontrol.html#cfn-route53recoverycontrol-routingcontrol-name", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } + }, + "AWS::Route53RecoveryControl::SafetyRule": { + "Attributes": { + "SafetyRuleArn": { + "PrimitiveType": "String" + }, + "Status": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53recoverycontrol-safetyrule.html", + "Properties": { + "AssertionRule": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53recoverycontrol-safetyrule.html#cfn-route53recoverycontrol-safetyrule-assertionrule", + "Required": false, + "Type": "AssertionRule", + "UpdateType": "Mutable" + }, + "ControlPanelArn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53recoverycontrol-safetyrule.html#cfn-route53recoverycontrol-safetyrule-controlpanelarn", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "GatingRule": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53recoverycontrol-safetyrule.html#cfn-route53recoverycontrol-safetyrule-gatingrule", + "Required": false, + "Type": "GatingRule", + "UpdateType": "Mutable" + }, + "Name": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53recoverycontrol-safetyrule.html#cfn-route53recoverycontrol-safetyrule-name", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "RuleConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53recoverycontrol-safetyrule.html#cfn-route53recoverycontrol-safetyrule-ruleconfig", + "Required": true, + "Type": "RuleConfig", + "UpdateType": "Immutable" + } + } + }, + "AWS::Route53RecoveryReadiness::Cell": { + "Attributes": { + "CellArn": { + "PrimitiveType": "String" + }, + "ParentReadinessScopes": { + "PrimitiveItemType": "String", + "Type": "List" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53recoveryreadiness-cell.html", + "Properties": { + "CellName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53recoveryreadiness-cell.html#cfn-route53recoveryreadiness-cell-cellname", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "Cells": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53recoveryreadiness-cell.html#cfn-route53recoveryreadiness-cell-cells", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "Tags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53recoveryreadiness-cell.html#cfn-route53recoveryreadiness-cell-tags", + "ItemType": "Tag", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + } + } + }, + "AWS::Route53RecoveryReadiness::ReadinessCheck": { + "Attributes": { + "ReadinessCheckArn": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53recoveryreadiness-readinesscheck.html", + "Properties": { + "ReadinessCheckName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53recoveryreadiness-readinesscheck.html#cfn-route53recoveryreadiness-readinesscheck-readinesscheckname", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "ResourceSetName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53recoveryreadiness-readinesscheck.html#cfn-route53recoveryreadiness-readinesscheck-resourcesetname", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "Tags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53recoveryreadiness-readinesscheck.html#cfn-route53recoveryreadiness-readinesscheck-tags", + "ItemType": "Tag", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + } + } + }, + "AWS::Route53RecoveryReadiness::RecoveryGroup": { + "Attributes": { + "RecoveryGroupArn": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53recoveryreadiness-recoverygroup.html", + "Properties": { + "Cells": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53recoveryreadiness-recoverygroup.html#cfn-route53recoveryreadiness-recoverygroup-cells", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "RecoveryGroupName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53recoveryreadiness-recoverygroup.html#cfn-route53recoveryreadiness-recoverygroup-recoverygroupname", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "Tags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53recoveryreadiness-recoverygroup.html#cfn-route53recoveryreadiness-recoverygroup-tags", + "ItemType": "Tag", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + } + } + }, + "AWS::Route53RecoveryReadiness::ResourceSet": { + "Attributes": { + "ResourceSetArn": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53recoveryreadiness-resourceset.html", + "Properties": { + "ResourceSetName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53recoveryreadiness-resourceset.html#cfn-route53recoveryreadiness-resourceset-resourcesetname", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "ResourceSetType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53recoveryreadiness-resourceset.html#cfn-route53recoveryreadiness-resourceset-resourcesettype", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "Resources": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53recoveryreadiness-resourceset.html#cfn-route53recoveryreadiness-resourceset-resources", + "ItemType": "Resource", + "Required": true, + "Type": "List", + "UpdateType": "Mutable" + }, + "Tags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53recoveryreadiness-resourceset.html#cfn-route53recoveryreadiness-resourceset-tags", + "ItemType": "Tag", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + } + } + }, "AWS::Route53Resolver::FirewallDomainList": { "Attributes": { "Arn": { @@ -94007,6 +94679,18 @@ }, "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-s3outposts-endpoint.html", "Properties": { + "AccessType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-s3outposts-endpoint.html#cfn-s3outposts-endpoint-accesstype", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "CustomerOwnedIpv4Pool": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-s3outposts-endpoint.html#cfn-s3outposts-endpoint-customerownedipv4pool", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, "OutpostId": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-s3outposts-endpoint.html#cfn-s3outposts-endpoint-outpostid", "PrimitiveType": "String", diff --git a/packages/@aws-cdk/cloudformation-include/package.json b/packages/@aws-cdk/cloudformation-include/package.json index f8c09b12fc8ea..71fcc718b4e3d 100644 --- a/packages/@aws-cdk/cloudformation-include/package.json +++ b/packages/@aws-cdk/cloudformation-include/package.json @@ -201,6 +201,8 @@ "@aws-cdk/aws-resourcegroups": "0.0.0", "@aws-cdk/aws-robomaker": "0.0.0", "@aws-cdk/aws-route53": "0.0.0", + "@aws-cdk/aws-route53recoverycontrol": "0.0.0", + "@aws-cdk/aws-route53recoveryreadiness": "0.0.0", "@aws-cdk/aws-route53resolver": "0.0.0", "@aws-cdk/aws-s3": "0.0.0", "@aws-cdk/aws-s3objectlambda": "0.0.0", @@ -369,6 +371,8 @@ "@aws-cdk/aws-resourcegroups": "0.0.0", "@aws-cdk/aws-robomaker": "0.0.0", "@aws-cdk/aws-route53": "0.0.0", + "@aws-cdk/aws-route53recoverycontrol": "0.0.0", + "@aws-cdk/aws-route53recoveryreadiness": "0.0.0", "@aws-cdk/aws-route53resolver": "0.0.0", "@aws-cdk/aws-s3": "0.0.0", "@aws-cdk/aws-s3objectlambda": "0.0.0", diff --git a/packages/aws-cdk-lib/package.json b/packages/aws-cdk-lib/package.json index 411d6eed9a312..e3b5cfb83db95 100644 --- a/packages/aws-cdk-lib/package.json +++ b/packages/aws-cdk-lib/package.json @@ -282,6 +282,8 @@ "@aws-cdk/aws-route53": "0.0.0", "@aws-cdk/aws-route53-patterns": "0.0.0", "@aws-cdk/aws-route53-targets": "0.0.0", + "@aws-cdk/aws-route53recoverycontrol": "0.0.0", + "@aws-cdk/aws-route53recoveryreadiness": "0.0.0", "@aws-cdk/aws-route53resolver": "0.0.0", "@aws-cdk/aws-s3": "0.0.0", "@aws-cdk/aws-s3-assets": "0.0.0", diff --git a/packages/decdk/package.json b/packages/decdk/package.json index 73c670cec466d..f386bef25c9e5 100644 --- a/packages/decdk/package.json +++ b/packages/decdk/package.json @@ -189,6 +189,8 @@ "@aws-cdk/aws-route53": "0.0.0", "@aws-cdk/aws-route53-patterns": "0.0.0", "@aws-cdk/aws-route53-targets": "0.0.0", + "@aws-cdk/aws-route53recoverycontrol": "0.0.0", + "@aws-cdk/aws-route53recoveryreadiness": "0.0.0", "@aws-cdk/aws-route53resolver": "0.0.0", "@aws-cdk/aws-s3": "0.0.0", "@aws-cdk/aws-s3-assets": "0.0.0", diff --git a/packages/monocdk/package.json b/packages/monocdk/package.json index 43227b31a4041..10c0235667470 100644 --- a/packages/monocdk/package.json +++ b/packages/monocdk/package.json @@ -283,6 +283,8 @@ "@aws-cdk/aws-route53": "0.0.0", "@aws-cdk/aws-route53-patterns": "0.0.0", "@aws-cdk/aws-route53-targets": "0.0.0", + "@aws-cdk/aws-route53recoverycontrol": "0.0.0", + "@aws-cdk/aws-route53recoveryreadiness": "0.0.0", "@aws-cdk/aws-route53resolver": "0.0.0", "@aws-cdk/aws-s3": "0.0.0", "@aws-cdk/aws-s3-assets": "0.0.0", From 6bd1ff863e5720259878a46b82ca236bbef1a1b3 Mon Sep 17 00:00:00 2001 From: Otavio Macedo Date: Wed, 4 Aug 2021 12:23:18 +0100 Subject: [PATCH 09/99] chore(assert): set only lower bound of the jest dependency (#15887) Setting the lower and upper bound breaks the build on Windows. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/@aws-cdk/assert/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/assert/package.json b/packages/@aws-cdk/assert/package.json index 7398412939102..a4366c4372345 100644 --- a/packages/@aws-cdk/assert/package.json +++ b/packages/@aws-cdk/assert/package.json @@ -53,7 +53,7 @@ "peerDependencies": { "@aws-cdk/core": "0.0.0", "constructs": "^3.3.69", - "jest": ">=26.6.3 <28.0.0" + "jest": ">=26.6.3" }, "repository": { "url": "https://github.com/aws/aws-cdk.git", From afd5bf768a280cd11b4e72db841af36df2268ccf Mon Sep 17 00:00:00 2001 From: Ben Chaimberg Date: Wed, 4 Aug 2021 13:13:28 -0700 Subject: [PATCH 10/99] feat(kinesisfirehose): supports Kinesis data stream source for delivery stream (#15836) closes #15500 closes #10783 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../@aws-cdk/aws-kinesisfirehose/README.md | 18 +- .../lib/delivery-stream.ts | 34 ++- .../@aws-cdk/aws-kinesisfirehose/package.json | 2 + .../test/delivery-stream.test.ts | 58 ++++ ...elivery-stream.source-stream.expected.json | 283 ++++++++++++++++++ .../integ.delivery-stream.source-stream.ts | 41 +++ 6 files changed, 434 insertions(+), 2 deletions(-) create mode 100644 packages/@aws-cdk/aws-kinesisfirehose/test/integ.delivery-stream.source-stream.expected.json create mode 100644 packages/@aws-cdk/aws-kinesisfirehose/test/integ.delivery-stream.source-stream.ts diff --git a/packages/@aws-cdk/aws-kinesisfirehose/README.md b/packages/@aws-cdk/aws-kinesisfirehose/README.md index b8ec936b46901..936fcdc881a86 100644 --- a/packages/@aws-cdk/aws-kinesisfirehose/README.md +++ b/packages/@aws-cdk/aws-kinesisfirehose/README.md @@ -63,11 +63,27 @@ The above example defines the following resources: ## Sources There are two main methods of sourcing input data: Kinesis Data Streams and via a "direct -put". This construct library currently only supports "direct put". See [#15500](https://github.com/aws/aws-cdk/issues/15500) to track the status of adding support for Kinesis Data Streams. +put". See: [Sending Data to a Delivery Stream](https://docs.aws.amazon.com/firehose/latest/dev/basic-write.html) in the *Kinesis Data Firehose Developer Guide*. +### Kinesis Data Stream + +A delivery stream can read directly from a Kinesis data stream as a consumer of the data +stream. Configure this behaviour by providing a data stream in the `sourceStream` +property when constructing a delivery stream: + +```ts fixture=with-destination +import * as kinesis from '@aws-cdk/aws-kinesis'; + +const sourceStream = new kinesis.Stream(this, 'Source Stream'); +new DeliveryStream(this, 'Delivery Stream', { + sourceStream: sourceStream, + destinations: [destination], +}); +``` + ### Direct Put Data must be provided via "direct put", ie., by using a `PutRecord` or `PutRecordBatch` API call. There are a number of ways of doing diff --git a/packages/@aws-cdk/aws-kinesisfirehose/lib/delivery-stream.ts b/packages/@aws-cdk/aws-kinesisfirehose/lib/delivery-stream.ts index bd40240e05409..7dfaed8eb384b 100644 --- a/packages/@aws-cdk/aws-kinesisfirehose/lib/delivery-stream.ts +++ b/packages/@aws-cdk/aws-kinesisfirehose/lib/delivery-stream.ts @@ -1,6 +1,7 @@ import * as cloudwatch from '@aws-cdk/aws-cloudwatch'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as iam from '@aws-cdk/aws-iam'; +import * as kinesis from '@aws-cdk/aws-kinesis'; import * as kms from '@aws-cdk/aws-kms'; import * as cdk from '@aws-cdk/core'; import { RegionInfo } from '@aws-cdk/region-info'; @@ -196,6 +197,13 @@ export interface DeliveryStreamProps { */ readonly deliveryStreamName?: string; + /** + * The Kinesis data stream to use as a source for this delivery stream. + * + * @default - data must be written to the delivery stream via a direct put. + */ + readonly sourceStream?: kinesis.IStream; + /** * The IAM role associated with this delivery stream. * @@ -319,6 +327,12 @@ export class DeliveryStream extends DeliveryStreamBase { }); this.grantPrincipal = role; + if ( + props.sourceStream && + (props.encryption === StreamEncryption.AWS_OWNED || props.encryption === StreamEncryption.CUSTOMER_MANAGED || props.encryptionKey) + ) { + throw new Error('Requested server-side encryption but delivery stream source is a Kinesis data stream. Specify server-side encryption on the data stream instead.'); + } if ((props.encryption === StreamEncryption.AWS_OWNED || props.encryption === StreamEncryption.UNENCRYPTED) && props.encryptionKey) { throw new Error(`Specified stream encryption as ${StreamEncryption[props.encryption]} but provided a customer-managed key`); } @@ -339,15 +353,33 @@ export class DeliveryStream extends DeliveryStreamBase { */ encryptionKey?.grantEncryptDecrypt(role); + const sourceStreamConfig = props.sourceStream ? { + kinesisStreamArn: props.sourceStream.streamArn, + roleArn: role.roleArn, + } : undefined; + const readStreamGrant = props.sourceStream?.grantRead(role); + /* + * Firehose still uses the deprecated DescribeStream API instead of the modern DescribeStreamSummary API. + * kinesis.IStream.grantRead does not provide DescribeStream permissions so we add it manually here. + */ + if (readStreamGrant && readStreamGrant.principalStatement) { + readStreamGrant.principalStatement.addActions('kinesis:DescribeStream'); + } + const destinationConfig = props.destinations[0].bind(this, {}); const resource = new CfnDeliveryStream(this, 'Resource', { deliveryStreamEncryptionConfigurationInput: encryptionConfig, deliveryStreamName: props.deliveryStreamName, - deliveryStreamType: 'DirectPut', + deliveryStreamType: props.sourceStream ? 'KinesisStreamAsSource' : 'DirectPut', + kinesisStreamSourceConfiguration: sourceStreamConfig, ...destinationConfig, }); + destinationConfig.dependables?.forEach(dependable => resource.node.addDependency(dependable)); + if (readStreamGrant) { + resource.node.addDependency(readStreamGrant); + } this.deliveryStreamArn = this.getResourceArnAttribute(resource.attrArn, { service: 'kinesis', diff --git a/packages/@aws-cdk/aws-kinesisfirehose/package.json b/packages/@aws-cdk/aws-kinesisfirehose/package.json index 1328b98adce32..58c5568c8c299 100644 --- a/packages/@aws-cdk/aws-kinesisfirehose/package.json +++ b/packages/@aws-cdk/aws-kinesisfirehose/package.json @@ -85,6 +85,7 @@ "@aws-cdk/aws-cloudwatch": "0.0.0", "@aws-cdk/aws-ec2": "0.0.0", "@aws-cdk/aws-iam": "0.0.0", + "@aws-cdk/aws-kinesis": "0.0.0", "@aws-cdk/aws-kms": "0.0.0", "@aws-cdk/aws-lambda": "0.0.0", "@aws-cdk/aws-logs": "0.0.0", @@ -98,6 +99,7 @@ "@aws-cdk/aws-cloudwatch": "0.0.0", "@aws-cdk/aws-ec2": "0.0.0", "@aws-cdk/aws-iam": "0.0.0", + "@aws-cdk/aws-kinesis": "0.0.0", "@aws-cdk/aws-kms": "0.0.0", "@aws-cdk/aws-lambda": "0.0.0", "@aws-cdk/aws-logs": "0.0.0", diff --git a/packages/@aws-cdk/aws-kinesisfirehose/test/delivery-stream.test.ts b/packages/@aws-cdk/aws-kinesisfirehose/test/delivery-stream.test.ts index 857391cc07a23..345e7feb0774a 100644 --- a/packages/@aws-cdk/aws-kinesisfirehose/test/delivery-stream.test.ts +++ b/packages/@aws-cdk/aws-kinesisfirehose/test/delivery-stream.test.ts @@ -3,6 +3,7 @@ import { ABSENT, ResourcePart, SynthUtils, anything, arrayWith } from '@aws-cdk/ import * as cloudwatch from '@aws-cdk/aws-cloudwatch'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as iam from '@aws-cdk/aws-iam'; +import * as kinesis from '@aws-cdk/aws-kinesis'; import * as kms from '@aws-cdk/aws-kms'; import * as cdk from '@aws-cdk/core'; import { Construct, Node } from 'constructs'; @@ -89,6 +90,43 @@ describe('delivery stream', () => { }); }); + test('providing source stream creates configuration and grants permission', () => { + const sourceStream = new kinesis.Stream(stack, 'Source Stream'); + + new firehose.DeliveryStream(stack, 'Delivery Stream', { + destinations: [mockS3Destination], + sourceStream: sourceStream, + role: deliveryStreamRole, + }); + + expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: arrayWith( + 'kinesis:DescribeStream', + 'kinesis:GetRecords', + 'kinesis:GetShardIterator', + 'kinesis:ListShards', + ), + Resource: stack.resolve(sourceStream.streamArn), + }, + ], + }, + Roles: [stack.resolve(deliveryStreamRole.roleName)], + }); + expect(stack).toHaveResource('AWS::KinesisFirehose::DeliveryStream', { + DeliveryStreamType: 'KinesisStreamAsSource', + KinesisStreamSourceConfiguration: { + KinesisStreamARN: stack.resolve(sourceStream.streamArn), + RoleARN: stack.resolve(deliveryStreamRole.roleArn), + }, + }); + expect(stack).toHaveResourceLike('AWS::KinesisFirehose::DeliveryStream', { + DependsOn: arrayWith('DeliveryStreamRoleDefaultPolicy2759968B'), + }, ResourcePart.CompleteDefinition); + }); + test('requesting customer-owned encryption creates key and configuration', () => { new firehose.DeliveryStream(stack, 'Delivery Stream', { destinations: [mockS3Destination], @@ -232,6 +270,26 @@ describe('delivery stream', () => { })).toThrowError('Specified stream encryption as UNENCRYPTED but provided a customer-managed key'); }); + test('requesting encryption or providing a key when source is a stream throws an error', () => { + const sourceStream = new kinesis.Stream(stack, 'Source Stream'); + + expect(() => new firehose.DeliveryStream(stack, 'Delivery Stream 1', { + destinations: [mockS3Destination], + encryption: firehose.StreamEncryption.AWS_OWNED, + sourceStream, + })).toThrowError('Requested server-side encryption but delivery stream source is a Kinesis data stream. Specify server-side encryption on the data stream instead.'); + expect(() => new firehose.DeliveryStream(stack, 'Delivery Stream 2', { + destinations: [mockS3Destination], + encryption: firehose.StreamEncryption.CUSTOMER_MANAGED, + sourceStream, + })).toThrowError('Requested server-side encryption but delivery stream source is a Kinesis data stream. Specify server-side encryption on the data stream instead.'); + expect(() => new firehose.DeliveryStream(stack, 'Delivery Stream 3', { + destinations: [mockS3Destination], + encryptionKey: new kms.Key(stack, 'Key'), + sourceStream, + })).toThrowError('Requested server-side encryption but delivery stream source is a Kinesis data stream. Specify server-side encryption on the data stream instead.'); + }); + test('grant provides access to stream', () => { const role = new iam.Role(stack, 'Role', { assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'), diff --git a/packages/@aws-cdk/aws-kinesisfirehose/test/integ.delivery-stream.source-stream.expected.json b/packages/@aws-cdk/aws-kinesisfirehose/test/integ.delivery-stream.source-stream.expected.json new file mode 100644 index 0000000000000..eb46541a1cdf2 --- /dev/null +++ b/packages/@aws-cdk/aws-kinesisfirehose/test/integ.delivery-stream.source-stream.expected.json @@ -0,0 +1,283 @@ +{ + "Resources": { + "Bucket83908E77": { + "Type": "AWS::S3::Bucket", + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "Role1ABCC5F0": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "firehose.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "RoleDefaultPolicy5FFB7DAB": { + "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": [ + "Bucket83908E77", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "Bucket83908E77", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "RoleDefaultPolicy5FFB7DAB", + "Roles": [ + { + "Ref": "Role1ABCC5F0" + } + ] + } + }, + "SourceStream95FF52BE": { + "Type": "AWS::Kinesis::Stream", + "Properties": { + "ShardCount": 1, + "RetentionPeriodHours": 24, + "StreamEncryption": { + "Fn::If": [ + "AwsCdkKinesisEncryptedStreamsUnsupportedRegions", + { + "Ref": "AWS::NoValue" + }, + { + "EncryptionType": "KMS", + "KeyId": "alias/aws/kinesis" + } + ] + } + } + }, + "DeliveryStreamServiceRole964EEBCC": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "firehose.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "DeliveryStreamServiceRoleDefaultPolicyB87D9ACF": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "kinesis:DescribeStreamSummary", + "kinesis:GetRecords", + "kinesis:GetShardIterator", + "kinesis:ListShards", + "kinesis:SubscribeToShard", + "kinesis:DescribeStream" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "SourceStream95FF52BE", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "DeliveryStreamServiceRoleDefaultPolicyB87D9ACF", + "Roles": [ + { + "Ref": "DeliveryStreamServiceRole964EEBCC" + } + ] + } + }, + "DeliveryStreamF6D5572D": { + "Type": "AWS::KinesisFirehose::DeliveryStream", + "Properties": { + "DeliveryStreamType": "KinesisStreamAsSource", + "ExtendedS3DestinationConfiguration": { + "BucketARN": { + "Fn::GetAtt": [ + "Bucket83908E77", + "Arn" + ] + }, + "RoleARN": { + "Fn::GetAtt": [ + "Role1ABCC5F0", + "Arn" + ] + } + }, + "KinesisStreamSourceConfiguration": { + "KinesisStreamARN": { + "Fn::GetAtt": [ + "SourceStream95FF52BE", + "Arn" + ] + }, + "RoleARN": { + "Fn::GetAtt": [ + "DeliveryStreamServiceRole964EEBCC", + "Arn" + ] + } + } + }, + "DependsOn": [ + "DeliveryStreamServiceRoleDefaultPolicyB87D9ACF", + "RoleDefaultPolicy5FFB7DAB" + ] + } + }, + "Conditions": { + "AwsCdkKinesisEncryptedStreamsUnsupportedRegions": { + "Fn::Or": [ + { + "Fn::Equals": [ + { + "Ref": "AWS::Region" + }, + "cn-north-1" + ] + }, + { + "Fn::Equals": [ + { + "Ref": "AWS::Region" + }, + "cn-northwest-1" + ] + } + ] + } + }, + "Mappings": { + "awscdkawskinesisfirehoseCidrBlocks": { + "af-south-1": { + "FirehoseCidrBlock": "13.244.121.224/27" + }, + "ap-east-1": { + "FirehoseCidrBlock": "18.162.221.32/27" + }, + "ap-northeast-1": { + "FirehoseCidrBlock": "13.113.196.224/27" + }, + "ap-northeast-2": { + "FirehoseCidrBlock": "13.209.1.64/27" + }, + "ap-northeast-3": { + "FirehoseCidrBlock": "13.208.177.192/27" + }, + "ap-south-1": { + "FirehoseCidrBlock": "13.232.67.32/27" + }, + "ap-southeast-1": { + "FirehoseCidrBlock": "13.228.64.192/27" + }, + "ap-southeast-2": { + "FirehoseCidrBlock": "13.210.67.224/27" + }, + "ca-central-1": { + "FirehoseCidrBlock": "35.183.92.128/27" + }, + "cn-north-1": { + "FirehoseCidrBlock": "52.81.151.32/27" + }, + "cn-northwest-1": { + "FirehoseCidrBlock": "161.189.23.64/27" + }, + "eu-central-1": { + "FirehoseCidrBlock": "35.158.127.160/27" + }, + "eu-north-1": { + "FirehoseCidrBlock": "13.53.63.224/27" + }, + "eu-south-1": { + "FirehoseCidrBlock": "15.161.135.128/27" + }, + "eu-west-1": { + "FirehoseCidrBlock": "52.19.239.192/27" + }, + "eu-west-2": { + "FirehoseCidrBlock": "18.130.1.96/27" + }, + "eu-west-3": { + "FirehoseCidrBlock": "35.180.1.96/27" + }, + "me-south-1": { + "FirehoseCidrBlock": "15.185.91.0/27" + }, + "sa-east-1": { + "FirehoseCidrBlock": "18.228.1.128/27" + }, + "us-east-1": { + "FirehoseCidrBlock": "52.70.63.192/27" + }, + "us-east-2": { + "FirehoseCidrBlock": "13.58.135.96/27" + }, + "us-gov-east-1": { + "FirehoseCidrBlock": "18.253.138.96/27" + }, + "us-gov-west-1": { + "FirehoseCidrBlock": "52.61.204.160/27" + }, + "us-west-1": { + "FirehoseCidrBlock": "13.57.135.192/27" + }, + "us-west-2": { + "FirehoseCidrBlock": "52.89.255.224/27" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-kinesisfirehose/test/integ.delivery-stream.source-stream.ts b/packages/@aws-cdk/aws-kinesisfirehose/test/integ.delivery-stream.source-stream.ts new file mode 100644 index 0000000000000..f39510a74322b --- /dev/null +++ b/packages/@aws-cdk/aws-kinesisfirehose/test/integ.delivery-stream.source-stream.ts @@ -0,0 +1,41 @@ +#!/usr/bin/env node +import * as iam from '@aws-cdk/aws-iam'; +import * as kinesis from '@aws-cdk/aws-kinesis'; +import * as s3 from '@aws-cdk/aws-s3'; +import * as cdk from '@aws-cdk/core'; +import * as constructs from 'constructs'; +import * as firehose from '../lib'; + +const app = new cdk.App(); + +const stack = new cdk.Stack(app, 'aws-cdk-firehose-delivery-stream-source-stream'); + +const bucket = new s3.Bucket(stack, 'Bucket', { + removalPolicy: cdk.RemovalPolicy.DESTROY, +}); + +const role = new iam.Role(stack, 'Role', { + assumedBy: new iam.ServicePrincipal('firehose.amazonaws.com'), +}); + +const mockS3Destination: firehose.IDestination = { + bind(_scope: constructs.Construct, _options: firehose.DestinationBindOptions): firehose.DestinationConfig { + const bucketGrant = bucket.grantReadWrite(role); + return { + extendedS3DestinationConfiguration: { + bucketArn: bucket.bucketArn, + roleArn: role.roleArn, + }, + dependables: [bucketGrant], + }; + }, +}; + +const sourceStream = new kinesis.Stream(stack, 'Source Stream'); + +new firehose.DeliveryStream(stack, 'Delivery Stream', { + destinations: [mockS3Destination], + sourceStream, +}); + +app.synth(); From de97179facc77663779ae8c630f44293f6c8ada6 Mon Sep 17 00:00:00 2001 From: Madeline Kusters <80541297+madeline-k@users.noreply.github.com> Date: Wed, 4 Aug 2021 17:52:19 -0700 Subject: [PATCH 11/99] chore(docs): update doc strings in DestinationS3BackupProps (#15896) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../@aws-cdk/aws-kinesisfirehose-destinations/lib/common.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk/aws-kinesisfirehose-destinations/lib/common.ts b/packages/@aws-cdk/aws-kinesisfirehose-destinations/lib/common.ts index 9155346f06b09..81e53e8288a73 100644 --- a/packages/@aws-cdk/aws-kinesisfirehose-destinations/lib/common.ts +++ b/packages/@aws-cdk/aws-kinesisfirehose-destinations/lib/common.ts @@ -153,16 +153,16 @@ export interface DestinationS3BackupProps extends DestinationLoggingProps, Commo /** * The S3 bucket that will store data and failed records. * - * @default - If `backup` is set to `BackupMode.ALL` or `BackupMode.FAILED`, a bucket will be created for you. + * @default - If `mode` is set to `BackupMode.ALL` or `BackupMode.FAILED`, a bucket will be created for you. */ readonly bucket?: s3.IBucket; /** * Indicates the mode by which incoming records should be backed up to S3, if any. * - * If `backupBucket ` is provided, this will be implicitly set to `BackupMode.ALL`. + * If `bucket` is provided, this will be implicitly set to `BackupMode.ALL`. * - * @default - If `backupBucket` is provided, the default will be `BackupMode.ALL`. Otherwise, + * @default - If `bucket` is provided, the default will be `BackupMode.ALL`. Otherwise, * source records are not backed up to S3. */ readonly mode?: BackupMode; From a3b4911e13c73361fda6a808f5818ef737bf00d2 Mon Sep 17 00:00:00 2001 From: AWS CDK Team Date: Thu, 5 Aug 2021 08:06:21 +0000 Subject: [PATCH 12/99] chore(release): 1.117.0 --- CHANGELOG.md | 54 +++++++++++++++++++++++++++++++++++++++++++++++++ version.v1.json | 2 +- 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 21264b7582645..82d0f58d6868c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,60 @@ 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.117.0](https://github.com/aws/aws-cdk/compare/v1.116.0...v1.117.0) (2021-08-05) + + +### ⚠ BREAKING CHANGES TO EXPERIMENTAL FEATURES + +* **assertions:** `Template.fromTemplate()` is now +renamed to `Template.fromJSON()` to provide clarity. +* **assertions:** `TemplateAssertions` is now renamed to +`Template`. + +### Features + +* **aws-cloudfront:** add enabled to web distribution ([#15433](https://github.com/aws/aws-cdk/issues/15433)) ([7ad9348](https://github.com/aws/aws-cdk/commit/7ad9348b49ab3b9dde1b4f1db3d888ddec423a9f)) +* **aws-ec2:** Add SubnetFilter for Id and CIDR netmask ([#15373](https://github.com/aws/aws-cdk/issues/15373)) ([407b02d](https://github.com/aws/aws-cdk/commit/407b02d62bd8b3eb77e53fc74197b64148640b5a)), closes [#15228](https://github.com/aws/aws-cdk/issues/15228) +* **aws-kinesisfirehose:** support for S3 destination encryption on DeliveryStream ([#15558](https://github.com/aws/aws-cdk/issues/15558)) ([3888773](https://github.com/aws/aws-cdk/commit/388877300e460e23cd69d67a16a00f7c57630649)), closes [#15555](https://github.com/aws/aws-cdk/issues/15555) +* **cfnspec:** cloudformation spec v39.8.0 ([#15885](https://github.com/aws/aws-cdk/issues/15885)) ([60e6b41](https://github.com/aws/aws-cdk/commit/60e6b4186680af98b538a21e82146fb0a0e84f33)) +* **cloudfront:** Origin Shield support ([#15453](https://github.com/aws/aws-cdk/issues/15453)) ([08ebbae](https://github.com/aws/aws-cdk/commit/08ebbae4cffdf85a66775f4e8f5ea9d7400bf358)), closes [#12872](https://github.com/aws/aws-cdk/issues/12872) [/github.com/aws/aws-cdk/issues/12872#issuecomment-775873384](https://github.com/aws//github.com/aws/aws-cdk/issues/12872/issues/issuecomment-775873384) +* **cloudfront:** use TLS_V1_2_2021 SecurityPolicy as default version (under feature flag) ([#15477](https://github.com/aws/aws-cdk/issues/15477)) ([7b64abf](https://github.com/aws/aws-cdk/commit/7b64abf51c52cd2f6f585d7fd9201030fdba8163)) +* **ec2:** Add Transcribe interface endpoint ([#15465](https://github.com/aws/aws-cdk/issues/15465)) ([929d6ae](https://github.com/aws/aws-cdk/commit/929d6aef84eb21aea0d9a4fff953a0f39246288e)) +* **eks:** support Kubernetes 1.21 ([#15774](https://github.com/aws/aws-cdk/issues/15774)) ([83dd318](https://github.com/aws/aws-cdk/commit/83dd318959b1b1e5f94b5a31030d03379638c9ad)), closes [#15758](https://github.com/aws/aws-cdk/issues/15758) +* **kinesisfirehose:** add metrics functions to IDeliveryStream ([#15618](https://github.com/aws/aws-cdk/issues/15618)) ([33909ed](https://github.com/aws/aws-cdk/commit/33909ed2144ede58e5e503f3f220f610dbd89675)), closes [#15543](https://github.com/aws/aws-cdk/issues/15543) +* **kinesisfirehose:** add support for backing up source records to S3 ([#15725](https://github.com/aws/aws-cdk/issues/15725)) ([b86062f](https://github.com/aws/aws-cdk/commit/b86062ff6215384b5def76e07586e94cc6ecc9c1)), closes [#15724](https://github.com/aws/aws-cdk/issues/15724) +* **kinesisfirehose:** add support for BufferingHints ([#15557](https://github.com/aws/aws-cdk/issues/15557)) ([099b584](https://github.com/aws/aws-cdk/commit/099b5840cc5b45bad987b7e797e6009d6383a3a7)), closes [#15554](https://github.com/aws/aws-cdk/issues/15554) +* **kinesisfirehose:** add support for Lambda data processors ([#15704](https://github.com/aws/aws-cdk/issues/15704)) ([6244a81](https://github.com/aws/aws-cdk/commit/6244a81af17ec823df409437c4a33ef5fb13a1c5)), closes [#15703](https://github.com/aws/aws-cdk/issues/15703) +* **kinesisfirehose:** add support for server-side encryption on DeliveryStream ([#15547](https://github.com/aws/aws-cdk/issues/15547)) ([74f3cda](https://github.com/aws/aws-cdk/commit/74f3cda53de7e8b5cd1d144e79cf9f5bb28e1938)), closes [#15546](https://github.com/aws/aws-cdk/issues/15546) +* **kinesisfirehose:** supports Kinesis data stream source for delivery stream ([#15836](https://github.com/aws/aws-cdk/issues/15836)) ([afd5bf7](https://github.com/aws/aws-cdk/commit/afd5bf768a280cd11b4e72db841af36df2268ccf)), closes [#15500](https://github.com/aws/aws-cdk/issues/15500) [#10783](https://github.com/aws/aws-cdk/issues/10783) +* **kinesisfirehose-destinations:** add support for compression on S3 delivery stream destinations ([#15550](https://github.com/aws/aws-cdk/issues/15550)) ([1eb56a0](https://github.com/aws/aws-cdk/commit/1eb56a025f728b7596f57b1289c2fc4c1c20e7f4)), closes [#15548](https://github.com/aws/aws-cdk/issues/15548) +* **kinesisfirehose-destinations:** add support for prefixes in the S3 destination ([#15552](https://github.com/aws/aws-cdk/issues/15552)) ([d227e48](https://github.com/aws/aws-cdk/commit/d227e48458832ff85d2d575e5462e45d29f49a6c)), closes [#15551](https://github.com/aws/aws-cdk/issues/15551) +* **lambda:** cloudwatch lambda insights ([#15439](https://github.com/aws/aws-cdk/issues/15439)) ([9efd800](https://github.com/aws/aws-cdk/commit/9efd800b4eea3a849edc5710975e4d70ec14a5cd)) +* **Route53:** add support for RemovalPolicy in CrossAccountZoneDelegationRecord ([#15782](https://github.com/aws/aws-cdk/issues/15782)) ([9eea4b8](https://github.com/aws/aws-cdk/commit/9eea4b8d454f7bc23930e6254651029b1a348a2c)), closes [#15211](https://github.com/aws/aws-cdk/issues/15211) +* **s3-deployment:** control object access ([#15730](https://github.com/aws/aws-cdk/issues/15730)) ([f58cf3c](https://github.com/aws/aws-cdk/commit/f58cf3c95eb32e9a4dc797665160e1b508ace2e1)) +* **servicecatalog:** add CloudFormation Parameter constraint ([#15770](https://github.com/aws/aws-cdk/issues/15770)) ([58fda91](https://github.com/aws/aws-cdk/commit/58fda9104ad884026d578dc0602f7d64dd533f6d)) +* **stepfunctions-tasks:** add sns publish with message attributes ([#14817](https://github.com/aws/aws-cdk/issues/14817)) ([bc99e82](https://github.com/aws/aws-cdk/commit/bc99e8271d443b10928d99437593c52efd763d7c)), closes [#4702](https://github.com/aws/aws-cdk/issues/4702) + + +### Bug Fixes + +* **assert:** module is incompatible with jest@27 ([#15666](https://github.com/aws/aws-cdk/issues/15666)) ([f446566](https://github.com/aws/aws-cdk/commit/f446566bd26ca024aed0a88da08a82a261c0dac6)) +* **aws-appsync:** graphqlapi throws incorrect error message for authorizationConfig ([#15830](https://github.com/aws/aws-cdk/issues/15830)) ([1f23313](https://github.com/aws/aws-cdk/commit/1f23313e889a00d85e7cbc56a64242d6e7762835)), closes [#15039](https://github.com/aws/aws-cdk/issues/15039) +* **aws-eks:** Allow desiredsize minsize and maxsize to accept CfnParameters. ([#15487](https://github.com/aws/aws-cdk/issues/15487)) ([fb43769](https://github.com/aws/aws-cdk/commit/fb437693c0f1568ddc53e9a198e54be3b9a01592)) +* **chatbot:** ARN validation in fromSlackChannelConfigurationArn fails for tokenized values ([#15849](https://github.com/aws/aws-cdk/issues/15849)) ([440ca35](https://github.com/aws/aws-cdk/commit/440ca35cf0f0e9f6f86bef445bd9aa6ef05ff9be)), closes [#15842](https://github.com/aws/aws-cdk/issues/15842) +* **cli:** move fail option into the diff command ([#15829](https://github.com/aws/aws-cdk/issues/15829)) ([473c1d8](https://github.com/aws/aws-cdk/commit/473c1d8248ae84bd8b4bb3863334e05e5328fddc)) +* **ec2:** volumename doesn't set name of volume ([#15832](https://github.com/aws/aws-cdk/issues/15832)) ([b842702](https://github.com/aws/aws-cdk/commit/b842702cbb7aa6632dd2fc4b4981abdd3a773826)), closes [#15831](https://github.com/aws/aws-cdk/issues/15831) +* **elbv2:** unresolved listener priority throws error ([#15804](https://github.com/aws/aws-cdk/issues/15804)) ([fce9ac7](https://github.com/aws/aws-cdk/commit/fce9ac73fe6da5e604f0659d9f101001dcef830a)) +* **pipelines:** Prepare stage doesn't have AUTO_EXPAND capability ([#15819](https://github.com/aws/aws-cdk/issues/15819)) ([a6fac49](https://github.com/aws/aws-cdk/commit/a6fac4974fa17949b836c72d04e1cc4504bc920a)), closes [#15711](https://github.com/aws/aws-cdk/issues/15711) +* **s3:** notifications are broken in some regions ([#15884](https://github.com/aws/aws-cdk/issues/15884)) ([ee19196](https://github.com/aws/aws-cdk/commit/ee191961a8b057a0585e731a67c15a7edd59c79e)) +* **stepfunctions-tasks:** Stage field not included in CallApiGatewayHttpApiEndpoint task definition ([#15755](https://github.com/aws/aws-cdk/issues/15755)) ([4f38fe1](https://github.com/aws/aws-cdk/commit/4f38fe1c3e5515ae22f2820712644ed763dbc248)), closes [#14242](https://github.com/aws/aws-cdk/issues/14242) + + +### Miscellaneous Chores + +* **assertions:** migrate more modules to use assertions ([#15857](https://github.com/aws/aws-cdk/issues/15857)) ([45b484c](https://github.com/aws/aws-cdk/commit/45b484cdff115a0893f7eed2b0c1d6424c2751e4)) +* **assertions:** rename TemplateAssertions to Template ([#15823](https://github.com/aws/aws-cdk/issues/15823)) ([823dfda](https://github.com/aws/aws-cdk/commit/823dfda76f39f0eff51d792b28aafcc5568f3db1)) + ## [1.116.0](https://github.com/aws/aws-cdk/compare/v1.115.0...v1.116.0) (2021-07-28) diff --git a/version.v1.json b/version.v1.json index 63c5030d06ef4..95b9ca9e3c2f0 100644 --- a/version.v1.json +++ b/version.v1.json @@ -1,3 +1,3 @@ { - "version": "1.116.0" + "version": "1.117.0" } From 90d5e03ddfcb961dd82967b5f0f9d38e27cb376f Mon Sep 17 00:00:00 2001 From: Otavio Macedo Date: Thu, 5 Aug 2021 09:12:31 +0100 Subject: [PATCH 13/99] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 82d0f58d6868c..91e3148260153 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,7 @@ renamed to `Template.fromJSON()` to provide clarity. * **aws-ec2:** Add SubnetFilter for Id and CIDR netmask ([#15373](https://github.com/aws/aws-cdk/issues/15373)) ([407b02d](https://github.com/aws/aws-cdk/commit/407b02d62bd8b3eb77e53fc74197b64148640b5a)), closes [#15228](https://github.com/aws/aws-cdk/issues/15228) * **aws-kinesisfirehose:** support for S3 destination encryption on DeliveryStream ([#15558](https://github.com/aws/aws-cdk/issues/15558)) ([3888773](https://github.com/aws/aws-cdk/commit/388877300e460e23cd69d67a16a00f7c57630649)), closes [#15555](https://github.com/aws/aws-cdk/issues/15555) * **cfnspec:** cloudformation spec v39.8.0 ([#15885](https://github.com/aws/aws-cdk/issues/15885)) ([60e6b41](https://github.com/aws/aws-cdk/commit/60e6b4186680af98b538a21e82146fb0a0e84f33)) -* **cloudfront:** Origin Shield support ([#15453](https://github.com/aws/aws-cdk/issues/15453)) ([08ebbae](https://github.com/aws/aws-cdk/commit/08ebbae4cffdf85a66775f4e8f5ea9d7400bf358)), closes [#12872](https://github.com/aws/aws-cdk/issues/12872) [/github.com/aws/aws-cdk/issues/12872#issuecomment-775873384](https://github.com/aws//github.com/aws/aws-cdk/issues/12872/issues/issuecomment-775873384) +* **cloudfront:** Origin Shield support ([#15453](https://github.com/aws/aws-cdk/issues/15453)) ([08ebbae](https://github.com/aws/aws-cdk/commit/08ebbae4cffdf85a66775f4e8f5ea9d7400bf358)), closes [#12872](https://github.com/aws/aws-cdk/issues/12872) * **cloudfront:** use TLS_V1_2_2021 SecurityPolicy as default version (under feature flag) ([#15477](https://github.com/aws/aws-cdk/issues/15477)) ([7b64abf](https://github.com/aws/aws-cdk/commit/7b64abf51c52cd2f6f585d7fd9201030fdba8163)) * **ec2:** Add Transcribe interface endpoint ([#15465](https://github.com/aws/aws-cdk/issues/15465)) ([929d6ae](https://github.com/aws/aws-cdk/commit/929d6aef84eb21aea0d9a4fff953a0f39246288e)) * **eks:** support Kubernetes 1.21 ([#15774](https://github.com/aws/aws-cdk/issues/15774)) ([83dd318](https://github.com/aws/aws-cdk/commit/83dd318959b1b1e5f94b5a31030d03379638c9ad)), closes [#15758](https://github.com/aws/aws-cdk/issues/15758) From 00b916a752e0251118c852dc257c10a879abd1fb Mon Sep 17 00:00:00 2001 From: Otavio Macedo Date: Thu, 5 Aug 2021 10:05:30 +0100 Subject: [PATCH 14/99] Update CHANGELOG.md Co-authored-by: Niranjan Jayakar --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91e3148260153..4476f44135495 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,7 +39,6 @@ renamed to `Template.fromJSON()` to provide clarity. ### Bug Fixes -* **assert:** module is incompatible with jest@27 ([#15666](https://github.com/aws/aws-cdk/issues/15666)) ([f446566](https://github.com/aws/aws-cdk/commit/f446566bd26ca024aed0a88da08a82a261c0dac6)) * **aws-appsync:** graphqlapi throws incorrect error message for authorizationConfig ([#15830](https://github.com/aws/aws-cdk/issues/15830)) ([1f23313](https://github.com/aws/aws-cdk/commit/1f23313e889a00d85e7cbc56a64242d6e7762835)), closes [#15039](https://github.com/aws/aws-cdk/issues/15039) * **aws-eks:** Allow desiredsize minsize and maxsize to accept CfnParameters. ([#15487](https://github.com/aws/aws-cdk/issues/15487)) ([fb43769](https://github.com/aws/aws-cdk/commit/fb437693c0f1568ddc53e9a198e54be3b9a01592)) * **chatbot:** ARN validation in fromSlackChannelConfigurationArn fails for tokenized values ([#15849](https://github.com/aws/aws-cdk/issues/15849)) ([440ca35](https://github.com/aws/aws-cdk/commit/440ca35cf0f0e9f6f86bef445bd9aa6ef05ff9be)), closes [#15842](https://github.com/aws/aws-cdk/issues/15842) From de07ba27c3df551e86dbb8aedc260b23b292edb8 Mon Sep 17 00:00:00 2001 From: Otavio Macedo Date: Thu, 5 Aug 2021 10:05:39 +0100 Subject: [PATCH 15/99] Update CHANGELOG.md Co-authored-by: Niranjan Jayakar --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4476f44135495..1488e8702a7da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,8 +39,8 @@ renamed to `Template.fromJSON()` to provide clarity. ### Bug Fixes -* **aws-appsync:** graphqlapi throws incorrect error message for authorizationConfig ([#15830](https://github.com/aws/aws-cdk/issues/15830)) ([1f23313](https://github.com/aws/aws-cdk/commit/1f23313e889a00d85e7cbc56a64242d6e7762835)), closes [#15039](https://github.com/aws/aws-cdk/issues/15039) -* **aws-eks:** Allow desiredsize minsize and maxsize to accept CfnParameters. ([#15487](https://github.com/aws/aws-cdk/issues/15487)) ([fb43769](https://github.com/aws/aws-cdk/commit/fb437693c0f1568ddc53e9a198e54be3b9a01592)) +* **appsync:** graphqlapi throws incorrect error message for authorizationConfig ([#15830](https://github.com/aws/aws-cdk/issues/15830)) ([1f23313](https://github.com/aws/aws-cdk/commit/1f23313e889a00d85e7cbc56a64242d6e7762835)), closes [#15039](https://github.com/aws/aws-cdk/issues/15039) +* **eks:** Allow desiredsize minsize and maxsize to accept CfnParameters. ([#15487](https://github.com/aws/aws-cdk/issues/15487)) ([fb43769](https://github.com/aws/aws-cdk/commit/fb437693c0f1568ddc53e9a198e54be3b9a01592)) * **chatbot:** ARN validation in fromSlackChannelConfigurationArn fails for tokenized values ([#15849](https://github.com/aws/aws-cdk/issues/15849)) ([440ca35](https://github.com/aws/aws-cdk/commit/440ca35cf0f0e9f6f86bef445bd9aa6ef05ff9be)), closes [#15842](https://github.com/aws/aws-cdk/issues/15842) * **cli:** move fail option into the diff command ([#15829](https://github.com/aws/aws-cdk/issues/15829)) ([473c1d8](https://github.com/aws/aws-cdk/commit/473c1d8248ae84bd8b4bb3863334e05e5328fddc)) * **ec2:** volumename doesn't set name of volume ([#15832](https://github.com/aws/aws-cdk/issues/15832)) ([b842702](https://github.com/aws/aws-cdk/commit/b842702cbb7aa6632dd2fc4b4981abdd3a773826)), closes [#15831](https://github.com/aws/aws-cdk/issues/15831) From 275e6b61aea97aa85a64e062f211792b01adb7cd Mon Sep 17 00:00:00 2001 From: Otavio Macedo Date: Thu, 5 Aug 2021 10:46:49 +0100 Subject: [PATCH 16/99] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1488e8702a7da..ef046c0c53529 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ renamed to `Template.fromJSON()` to provide clarity. ### Bug Fixes +* **assert:** module is incompatible with jest@27 ([#15666](https://github.com/aws/aws-cdk/issues/15666)) ([f446566](https://github.com/aws/aws-cdk/commit/f446566bd26ca024aed0a88da08a82a261c0dac6)) * **appsync:** graphqlapi throws incorrect error message for authorizationConfig ([#15830](https://github.com/aws/aws-cdk/issues/15830)) ([1f23313](https://github.com/aws/aws-cdk/commit/1f23313e889a00d85e7cbc56a64242d6e7762835)), closes [#15039](https://github.com/aws/aws-cdk/issues/15039) * **eks:** Allow desiredsize minsize and maxsize to accept CfnParameters. ([#15487](https://github.com/aws/aws-cdk/issues/15487)) ([fb43769](https://github.com/aws/aws-cdk/commit/fb437693c0f1568ddc53e9a198e54be3b9a01592)) * **chatbot:** ARN validation in fromSlackChannelConfigurationArn fails for tokenized values ([#15849](https://github.com/aws/aws-cdk/issues/15849)) ([440ca35](https://github.com/aws/aws-cdk/commit/440ca35cf0f0e9f6f86bef445bd9aa6ef05ff9be)), closes [#15842](https://github.com/aws/aws-cdk/issues/15842) From cc33466742e9589daa83a65aa351d513d1f60a22 Mon Sep 17 00:00:00 2001 From: kaizen3031593 Date: Thu, 5 Aug 2021 20:13:44 +0000 Subject: [PATCH 17/99] chore: add kaizen3031593 to mergify --- .mergify.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mergify.yml b/.mergify.yml index 1616f92196fd8..18f6ee0bb2555 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)$ + - 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)$ - -label~="contribution/core" - name: automatic merge actions: From 4f65bd89dcb2c32a38550627f2479d0464eef8bd Mon Sep 17 00:00:00 2001 From: Nick Lynch Date: Fri, 6 Aug 2021 12:55:22 +0100 Subject: [PATCH 18/99] test(aws-lambda-python): remove hard-coded references to @aws-cdk/aws-lambda (#15921) Remove the hard coded reference to the @aws-cdk/aws-lambda packages from the test, which should fix the issue that prevent building the aws-cdk-lib package. Copied from (and kudos to!) #15826 Related #15586 ---- *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-python/test/bundling.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-lambda-python/test/bundling.test.ts b/packages/@aws-cdk/aws-lambda-python/test/bundling.test.ts index d6de4ee23aedd..712852023a367 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/bundling.test.ts +++ b/packages/@aws-cdk/aws-lambda-python/test/bundling.test.ts @@ -4,7 +4,7 @@ import { Code, Runtime } from '@aws-cdk/aws-lambda'; import { FileSystem } from '@aws-cdk/core'; import { stageDependencies, bundle } from '../lib/bundling'; -jest.mock('@aws-cdk/aws-lambda'); +jest.spyOn(Code, 'fromAsset'); jest.mock('child_process', () => ({ spawnSync: jest.fn(() => { From 4ce318224453cebcf817b7683e5020780ab5df87 Mon Sep 17 00:00:00 2001 From: Otavio Macedo Date: Fri, 6 Aug 2021 15:57:16 +0100 Subject: [PATCH 19/99] chore(assertions): explicit feature flags to produce a consistent template during tests (#15924) In v1, the default value of the `@aws-cdk/core:newStyleStackSynthesis` flag is `false`. As a consequence, `Template.fromStack()` generates, by default, a template without the rule and parameter related to bootstrap versions. In v2, the default value of this flag is `true`. So this test fails in the v2 branch. By explicitly setting the flag to `false`, we ensure that the tests passes on both v1 and v2, regardless of the default values. ---- *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/test/template.test.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/assertions/test/template.test.ts b/packages/@aws-cdk/assertions/test/template.test.ts index 0fe308e68e5be..fcbc199f1f2da 100644 --- a/packages/@aws-cdk/assertions/test/template.test.ts +++ b/packages/@aws-cdk/assertions/test/template.test.ts @@ -1,4 +1,4 @@ -import { CfnResource, Stack } from '@aws-cdk/core'; +import { App, CfnResource, Stack } from '@aws-cdk/core'; import { Construct } from 'constructs'; import { Match, Template } from '../lib'; @@ -25,7 +25,12 @@ describe('Template', () => { }); test('fromStack', () => { - const stack = new Stack(); + const app = new App({ + context: { + '@aws-cdk/core:newStyleStackSynthesis': false, + }, + }); + const stack = new Stack(app); new CfnResource(stack, 'Foo', { type: 'Foo::Bar', properties: { From 891f111705f58e1c1e93fdd76659ca0bfbbcf2d5 Mon Sep 17 00:00:00 2001 From: Seiya6329 Date: Fri, 6 Aug 2021 13:40:58 -0700 Subject: [PATCH 20/99] docs(appmesh): comprehensive App Mesh readme review (#15877) Conducting comprehensive review on `README` file. ---- *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-appmesh/README.md | 272 ++++++++++++------------ 1 file changed, 137 insertions(+), 135 deletions(-) diff --git a/packages/@aws-cdk/aws-appmesh/README.md b/packages/@aws-cdk/aws-appmesh/README.md index 1b04f9dd93cb9..b1779dffe6f8a 100644 --- a/packages/@aws-cdk/aws-appmesh/README.md +++ b/packages/@aws-cdk/aws-appmesh/README.md @@ -36,7 +36,7 @@ The following example creates the `AppMesh` service mesh with the default egress ```ts const mesh = new Mesh(stack, 'AppMesh', { - meshName: 'myAwsmMesh', + meshName: 'myAwsMesh', }); ``` @@ -44,7 +44,7 @@ The mesh can instead be created with the `ALLOW_ALL` egress filter by providing ```ts const mesh = new Mesh(stack, 'AppMesh', { - meshName: 'myAwsmMesh', + meshName: 'myAwsMesh', egressFilter: MeshFilterType.ALLOW_ALL, }); ``` @@ -58,7 +58,7 @@ After you create a virtual router, you can create and associate routes to your v ```ts const router = mesh.addVirtualRouter('router', { - listeners: [ appmesh.VirtualRouterListener.http(8080) ], + listeners: [ VirtualRouterListener.http(8080) ], }); ``` @@ -69,15 +69,15 @@ This is particularly useful when splitting your resources between many stacks: f ```ts const mesh = new Mesh(infraStack, 'AppMesh', { - meshName: 'myAwsmMesh', + meshName: 'myAwsMesh', egressFilter: MeshFilterType.ALLOW_ALL, }); // the VirtualRouter will belong to 'appStack', // even though the Mesh belongs to 'infraStack' const router = new VirtualRouter(appStack, 'router', { - mesh: mesh, // notice that mesh is a required property when creating a router with the 'new' statement - listeners: [appmesh.VirtualRouterListener.http(8081)], + mesh, // notice that mesh is a required property when creating a router with the 'new' statement + listeners: [VirtualRouterListener.http(8081)], }); ``` @@ -102,18 +102,18 @@ When creating a virtual service: Adding a virtual router as the provider: ```ts -new appmesh.VirtualService('virtual-service', { +new VirtualService(stack, 'virtual-service', { virtualServiceName: 'my-service.default.svc.cluster.local', // optional - virtualServiceProvider: appmesh.VirtualServiceProvider.virtualRouter(router), + virtualServiceProvider: VirtualServiceProvider.virtualRouter(router), }); ``` Adding a virtual node as the provider: ```ts -new appmesh.VirtualService('virtual-service', { +new VirtualService(stack, 'virtual-service', { virtualServiceName: `my-service.default.svc.cluster.local`, // optional - virtualServiceProvider: appmesh.VirtualServiceProvider.virtualNode(node), + virtualServiceProvider: VirtualServiceProvider.virtualNode(node), }); ``` @@ -130,41 +130,41 @@ The response metadata for your new virtual node contains the Amazon Resource Nam ```ts const vpc = new ec2.Vpc(stack, 'vpc'); -const namespace = new servicediscovery.PrivateDnsNamespace(this, 'test-namespace', { +const namespace = new servicediscovery.PrivateDnsNamespace(stack, 'test-namespace', { vpc, name: 'domain.local', }); const service = namespace.createService('Svc'); const node = mesh.addVirtualNode('virtual-node', { - serviceDiscovery: appmesh.ServiceDiscovery.cloudMap(service), - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + serviceDiscovery: ServiceDiscovery.cloudMap(service), + listeners: [VirtualNodeListener.http({ port: 8081, - healthCheck: appmesh.HealthCheck.http({ + healthCheck: HealthCheck.http({ healthyThreshold: 3, - interval: Duration.seconds(5), // minimum - path: `/health-check-path`, - timeout: Duration.seconds(2), // minimum + interval: cdk.Duration.seconds(5), // minimum + path: '/health-check-path', + timeout: cdk.Duration.seconds(2), // minimum unhealthyThreshold: 2, }), })], - accessLog: appmesh.AccessLog.fromFilePath('/dev/stdout'), + accessLog: AccessLog.fromFilePath('/dev/stdout'), }); ``` Create a `VirtualNode` with the constructor and add tags. ```ts -const node = new VirtualNode(this, 'node', { +const node = new VirtualNode(stack, 'node', { mesh, - serviceDiscovery: appmesh.ServiceDiscovery.cloudMap(service), - listeners: [appmesh.VirtualNodeListener.http({ + serviceDiscovery: ServiceDiscovery.cloudMap(service), + listeners: [VirtualNodeListener.http({ port: 8080, - healthCheck: appmesh.HealthCheck.http({ + healthCheck: HealthCheck.http({ healthyThreshold: 3, - interval: Duration.seconds(5), // min + interval: cdk.Duration.seconds(5), path: '/ping', - timeout: Duration.seconds(2), // min + timeout: cdk.Duration.seconds(2), unhealthyThreshold: 2, }), timeout: { @@ -174,44 +174,44 @@ const node = new VirtualNode(this, 'node', { backendDefaults: { tlsClientPolicy: { validation: { - trust: appmesh.TlsValidationTrust.file('/keys/local_cert_chain.pem'), + trust: TlsValidationTrust.file('/keys/local_cert_chain.pem'), }, }, }, - accessLog: appmesh.AccessLog.fromFilePath('/dev/stdout'), + accessLog: AccessLog.fromFilePath('/dev/stdout'), }); -cdk.Tag.add(node, 'Environment', 'Dev'); +cdk.Tags.of(node).add('Environment', 'Dev'); ``` Create a `VirtualNode` with the constructor and add backend virtual service. ```ts -const node = new VirtualNode(this, 'node', { +const node = new VirtualNode(stack, 'node', { mesh, - serviceDiscovery: appmesh.ServiceDiscovery.cloudMap(service), - listeners: [appmesh.VirtualNodeListener.httpNodeListener({ + serviceDiscovery: ServiceDiscovery.cloudMap(service), + listeners: [VirtualNodeListener.http({ port: 8080, - healthCheck: appmesh.HealthCheck.http({ + healthCheck: HealthCheck.http({ healthyThreshold: 3, - interval: Duration.seconds(5), // min + interval: cdk.Duration.seconds(5), path: '/ping', - timeout: Duration.seconds(2), // min + timeout: cdk.Duration.seconds(2), unhealthyThreshold: 2, }), timeout: { idle: cdk.Duration.seconds(5), }, })], - accessLog: appmesh.AccessLog.fromFilePath('/dev/stdout'), + accessLog: AccessLog.fromFilePath('/dev/stdout'), }); -const virtualService = new appmesh.VirtualService(stack, 'service-1', { - virtualServiceProvider: appmesh.VirtualServiceProvider.virtualRouter(router), +const virtualService = new VirtualService(stack, 'service-1', { + virtualServiceProvider: VirtualServiceProvider.virtualRouter(router), virtualServiceName: 'service1.domain.local', }); -node.addBackend(appmesh.Backend.virtualService(virtualService)); +node.addBackend(Backend.virtualService(virtualService)); ``` The `listeners` property can be left blank and added later with the `node.addListener()` method. The `serviceDiscovery` property must be specified when specifying a listener. @@ -220,7 +220,7 @@ The `backends` property can be added with `node.addBackend()`. In the example, w The `backendDefaults` property is added to the node while creating the virtual node. These are the virtual node's default settings for all backends. -## Adding TLS to a listener +### Adding TLS to a listener The `tls` property specifies TLS configuration when creating a listener for a virtual node or a virtual gateway. Provide the TLS certificate to the proxy in one of the following ways: @@ -237,46 +237,46 @@ import * as certificatemanager from '@aws-cdk/aws-certificatemanager'; // A Virtual Node with listener TLS from an ACM provided certificate const cert = new certificatemanager.Certificate(this, 'cert', {...}); -const node = new appmesh.VirtualNode(stack, 'node', { +const node = new VirtualNode(stack, 'node', { mesh, - serviceDiscovery: appmesh.ServiceDiscovery.dns('node'), - listeners: [appmesh.VirtualNodeListener.grpc({ + serviceDiscovery: ServiceDiscovery.dns('node'), + listeners: [VirtualNodeListener.grpc({ port: 80, tls: { - mode: appmesh.TlsMode.STRICT, - certificate: appmesh.TlsCertificate.acm(cert), + mode: TlsMode.STRICT, + certificate: TlsCertificate.acm(cert), }, })], }); // A Virtual Gateway with listener TLS from a customer provided file certificate -const gateway = new appmesh.VirtualGateway(this, 'gateway', { +const gateway = new VirtualGateway(this, 'gateway', { mesh: mesh, - listeners: [appmesh.VirtualGatewayListener.grpc({ + listeners: [VirtualGatewayListener.grpc({ port: 8080, tls: { - mode: appmesh.TlsMode.STRICT, - certificate: appmesh.TlsCertificate.file('path/to/certChain', 'path/to/privateKey'), + mode: TlsMode.STRICT, + certificate: TlsCertificate.file('path/to/certChain', 'path/to/privateKey'), }, })], virtualGatewayName: 'gateway', }); // A Virtual Gateway with listener TLS from a SDS provided certificate -const gateway2 = new appmesh.VirtualGateway(this, 'gateway2', { +const gateway2 = new VirtualGateway(this, 'gateway2', { mesh: mesh, - listeners: [appmesh.VirtualGatewayListener.http2({ + listeners: [VirtualGatewayListener.http2({ port: 8080, tls: { - mode: appmesh.TlsMode.STRICT, - certificate: appmesh.TlsCertificate.sds('secrete_certificate'), + mode: TlsMode.STRICT, + certificate: TlsCertificate.sds('secrete_certificate'), }, })], virtualGatewayName: 'gateway2', }); ``` -## Adding mutual TLS authentication +### Adding mutual TLS authentication Mutual TLS authentication is an optional component of TLS that offers two-way peer authentication. To enable mutual TLS authentication, add the `mutualTlsCertificate` property to TLS client policy and/or the `mutualTlsValidation` property to your TLS listener. @@ -293,41 +293,41 @@ To enable mutual TLS authentication, add the `mutualTlsCertificate` property to ```typescript import * as certificatemanager from '@aws-cdk/aws-certificatemanager'; -const node1 = new appmesh.VirtualNode(stack, 'node1', { +const node1 = new VirtualNode(stack, 'node1', { mesh, - serviceDiscovery: appmesh.ServiceDiscovery.dns('node'), - listeners: [appmesh.VirtualNodeListener.grpc({ + serviceDiscovery: ServiceDiscovery.dns('node'), + listeners: [VirtualNodeListener.grpc({ port: 80, tls: { - mode: appmesh.TlsMode.STRICT, - certificate: appmesh.TlsCertificate.file('path/to/certChain', 'path/to/privateKey'), + mode: TlsMode.STRICT, + certificate: TlsCertificate.file('path/to/certChain', 'path/to/privateKey'), // Validate a file client certificates to enable mutual TLS authentication when a client provides a certificate. mutualTlsValidation: { - trust: appmesh.TlsValidationTrust.file('path-to-certificate'), + trust: TlsValidationTrust.file('path-to-certificate'), }, }, })], }); -const node2 = new appmesh.VirtualNode(stack, 'node2', { +const node2 = new VirtualNode(stack, 'node2', { mesh, - serviceDiscovery: appmesh.ServiceDiscovery.dns('node2'), + serviceDiscovery: ServiceDiscovery.dns('node2'), backendDefaults: { tlsClientPolicy: { ports: [8080, 8081], validation: { - subjectAlternativeNames: appmesh.SubjectAlternativeNames.matchingExactly('mesh-endpoint.apps.local'), - trust: appmesh.TlsValidationTrust.acm([ + subjectAlternativeNames: SubjectAlternativeNames.matchingExactly('mesh-endpoint.apps.local'), + trust: TlsValidationTrust.acm([ acmpca.CertificateAuthority.fromCertificateAuthorityArn(stack, 'certificate', certificateAuthorityArn)]), }, // Provide a SDS client certificate when a server requests it and enable mutual TLS authentication. - mutualTlsCertificate: appmesh.TlsCertificate.sds('secret_certificate'), + mutualTlsCertificate: TlsCertificate.sds('secret_certificate'), }, }, }); ``` -## Adding outlier detection to a Virtual Node listener +### Adding outlier detection to a Virtual Node listener The `outlierDetection` property adds outlier detection to a Virtual Node listener. The properties `baseEjectionDuration`, `interval`, `maxEjectionPercent`, and `maxServerErrors` are required. @@ -342,30 +342,32 @@ const namespace = new servicediscovery.PrivateDnsNamespace(this, 'test-namespace const service = namespace.createService('Svc'); const node = mesh.addVirtualNode('virtual-node', { - serviceDiscovery: appmesh.ServiceDiscovery.cloudMap(service), - outlierDetection: { - baseEjectionDuration: cdk.Duration.seconds(10), - interval: cdk.Duration.seconds(30), - maxEjectionPercent: 50, - maxServerErrors: 5, - }, + serviceDiscovery: ServiceDiscovery.cloudMap(service), + listeners: [VirtualNodeListener.http({ + outlierDetection: { + baseEjectionDuration: cdk.Duration.seconds(10), + interval: cdk.Duration.seconds(30), + maxEjectionPercent: 50, + maxServerErrors: 5, + }, + })], }); ``` -## Adding a connection pool to a listener +### Adding a connection pool to a listener The `connectionPool` property can be added to a Virtual Node listener or Virtual Gateway listener to add a request connection pool. Each listener protocol type has its own connection pool properties. ```typescript // A Virtual Node with a gRPC listener with a connection pool set -const node = new appmesh.VirtualNode(stack, 'node', { +const node = new VirtualNode(stack, 'node', { mesh, // DNS service discovery can optionally specify the DNS response type as either LOAD_BALANCER or ENDPOINTS. - // LOAD_BALANCER means that the DNS resolver returns a loadbalanced set of endpoints, + // LOAD_BALANCER means that the DNS resolver returns a loadbalanced set of endpoints, // whereas ENDPOINTS means that the DNS resolver is returning all the endpoints. // By default, the response type is assumed to be LOAD_BALANCER - serviceDiscovery: appmesh.ServiceDiscovery.dns('node', appmesh.ResponseType.ENDPOINTS), - listeners: [appmesh.VirtualNodeListener.http({ + serviceDiscovery: ServiceDiscovery.dns('node', DnsResponseType.ENDPOINTS), + listeners: [VirtualNodeListener.http({ port: 80, connectionPool: { maxConnections: 100, @@ -375,9 +377,9 @@ const node = new appmesh.VirtualNode(stack, 'node', { }); // A Virtual Gateway with a gRPC listener with a connection pool set -const gateway = new appmesh.VirtualGateway(this, 'gateway', { - mesh: mesh, - listeners: [appmesh.VirtualGatewayListener.grpc({ +const gateway = new VirtualGateway(stack, 'gateway', { + mesh, + listeners: [VirtualGatewayListener.grpc({ port: 8080, connectionPool: { maxRequests: 10, @@ -405,7 +407,7 @@ For example, here's how to add an HTTP route that matches based on a prefix of t ```ts router.addRoute('route-http', { - routeSpec: appmesh.RouteSpec.http({ + routeSpec: RouteSpec.http({ weightedTargets: [ { virtualNode: node, @@ -413,7 +415,7 @@ router.addRoute('route-http', { ], match: { // Path that is passed to this method must start with '/'. - path: appmesh.HttpRoutePathMatch.startsWith('/path-to-app'), + path: HttpRoutePathMatch.startsWith('/path-to-app'), }, }), }); @@ -423,24 +425,24 @@ Add an HTTP2 route that matches based on exact path, method, scheme, headers, an ```ts router.addRoute('route-http2', { - routeSpec: appmesh.RouteSpec.http2({ + routeSpec: RouteSpec.http2({ weightedTargets: [ { virtualNode: node, }, ], match: { - path: appmesh.HttpRoutePathMatch.exactly('/exact'), - method: appmesh.HttpRouteMethod.POST, - protocol: appmesh.HttpRouteProtocol.HTTPS, + path: HttpRoutePathMatch.exactly('/exact'), + method: HttpRouteMethod.POST, + protocol: HttpRouteProtocol.HTTPS, headers: [ // All specified headers must match for the route to match. - appmesh.HeaderMatch.valueIs('Content-Type', 'application/json'), - appmesh.HeaderMatch.valueIsNot('Content-Type', 'application/json'), + HeaderMatch.valueIs('Content-Type', 'application/json'), + HeaderMatch.valueIsNot('Content-Type', 'application/json'), ], queryParameters: [ // All specified query parameters must match for the route to match. - appmesh.QueryParameterMatch.valueIs('query-field', 'value') + QueryParameterMatch.valueIs('query-field', 'value') ], }, }), @@ -451,7 +453,7 @@ Add a single route with two targets and split traffic 50/50: ```ts router.addRoute('route-http', { - routeSpec: appmesh.RouteSpec.http({ + routeSpec: RouteSpec.http({ weightedTargets: [ { virtualNode: node, @@ -463,7 +465,7 @@ router.addRoute('route-http', { }, ], match: { - path: appmesh.HttpRoutePathMatch.startsWith('/path-to-app'), + path: HttpRoutePathMatch.startsWith('/path-to-app'), }, }), }); @@ -473,13 +475,13 @@ Add an http2 route with retries: ```ts router.addRoute('route-http2-retry', { - routeSpec: appmesh.RouteSpec.http2({ + routeSpec: RouteSpec.http2({ weightedTargets: [{ virtualNode: node }], retryPolicy: { // Retry if the connection failed - tcpRetryEvents: [appmesh.TcpRetryEvent.CONNECTION_ERROR], + tcpRetryEvents: [TcpRetryEvent.CONNECTION_ERROR], // Retry if HTTP responds with a gateway error (502, 503, 504) - httpRetryEvents: [appmesh.HttpRetryEvent.GATEWAY_ERROR], + httpRetryEvents: [HttpRetryEvent.GATEWAY_ERROR], // Retry five times retryAttempts: 5, // Use a 1 second timeout per retry @@ -493,18 +495,18 @@ Add a gRPC route with retries: ```ts router.addRoute('route-grpc-retry', { - routeSpec: appmesh.RouteSpec.grpc({ + routeSpec: RouteSpec.grpc({ weightedTargets: [{ virtualNode: node }], match: { serviceName: 'servicename' }, retryPolicy: { - tcpRetryEvents: [appmesh.TcpRetryEvent.CONNECTION_ERROR], - httpRetryEvents: [appmesh.HttpRetryEvent.GATEWAY_ERROR], + tcpRetryEvents: [TcpRetryEvent.CONNECTION_ERROR], + httpRetryEvents: [HttpRetryEvent.GATEWAY_ERROR], // Retry if gRPC responds that the request was cancelled, a resource // was exhausted, or if the service is unavailable grpcRetryEvents: [ - appmesh.GrpcRetryEvent.CANCELLED, - appmesh.GrpcRetryEvent.RESOURCE_EXHAUSTED, - appmesh.GrpcRetryEvent.UNAVAILABLE, + GrpcRetryEvent.CANCELLED, + GrpcRetryEvent.RESOURCE_EXHAUSTED, + GrpcRetryEvent.UNAVAILABLE, ], retryAttempts: 5, retryTimeout: cdk.Duration.seconds(1), @@ -517,7 +519,7 @@ Add an gRPC route that matches based on method name and metadata: ```ts router.addRoute('route-grpc-retry', { - routeSpec: appmesh.RouteSpec.grpc({ + routeSpec: RouteSpec.grpc({ weightedTargets: [{ virtualNode: node }], match: { // When method name is specified, service name must be also specified. @@ -525,8 +527,8 @@ router.addRoute('route-grpc-retry', { serviceName: 'servicename', metadata: [ // All specified metadata must match for the route to match. - appmesh.HeaderMatch.valueStartsWith('Content-Type', 'application/'), - appmesh.HeaderMatch.valueDoesNotStartWith('Content-Type', 'text/'), + HeaderMatch.valueStartsWith('Content-Type', 'application/'), + HeaderMatch.valueDoesNotStartWith('Content-Type', 'text/'), ], }, }), @@ -537,7 +539,7 @@ Add a gRPC route with timeout: ```ts router.addRoute('route-http', { - routeSpec: appmesh.RouteSpec.grpc({ + routeSpec: RouteSpec.grpc({ weightedTargets: [ { virtualNode: node, @@ -547,8 +549,8 @@ router.addRoute('route-http', { serviceName: 'my-service.default.svc.cluster.local', }, timeout: { - idle : Duration.seconds(2), - perRequest: Duration.seconds(1), + idle : cdk.Duration.seconds(2), + perRequest: cdk.Duration.seconds(1), }, }), }); @@ -560,7 +562,7 @@ A _virtual gateway_ allows resources outside your mesh to communicate with resou The virtual gateway represents an Envoy proxy running in an Amazon ECS task, in a Kubernetes service, or on an Amazon EC2 instance. Unlike a virtual node, which represents Envoy running with an application, a virtual gateway represents Envoy deployed by itself. -A virtual gateway is similar to a virtual node in that it has a listener that accepts traffic for a particular port and protocol (HTTP, HTTP2, GRPC). +A virtual gateway is similar to a virtual node in that it has a listener that accepts traffic for a particular port and protocol (HTTP, HTTP2, gRPC). Traffic received by the virtual gateway is directed to other services in your mesh using rules defined in gateway routes which can be added to your virtual gateway. @@ -569,11 +571,11 @@ Create a virtual gateway with the constructor: ```ts const certificateAuthorityArn = 'arn:aws:acm-pca:us-east-1:123456789012:certificate-authority/12345678-1234-1234-1234-123456789012'; -const gateway = new appmesh.VirtualGateway(stack, 'gateway', { +const gateway = new VirtualGateway(stack, 'gateway', { mesh: mesh, - listeners: [appmesh.VirtualGatewayListener.http({ + listeners: [VirtualGatewayListener.http({ port: 443, - healthCheck: appmesh.HealthCheck.http({ + healthCheck: HealthCheck.http({ interval: cdk.Duration.seconds(10), }), })], @@ -581,12 +583,12 @@ const gateway = new appmesh.VirtualGateway(stack, 'gateway', { tlsClientPolicy: { ports: [8080, 8081], validation: { - trust: appmesh.TlsValidationTrust.acm([ + trust: TlsValidationTrust.acm([ acmpca.CertificateAuthority.fromCertificateAuthorityArn(stack, 'certificate', certificateAuthorityArn)]), }, }, }, - accessLog: appmesh.AccessLog.fromFilePath('/dev/stdout'), + accessLog: AccessLog.fromFilePath('/dev/stdout'), virtualGatewayName: 'virtualGateway', }); ``` @@ -595,11 +597,11 @@ Add a virtual gateway directly to the mesh: ```ts const gateway = mesh.addVirtualGateway('gateway', { - accessLog: appmesh.AccessLog.fromFilePath('/dev/stdout'), + accessLog: AccessLog.fromFilePath('/dev/stdout'), virtualGatewayName: 'virtualGateway', - listeners: [appmesh.VirtualGatewayListener.http({ + listeners: [VirtualGatewayListener.http({ port: 443, - healthCheck: appmesh.HealthCheck.http({ + healthCheck: HealthCheck.http({ interval: cdk.Duration.seconds(10), }), })], @@ -621,10 +623,10 @@ By default, HTTP-based gateway routes match all requests. ```ts gateway.addGatewayRoute('gateway-route-http', { - routeSpec: appmesh.GatewayRouteSpec.http({ + routeSpec: GatewayRouteSpec.http({ routeTarget: virtualService, match: { - path: appmesh.HttpGatewayRoutePathMatch.regex('regex'), + path: HttpGatewayRoutePathMatch.regex('regex'), }, }), }); @@ -634,10 +636,10 @@ For gRPC-based gateway routes, the `match` field can be used to match on service ```ts gateway.addGatewayRoute('gateway-route-grpc', { - routeSpec: appmesh.GatewayRouteSpec.grpc({ + routeSpec: GatewayRouteSpec.grpc({ routeTarget: virtualService, match: { - hostname: appmesh.GatewayRouteHostnameMatch.endsWith('.example.com'), + hostname: GatewayRouteHostnameMatch.endsWith('.example.com'), }, }), }); @@ -648,22 +650,22 @@ This automatic rewrite configuration can be overwritten in following ways: ```ts gateway.addGatewayRoute('gateway-route-http', { - routeSpec: appmesh.GatewayRouteSpec.http({ + routeSpec: GatewayRouteSpec.http({ routeTarget: virtualService, match: { // This disables the default rewrite to '/', and retains original path. - path: appmesh.HttpGatewayRoutePathMatch.startsWith('/path-to-app/', ''), + path: HttpGatewayRoutePathMatch.startsWith('/path-to-app/', ''), }, }), }); gateway.addGatewayRoute('gateway-route-http-1', { - routeSpec: appmesh.GatewayRouteSpec.http({ + routeSpec: GatewayRouteSpec.http({ routeTarget: virtualService, match: { // If the request full path is '/path-to-app/xxxxx', this rewrites the path to '/rewrittenUri/xxxxx'. // Please note both `prefixPathMatch` and `rewriteTo` must start and end with the `/` character. - path: appmesh.HttpGatewayRoutePathMatch.startsWith('/path-to-app/', '/rewrittenUri/'), + path: HttpGatewayRoutePathMatch.startsWith('/path-to-app/', '/rewrittenUri/'), }, }), }); @@ -674,11 +676,11 @@ Unlike `startsWith()` method above, no default rewrite is performed. ```ts gateway.addGatewayRoute('gateway-route-http-2', { - routeSpec: appmesh.GatewayRouteSpec.http({ + routeSpec: GatewayRouteSpec.http({ routeTarget: virtualService, match: { // This rewrites the path from '/test' to '/rewrittenPath'. - path: appmesh.HttpGatewayRoutePathMatch.exactly('/test', '/rewrittenPath'), + path: HttpGatewayRoutePathMatch.exactly('/test', '/rewrittenPath'), }, }), }); @@ -690,10 +692,10 @@ This default host name rewrite can be configured by specifying the rewrite rule ```ts gateway.addGatewayRoute('gateway-route-grpc', { - routeSpec: appmesh.GatewayRouteSpec.grpc({ + routeSpec: GatewayRouteSpec.grpc({ routeTarget: virtualService, match: { - hostname: appmesh.GatewayRouteHostnameMatch.exactly('example.com'), + hostname: GatewayRouteHostnameMatch.exactly('example.com'), // This disables the default rewrite to virtual service name and retain original request. rewriteRequestHostname: false, }, @@ -707,13 +709,13 @@ Each App Mesh resource class comes with two static methods, `fromArn` These imported resources can be used with other resources in your mesh as if they were defined directly in your CDK application. ```ts -const arn = "arn:aws:appmesh:us-east-1:123456789012:mesh/testMesh/virtualNode/testNode"; -appmesh.VirtualNode.fromVirtualNodeArn(stack, 'importedVirtualNode', arn); +const arn = 'arn:aws:appmesh:us-east-1:123456789012:mesh/testMesh/virtualNode/testNode'; +VirtualNode.fromVirtualNodeArn(stack, 'importedVirtualNode', arn); ``` ```ts -appmesh.VirtualNode.fromVirtualNodeAttributes(stack, 'imported-virtual-node', { - mesh: appmesh.Mesh.fromMeshName(stack, 'Mesh', 'testMesh'), +VirtualNode.fromVirtualNodeAttributes(stack, 'imported-virtual-node', { + mesh: Mesh.fromMeshName(stack, 'Mesh', 'testMesh'), virtualNodeName: virtualNodeName, }); ``` @@ -722,11 +724,11 @@ To import a mesh, again there are two static methods, `fromMeshArn` and `fromMes ```ts const arn = 'arn:aws:appmesh:us-east-1:123456789012:mesh/testMesh'; -appmesh.Mesh.fromMeshArn(stack, 'imported-mesh', arn); +Mesh.fromMeshArn(stack, 'imported-mesh', arn); ``` ```ts -appmesh.Mesh.fromMeshName(stack, 'imported-mesh', 'abc'); +Mesh.fromMeshName(stack, 'imported-mesh', 'abc'); ``` ## IAM Grants @@ -735,7 +737,7 @@ appmesh.Mesh.fromMeshName(stack, 'imported-mesh', 'abc'); Envoy access to stream generated config from App Mesh. ```ts -const gateway = new appmesh.VirtualGateway(stack, 'testGateway', { mesh: mesh }); +const gateway = new VirtualGateway(stack, 'testGateway', { mesh: mesh }); const envoyUser = new iam.User(stack, 'envoyUser'); /** @@ -752,10 +754,10 @@ A shared mesh allows resources created by different accounts to communicate with // This is the ARN for the mesh from different AWS IAM account ID. // Ensure mesh is properly shared with your account. For more details, see: https://github.com/aws/aws-cdk/issues/15404 const arn = 'arn:aws:appmesh:us-east-1:123456789012:mesh/testMesh'; -sharedMesh = appmesh.Mesh.fromMeshArn(stack, 'imported-mesh', arn); +sharedMesh = Mesh.fromMeshArn(stack, 'imported-mesh', arn); // This VirtualNode resource can communicate with the resources in the mesh from different AWS IAM account ID. -new appmesh.VirtualNode(stack, 'test-node', { +new VirtualNode(stack, 'test-node', { mesh: sharedMesh, }); ``` From a04c017323130cb6f88a530e192e9e0e86fb137a Mon Sep 17 00:00:00 2001 From: Jordan Brough Date: Fri, 6 Aug 2021 15:53:18 -0600 Subject: [PATCH 21/99] docs(ecs): Add missing word ("permission") in comment (#15889) To match the description just below that says: "grants containers in the task permission to call" ---- *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/lib/base/task-definition.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-ecs/lib/base/task-definition.ts b/packages/@aws-cdk/aws-ecs/lib/base/task-definition.ts index 1861098e1395b..91c019d9fa1f1 100644 --- a/packages/@aws-cdk/aws-ecs/lib/base/task-definition.ts +++ b/packages/@aws-cdk/aws-ecs/lib/base/task-definition.ts @@ -70,7 +70,7 @@ export interface CommonTaskDefinitionProps { readonly family?: string; /** - * The name of the IAM task execution role that grants the ECS agent to call AWS APIs on your behalf. + * The name of the IAM task execution role that grants the ECS agent permission to call AWS APIs on your behalf. * * The role will be used to retrieve container images from ECR and create CloudWatch log groups. * From e85c444137af6a708015eeba11692ff90b34a1ee Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Aug 2021 09:26:18 -0700 Subject: [PATCH 22/99] chore(deps): bump actions/setup-node from 2.3.0 to 2.4.0 (#15942) Bumps [actions/setup-node](https://github.com/actions/setup-node) from 2.3.0 to 2.4.0. - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/v2.3.0...v2.4.0) --- updated-dependencies: - dependency-name: actions/setup-node dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/yarn-upgrade.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/yarn-upgrade.yml b/.github/workflows/yarn-upgrade.yml index 918b691544287..2b5737a13ec1b 100644 --- a/.github/workflows/yarn-upgrade.yml +++ b/.github/workflows/yarn-upgrade.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@v2 - name: Set up Node - uses: actions/setup-node@v2.3.0 + uses: actions/setup-node@v2.4.0 with: node-version: 10 From c2d89761cda38932a590a49f40ec5546bd46d9bc Mon Sep 17 00:00:00 2001 From: Madeline Kusters <80541297+madeline-k@users.noreply.github.com> Date: Mon, 9 Aug 2021 12:22:42 -0700 Subject: [PATCH 23/99] chore(sam): explicit feature flags to produce a consistent template during tests (#15953) In v1, the default value of the @aws-cdk/core:newStyleStackSynthesis flag is false. As a consequence, Template.fromStack() generates, by default, a template without the rule and parameter related to bootstrap versions. In v2, the default value of this flag is true. So this test fails in the v2 branch. By explicitly setting the flag to false, we ensure that the tests passes on both v1 and v2, regardless of the default values. ---- *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-sam/test/application.test.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-sam/test/application.test.ts b/packages/@aws-cdk/aws-sam/test/application.test.ts index 5ba6e59a186ed..760c485ae6130 100644 --- a/packages/@aws-cdk/aws-sam/test/application.test.ts +++ b/packages/@aws-cdk/aws-sam/test/application.test.ts @@ -3,7 +3,12 @@ import * as cdk from '@aws-cdk/core'; import { CfnApplication } from '../lib'; test('construct an AWS::Serverless::Application', () => { - const stack = new cdk.Stack(); + const app = new cdk.App({ + context: { + '@aws-cdk/core:newStyleStackSynthesis': false, + }, + }); + const stack = new cdk.Stack(app); new CfnApplication(stack, 'App', { location: { From 6dc9d3e50d90143d4f455528b233dade9641e02e Mon Sep 17 00:00:00 2001 From: Madeline Kusters <80541297+madeline-k@users.noreply.github.com> Date: Mon, 9 Aug 2021 13:26:11 -0700 Subject: [PATCH 24/99] chore(servicecatalogappregistry): explicit feature flags to produce a consistent template during tests (#15955) In v1, the default value of the `@aws-cdk/core:newStyleStackSynthesis` flag is `false`. As a consequence, `Template.fromStack()` generates, by default, a template without the rule and parameter related to bootstrap versions. In v2, the default value of this flag is `true`. So this test fails in the v2 branch. By explicitly setting the flag to `false`, we ensure that the tests passes on both v1 and v2, regardless of the default values. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../aws-servicecatalogappregistry/test/application.test.ts | 7 ++++++- .../test/attribute-group.test.ts | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/test/application.test.ts b/packages/@aws-cdk/aws-servicecatalogappregistry/test/application.test.ts index 2cd30da1b5eb8..18b7b55884522 100644 --- a/packages/@aws-cdk/aws-servicecatalogappregistry/test/application.test.ts +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/test/application.test.ts @@ -6,7 +6,12 @@ describe('Application', () => { let stack: cdk.Stack; beforeEach(() => { - stack = new cdk.Stack(); + const app = new cdk.App({ + context: { + '@aws-cdk/core:newStyleStackSynthesis': false, + }, + }); + stack = new cdk.Stack(app); }); test('default application creation', () => { diff --git a/packages/@aws-cdk/aws-servicecatalogappregistry/test/attribute-group.test.ts b/packages/@aws-cdk/aws-servicecatalogappregistry/test/attribute-group.test.ts index 728ee04976623..b94ff8411afdd 100644 --- a/packages/@aws-cdk/aws-servicecatalogappregistry/test/attribute-group.test.ts +++ b/packages/@aws-cdk/aws-servicecatalogappregistry/test/attribute-group.test.ts @@ -6,7 +6,12 @@ describe('Attribute Group', () => { let stack: cdk.Stack; beforeEach(() => { - stack = new cdk.Stack(); + const app = new cdk.App({ + context: { + '@aws-cdk/core:newStyleStackSynthesis': false, + }, + }); + stack = new cdk.Stack(app); }); test('default attribute group creation', () => { From d3df03add2d704d6e33c94bc9b2178a58db63421 Mon Sep 17 00:00:00 2001 From: Madeline Kusters <80541297+madeline-k@users.noreply.github.com> Date: Mon, 9 Aug 2021 16:00:22 -0700 Subject: [PATCH 25/99] chore(glue, ivs, msk, servicecatalog): explicit feature flags to produce a consistent template during tests (#15960) In v1, the default value of the `@aws-cdk/core:newStyleStackSynthesis` flag is `false`. As a consequence, `Template.fromStack()` generates, by default, a template without the rule and parameter related to bootstrap versions. In v2, the default value of this flag is `true`. So this test fails in the v2 branch. By explicitly setting the flag to `false`, we ensure that the tests passes on both v1 and v2, regardless of the default values. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../@aws-cdk/aws-glue/test/database.test.ts | 22 +++++++------ packages/@aws-cdk/aws-ivs/test/ivs.test.ts | 31 +++++++------------ .../@aws-cdk/aws-msk/test/cluster.test.ts | 7 ++++- .../aws-servicecatalog/test/portfolio.test.ts | 7 ++++- 4 files changed, 36 insertions(+), 31 deletions(-) diff --git a/packages/@aws-cdk/aws-glue/test/database.test.ts b/packages/@aws-cdk/aws-glue/test/database.test.ts index 6c8171df3547c..6d94eb710131a 100644 --- a/packages/@aws-cdk/aws-glue/test/database.test.ts +++ b/packages/@aws-cdk/aws-glue/test/database.test.ts @@ -1,10 +1,19 @@ import { Template } from '@aws-cdk/assertions'; -import { Stack } from '@aws-cdk/core'; +import { App, Stack } from '@aws-cdk/core'; import * as glue from '../lib'; -test('default database does not create a bucket', () => { - const stack = new Stack(); +let stack: Stack; + +beforeEach( () => { + const app = new App({ + context: { + '@aws-cdk/core:newStyleStackSynthesis': false, + }, + }); + stack = new Stack(app); +}); +test('default database does not create a bucket', () => { new glue.Database(stack, 'Database', { databaseName: 'test_database', }); @@ -28,8 +37,6 @@ test('default database does not create a bucket', () => { }); test('explicit locationURI', () => { - const stack = new Stack(); - new glue.Database(stack, 'Database', { databaseName: 'test_database', locationUri: 's3://my-uri/', @@ -55,9 +62,6 @@ test('explicit locationURI', () => { }); test('fromDatabase', () => { - // GIVEN - const stack = new Stack(); - // WHEN const database = glue.Database.fromDatabaseArn(stack, 'import', 'arn:aws:glue:us-east-1:123456789012:database/db1'); @@ -72,7 +76,6 @@ test('fromDatabase', () => { }); test('locationUri length must be >= 1', () => { - const stack = new Stack(); expect(() => new glue.Database(stack, 'Database', { databaseName: 'test_database', @@ -82,7 +85,6 @@ test('locationUri length must be >= 1', () => { }); test('locationUri length must be <= 1024', () => { - const stack = new Stack(); expect(() => new glue.Database(stack, 'Database', { databaseName: 'test_database', diff --git a/packages/@aws-cdk/aws-ivs/test/ivs.test.ts b/packages/@aws-cdk/aws-ivs/test/ivs.test.ts index 0e5efd63d5b2a..82e3b41e79e64 100644 --- a/packages/@aws-cdk/aws-ivs/test/ivs.test.ts +++ b/packages/@aws-cdk/aws-ivs/test/ivs.test.ts @@ -1,5 +1,5 @@ import { Template } from '@aws-cdk/assertions'; -import { Stack } from '@aws-cdk/core'; +import { App, Stack } from '@aws-cdk/core'; import * as ivs from '../lib'; const publicKey = `-----BEGIN PUBLIC KEY----- @@ -8,8 +8,18 @@ Yfo83eX0GJCKxJ8fr09h9LP9HDGof8/bo66P+SGHeAARGF/O9WPAQVUgSlm/KMFX EPtPtOm1s0GR9k1ydU5hkI++f9CoZ5lM -----END PUBLIC KEY-----`; +let stack: Stack; + +beforeEach( () => { + const app = new App({ + context: { + '@aws-cdk/core:newStyleStackSynthesis': false, + }, + }); + stack = new Stack(app); +}); + test('channel default properties', () => { - const stack = new Stack(); new ivs.Channel(stack, 'Channel'); Template.fromStack(stack).templateMatches({ @@ -22,7 +32,6 @@ test('channel default properties', () => { }); test('channel name', () => { - const stack = new Stack(); new ivs.Channel(stack, 'Channel', { name: 'CarrotsAreTasty', }); @@ -40,7 +49,6 @@ test('channel name', () => { }); test('channel is authorized', () => { - const stack = new Stack(); new ivs.Channel(stack, 'Channel', { authorized: true, }); @@ -58,7 +66,6 @@ test('channel is authorized', () => { }); test('channel type', () => { - const stack = new Stack(); new ivs.Channel(stack, 'Channel', { type: ivs.ChannelType.BASIC, }); @@ -76,7 +83,6 @@ test('channel type', () => { }); test('channel latency mode', () => { - const stack = new Stack(); new ivs.Channel(stack, 'Channel', { latencyMode: ivs.LatencyMode.NORMAL, }); @@ -94,22 +100,18 @@ test('channel latency mode', () => { }); test('channel from arn', () => { - const stack = new Stack(); const channel = ivs.Channel.fromChannelArn(stack, 'Channel', 'arn:aws:ivs:us-west-2:123456789012:channel/abcdABCDefgh'); expect(stack.resolve(channel.channelArn)).toBe('arn:aws:ivs:us-west-2:123456789012:channel/abcdABCDefgh'); }); test('channel invalid name throws validation error', () => { - const stack = new Stack(); - expect(() => new ivs.Channel(stack, 'Channel', { name: 'Would you like a carrot?', })).toThrow('name must contain only numbers, letters, hyphens and underscores, got: \'Would you like a carrot?\''); }); test('playback key pair mandatory properties', () => { - const stack = new Stack(); new ivs.PlaybackKeyPair(stack, 'PlaybackKeyPair', { publicKeyMaterial: publicKey, }); @@ -127,7 +129,6 @@ test('playback key pair mandatory properties', () => { }); test('playback key pair name', () => { - const stack = new Stack(); new ivs.PlaybackKeyPair(stack, 'PlaybackKeyPair', { publicKeyMaterial: publicKey, name: 'CarrotsAreNutritious', @@ -147,8 +148,6 @@ test('playback key pair name', () => { }); test('playback key pair invalid name throws validation error', () => { - const stack = new Stack(); - expect(() => new ivs.PlaybackKeyPair(stack, 'PlaybackKeyPair', { publicKeyMaterial: 'Carrots Are Orange', name: 'Would you like a carrot?', @@ -156,7 +155,6 @@ test('playback key pair invalid name throws validation error', () => { }); test('stream key mandatory properties', () => { - const stack = new Stack(); new ivs.StreamKey(stack, 'StreamKey', { channel: ivs.Channel.fromChannelArn(stack, 'ChannelRef', 'arn:aws:ivs:us-west-2:123456789012:channel/abcdABCDefgh'), }); @@ -174,7 +172,6 @@ test('stream key mandatory properties', () => { }); test('channel and stream key.. at the same time', () => { - const stack = new Stack(); const channel = new ivs.Channel(stack, 'Channel'); channel.addStreamKey('StreamKey'); @@ -194,7 +191,6 @@ test('channel and stream key.. at the same time', () => { }); test('stream key from channel reference', () => { - const stack = new Stack(); const channel = ivs.Channel.fromChannelArn(stack, 'Channel', 'arn:aws:ivs:us-west-2:123456789012:channel/abcdABCDefgh'); channel.addStreamKey('StreamKey'); @@ -211,20 +207,17 @@ test('stream key from channel reference', () => { }); test('channel from invalid channel arn throws error', () => { - const stack = new Stack(); expect(() => ivs.Channel.fromChannelArn(stack, 'ChannelRef', 'this is an invalid arn, in fact, it is a carrot 🥕')) .toThrow('ARNs must start with \"arn:\" and have at least 6 components: this is an invalid arn, in fact, it is a carrot 🥕'); }); test('channel from invalid channel arn service throws error', () => { - const stack = new Stack(); expect( () => ivs.Channel.fromChannelArn(stack, 'ChannelRef', 'arn:aws:ec2:us-west-2:123456789012:instance/abcdABCDefgh')) .toThrow('Invalid service, expected \'ivs\', got \'ec2\''); }); test('channel from invalid channel arn resource throws error', () => { - const stack = new Stack(); expect( () => ivs.Channel.fromChannelArn(stack, 'ChannelRef', 'arn:aws:ivs:us-west-2:123456789012:stream-key/abcdABCDefgh')) .toThrow('Invalid resource, expected \'channel\', got \'stream-key\''); diff --git a/packages/@aws-cdk/aws-msk/test/cluster.test.ts b/packages/@aws-cdk/aws-msk/test/cluster.test.ts index a990895e16d9c..71877df25e95a 100644 --- a/packages/@aws-cdk/aws-msk/test/cluster.test.ts +++ b/packages/@aws-cdk/aws-msk/test/cluster.test.ts @@ -13,7 +13,12 @@ describe('MSK Cluster', () => { let vpc: ec2.IVpc; beforeEach(() => { - stack = new core.Stack(); + const app = new core.App({ + context: { + '@aws-cdk/core:newStyleStackSynthesis': false, + }, + }); + stack = new core.Stack(app); vpc = new ec2.Vpc(stack, 'Vpc'); }); diff --git a/packages/@aws-cdk/aws-servicecatalog/test/portfolio.test.ts b/packages/@aws-cdk/aws-servicecatalog/test/portfolio.test.ts index 216c34295cab2..8f9a27a96a940 100644 --- a/packages/@aws-cdk/aws-servicecatalog/test/portfolio.test.ts +++ b/packages/@aws-cdk/aws-servicecatalog/test/portfolio.test.ts @@ -8,7 +8,12 @@ describe('Portfolio', () => { let stack: cdk.Stack; beforeEach(() => { - stack = new cdk.Stack(); + const app = new cdk.App({ + context: { + '@aws-cdk/core:newStyleStackSynthesis': false, + }, + }); + stack = new cdk.Stack(app); }); describe('portfolio creation and importing', () => { From c3b872ad47ff3bdf2c841aa195b6fa6922c03769 Mon Sep 17 00:00:00 2001 From: hanukoon Date: Tue, 10 Aug 2021 21:12:52 +0900 Subject: [PATCH 26/99] fix(ec2): "clientVpnEndoint" => "clientVpnEndpoint" (#14902) It is a solution to the issue #13810 Corrected the typo "clientVpnEndpoint" in the ec2 module to "clientVpnEnpoint". The maintainer (@rix0rrr) talked about @deprecated tags on existing incorrect members in the issue thread, but I didn't work on it because I thought it was an internal reference member. (if @deprecated tag is the rule of this repository in this case, please comment). This is my first commitment to this report. If there's anything wrong, please let me know in the comments. thanks ---- edit ----- Originally, this PR was #14835 , but I deleted my fork report by mistake, so I couldn't correct the error, so I uploaded it again. --- .../lib/client-vpn-authorization-rule.ts | 25 +++- .../aws-ec2/lib/client-vpn-endpoint.ts | 4 +- .../@aws-cdk/aws-ec2/lib/client-vpn-route.ts | 28 +++- .../client-vpn-authorization-rule.test.ts | 93 ++++++++++++++ .../aws-ec2/test/client-vpn-route.test.ts | 121 ++++++++++++++++++ 5 files changed, 262 insertions(+), 9 deletions(-) create mode 100644 packages/@aws-cdk/aws-ec2/test/client-vpn-authorization-rule.test.ts create mode 100644 packages/@aws-cdk/aws-ec2/test/client-vpn-route.test.ts diff --git a/packages/@aws-cdk/aws-ec2/lib/client-vpn-authorization-rule.ts b/packages/@aws-cdk/aws-ec2/lib/client-vpn-authorization-rule.ts index c63f940ab4883..ea574628d16e5 100644 --- a/packages/@aws-cdk/aws-ec2/lib/client-vpn-authorization-rule.ts +++ b/packages/@aws-cdk/aws-ec2/lib/client-vpn-authorization-rule.ts @@ -35,8 +35,16 @@ export interface ClientVpnAuthorizationRuleOptions { export interface ClientVpnAuthorizationRuleProps extends ClientVpnAuthorizationRuleOptions { /** * The client VPN endpoint to which to add the rule. + * @default clientVpnEndpoint is required */ - readonly clientVpnEndoint: IClientVpnEndpoint; + readonly clientVpnEndpoint?: IClientVpnEndpoint; + + /** + * The client VPN endpoint to which to add the rule. + * @deprecated Use `clientVpnEndpoint` instead + * @default clientVpnEndpoint is required + */ + readonly clientVpnEndoint?: IClientVpnEndpoint; } /** @@ -44,10 +52,21 @@ export interface ClientVpnAuthorizationRuleProps extends ClientVpnAuthorizationR */ export class ClientVpnAuthorizationRule extends Resource { constructor(scope: Construct, id: string, props: ClientVpnAuthorizationRuleProps) { + if (!props.clientVpnEndoint && !props.clientVpnEndpoint) { + throw new Error( + 'ClientVpnAuthorizationRule: either clientVpnEndpoint or clientVpnEndoint (deprecated) must be specified', + ); + } + if (props.clientVpnEndoint && props.clientVpnEndpoint) { + throw new Error( + 'ClientVpnAuthorizationRule: either clientVpnEndpoint or clientVpnEndoint (deprecated) must be specified' + + ', but not both', + ); + } + const clientVpnEndpoint = props.clientVpnEndoint || props.clientVpnEndpoint; super(scope, id); - new CfnClientVpnAuthorizationRule(this, 'Resource', { - clientVpnEndpointId: props.clientVpnEndoint.endpointId, + clientVpnEndpointId: clientVpnEndpoint!.endpointId, targetNetworkCidr: props.cidr, accessGroupId: props.groupId, authorizeAllGroups: !props.groupId, diff --git a/packages/@aws-cdk/aws-ec2/lib/client-vpn-endpoint.ts b/packages/@aws-cdk/aws-ec2/lib/client-vpn-endpoint.ts index 43431bd649046..3ee8e8956d3d1 100644 --- a/packages/@aws-cdk/aws-ec2/lib/client-vpn-endpoint.ts +++ b/packages/@aws-cdk/aws-ec2/lib/client-vpn-endpoint.ts @@ -356,7 +356,7 @@ export class ClientVpnEndpoint extends Resource implements IClientVpnEndpoint { public addAuthorizationRule(id: string, props: ClientVpnAuthorizationRuleOptions): ClientVpnAuthorizationRule { return new ClientVpnAuthorizationRule(this, id, { ...props, - clientVpnEndoint: this, + clientVpnEndpoint: this, }); } @@ -366,7 +366,7 @@ export class ClientVpnEndpoint extends Resource implements IClientVpnEndpoint { public addRoute(id: string, props: ClientVpnRouteOptions): ClientVpnRoute { return new ClientVpnRoute(this, id, { ...props, - clientVpnEndoint: this, + clientVpnEndpoint: this, }); } } diff --git a/packages/@aws-cdk/aws-ec2/lib/client-vpn-route.ts b/packages/@aws-cdk/aws-ec2/lib/client-vpn-route.ts index 38734631a5d91..dd0c026be5a55 100644 --- a/packages/@aws-cdk/aws-ec2/lib/client-vpn-route.ts +++ b/packages/@aws-cdk/aws-ec2/lib/client-vpn-route.ts @@ -62,10 +62,19 @@ export abstract class ClientVpnRouteTarget { * Properties for a ClientVpnRoute */ export interface ClientVpnRouteProps extends ClientVpnRouteOptions { + + /** + * The client VPN endpoint to which to add the route. + * @default clientVpnEndpoint is required + */ + readonly clientVpnEndpoint?: IClientVpnEndpoint; /** * The client VPN endpoint to which to add the route. + * @deprecated Use `clientVpnEndpoint` instead + * @default clientVpnEndpoint is required + */ - readonly clientVpnEndoint: IClientVpnEndpoint; + readonly clientVpnEndoint?: IClientVpnEndpoint; } /** @@ -73,16 +82,27 @@ export interface ClientVpnRouteProps extends ClientVpnRouteOptions { */ export class ClientVpnRoute extends Resource { constructor(scope: Construct, id: string, props: ClientVpnRouteProps) { + if (!props.clientVpnEndoint && !props.clientVpnEndpoint) { + throw new Error( + 'ClientVpnRoute: either clientVpnEndpoint or clientVpnEndoint (deprecated) must be specified', + ); + } + if (props.clientVpnEndoint && props.clientVpnEndpoint) { + throw new Error( + 'ClientVpnRoute: either clientVpnEndpoint or clientVpnEndoint (deprecated) must be specified' + + ', but not both', + ); + } + const clientVpnEndpoint = props.clientVpnEndoint || props.clientVpnEndpoint; super(scope, id); - const route = new CfnClientVpnRoute(this, 'Resource', { - clientVpnEndpointId: props.clientVpnEndoint.endpointId, + clientVpnEndpointId: clientVpnEndpoint!.endpointId, description: props.description, destinationCidrBlock: props.cidr, targetVpcSubnetId: props.target.subnetId, }); // See https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-clientvpnroute.html - route.node.addDependency(props.clientVpnEndoint.targetNetworksAssociated); + route.node.addDependency(clientVpnEndpoint!.targetNetworksAssociated); } } diff --git a/packages/@aws-cdk/aws-ec2/test/client-vpn-authorization-rule.test.ts b/packages/@aws-cdk/aws-ec2/test/client-vpn-authorization-rule.test.ts new file mode 100644 index 0000000000000..6c8911d90a06d --- /dev/null +++ b/packages/@aws-cdk/aws-ec2/test/client-vpn-authorization-rule.test.ts @@ -0,0 +1,93 @@ +import '@aws-cdk/assert-internal/jest'; +import { Stack } from '@aws-cdk/core'; +import { Connections, IClientVpnEndpoint } from '../lib'; +import { ClientVpnAuthorizationRule } from '../lib/client-vpn-authorization-rule'; + +let stack: Stack; +beforeEach(() => { + stack = new Stack(); +}); + +describe('ClientVpnAuthorizationRule constructor', () => { + test('normal usage', () => { + const clientVpnEndpoint: IClientVpnEndpoint = { + endpointId: 'myClientVpnEndpoint', + targetNetworksAssociated: [], + stack, + env: { account: 'myAccount', region: 'us-east-1' }, + connections: new Connections(), + node: stack.node, + }; + new ClientVpnAuthorizationRule(stack, 'NormalRule', { + cidr: '10.0.10.0/32', + clientVpnEndpoint, + }); + expect(stack).toCountResources('AWS::EC2::ClientVpnAuthorizationRule', 1); + expect(stack.node.children.length).toBe(1); + }); + test('either clientVpnEndoint (deprecated, typo) or clientVpnEndpoint is required', () => { + expect(() => { + new ClientVpnAuthorizationRule(stack, 'RuleNoEndointNoEndpoint', { + cidr: '10.0.10.0/32', + }); + }).toThrow( + new Error( + 'ClientVpnAuthorizationRule: either clientVpnEndpoint or clientVpnEndoint (deprecated) must be specified', + ), + ); + }); + test('specifying both clientVpnEndoint (deprecated, typo) and clientVpnEndpoint is not allowed', () => { + const clientVpnEndoint: IClientVpnEndpoint = { + endpointId: 'typoTypo', + targetNetworksAssociated: [], + stack, + env: { account: 'myAccount', region: 'us-east-1' }, + connections: new Connections(), + node: stack.node, + }; + const clientVpnEndpoint: IClientVpnEndpoint = { + endpointId: 'myClientVpnEndpoint', + targetNetworksAssociated: [], + stack, + env: { account: 'myAccount', region: 'us-east-1' }, + connections: new Connections(), + node: stack.node, + }; + expect(() => { + new ClientVpnAuthorizationRule(stack, 'RuleBothEndointAndEndpoint', { + cidr: '10.0.10.0/32', + clientVpnEndoint, + clientVpnEndpoint, + }); + }).toThrow( + new Error( + 'ClientVpnAuthorizationRule: either clientVpnEndpoint or clientVpnEndoint (deprecated) must be specified' + + ', but not both', + ), + ); + }); + test('invalid constructor calls should not add anything to the stack', () => { + expect(() => { + new ClientVpnAuthorizationRule(stack, 'RuleNoEndointNoEndpoint', { + cidr: '10.0.10.0/32', + }); + }).toThrow(); + expect(stack.node.children.length).toBe(0); + }); + test('supplying clientVpnEndoint (deprecated due to typo) should still work', () => { + const clientVpnEndoint: IClientVpnEndpoint = { + endpointId: 'myClientVpnEndpoint', + targetNetworksAssociated: [], + stack, + env: { account: 'myAccount', region: 'us-east-1' }, + connections: new Connections(), + node: stack.node, + }; + new ClientVpnAuthorizationRule(stack, 'RuleWithEndointTypo', { + cidr: '10.0.10.0/32', + clientVpnEndoint, + }); + expect(stack).toCountResources('AWS::EC2::ClientVpnAuthorizationRule', 1); + expect(stack.node.children.length).toBe(1); + }); +}); diff --git a/packages/@aws-cdk/aws-ec2/test/client-vpn-route.test.ts b/packages/@aws-cdk/aws-ec2/test/client-vpn-route.test.ts new file mode 100644 index 0000000000000..42f094ab4bb9e --- /dev/null +++ b/packages/@aws-cdk/aws-ec2/test/client-vpn-route.test.ts @@ -0,0 +1,121 @@ +import '@aws-cdk/assert-internal/jest'; +import { SamlMetadataDocument, SamlProvider } from '@aws-cdk/aws-iam'; +import { Stack } from '@aws-cdk/core'; +import * as ec2 from '../lib'; +import { + ClientVpnRoute, + ClientVpnRouteTarget, + ClientVpnUserBasedAuthentication, +} from '../lib'; + +let stack: Stack; +let vpc: ec2.IVpc; +beforeEach(() => { + stack = new Stack(); + vpc = new ec2.Vpc(stack, 'Vpc'); +}); + +describe('ClientVpnRoute constructor', () => { + test('normal usage', () => { + const samlProvider = new SamlProvider(stack, 'Provider', { + metadataDocument: SamlMetadataDocument.fromXml('xml'), + }); + const clientVpnEndpoint = vpc.addClientVpnEndpoint('Endpoint', { + cidr: '10.100.0.0/16', + serverCertificateArn: 'server-certificate-arn', + clientCertificateArn: 'client-certificate-arn', + clientConnectionHandler: { + functionArn: 'function-arn', + functionName: 'AWSClientVPN-function-name', + }, + dnsServers: ['8.8.8.8', '8.8.4.4'], + userBasedAuthentication: ClientVpnUserBasedAuthentication.federated(samlProvider), + }); + new ClientVpnRoute(stack, 'NormalRoute', { + clientVpnEndpoint, + cidr: '0.0.0.0/0', + target: ClientVpnRouteTarget.local(), + }); + expect(stack).toCountResources('AWS::EC2::VPC', 1); + expect(stack).toCountResources('AWS::EC2::ClientVpnEndpoint', 1); + expect(stack).toCountResources('AWS::EC2::ClientVpnRoute', 1); + expect(stack.node.children.length).toBe(3); + }); + test('either clientVpnEndoint (deprecated, typo) or clientVpnEndpoint is required', () => { + expect(() => { + new ClientVpnRoute(stack, 'RouteNoEndointOrEndpoint', { + cidr: '0.0.0.0/0', + target: ClientVpnRouteTarget.local(), + }); + }).toThrow( + new Error( + 'ClientVpnRoute: either clientVpnEndpoint or clientVpnEndoint (deprecated) must be specified', + ), + ); + }); + test('specifying both clientVpnEndoint (deprecated, typo) and clientVpnEndpoint is not allowed', () => { + const samlProvider = new SamlProvider(stack, 'Provider', { + metadataDocument: SamlMetadataDocument.fromXml('xml'), + }); + const clientVpnEndpoint = vpc.addClientVpnEndpoint('Endpoint', { + cidr: '10.100.0.0/16', + serverCertificateArn: 'server-certificate-arn', + clientCertificateArn: 'client-certificate-arn', + clientConnectionHandler: { + functionArn: 'function-arn', + functionName: 'AWSClientVPN-function-name', + }, + dnsServers: ['8.8.8.8', '8.8.4.4'], + userBasedAuthentication: ClientVpnUserBasedAuthentication.federated(samlProvider), + }); + const clientVpnEndoint = clientVpnEndpoint; + expect(() => { + new ClientVpnRoute(stack, 'RouteBothEndointAndEndpoint', { + clientVpnEndoint, + clientVpnEndpoint, + cidr: '0.0.0.0/0', + target: ClientVpnRouteTarget.local(), + }); + }).toThrow( + new Error( + 'ClientVpnRoute: either clientVpnEndpoint or clientVpnEndoint (deprecated) must be specified' + + ', but not both', + ), + ); + }); + test('invalid constructor calls should not add anything to the stack', () => { + expect(() => { + new ClientVpnRoute(stack, 'RouteNoEndointOrEndpoint', { + cidr: '0.0.0.0/0', + target: ClientVpnRouteTarget.local(), + }); + }).toThrow(); + expect(stack).toCountResources('AWS::EC2::VPC', 1); + expect(stack.node.children.length).toBe(1); + }); + test('supplying clientVpnEndoint (deprecated due to typo) should still work', () => { + const samlProvider = new SamlProvider(stack, 'Provider', { + metadataDocument: SamlMetadataDocument.fromXml('xml'), + }); + const clientVpnEndoint = vpc.addClientVpnEndpoint('Endpoint', { + cidr: '10.100.0.0/16', + serverCertificateArn: 'server-certificate-arn', + clientCertificateArn: 'client-certificate-arn', + clientConnectionHandler: { + functionArn: 'function-arn', + functionName: 'AWSClientVPN-function-name', + }, + dnsServers: ['8.8.8.8', '8.8.4.4'], + userBasedAuthentication: ClientVpnUserBasedAuthentication.federated(samlProvider), + }); + new ClientVpnRoute(stack, 'RouteWithEndointTypo', { + clientVpnEndoint, + cidr: '0.0.0.0/0', + target: ClientVpnRouteTarget.local(), + }); + expect(stack).toCountResources('AWS::EC2::VPC', 1); + expect(stack).toCountResources('AWS::EC2::ClientVpnEndpoint', 1); + expect(stack).toCountResources('AWS::EC2::ClientVpnRoute', 1); + expect(stack.node.children.length).toBe(3); + }); +}); From 04b8d400b2653aff4f48709e8b420c6adb996ef5 Mon Sep 17 00:00:00 2001 From: Thorsten Hoeger Date: Tue, 10 Aug 2021 14:56:32 +0200 Subject: [PATCH 27/99] feat(pipelines): add `synthCodeBuildDefaults` (#15627) This change allows specifying the codeBuildDefaults for the synth-action as it is already possible with assets and self-mutation. ---- *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 | 7 ++++--- .../pipelines/lib/codepipeline/codepipeline.ts | 15 +++++++++++---- .../pipelines/test/compliance/synths.test.ts | 8 ++++++++ 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/packages/@aws-cdk/pipelines/README.md b/packages/@aws-cdk/pipelines/README.md index 103715704ec62..f17a35e3a9990 100644 --- a/packages/@aws-cdk/pipelines/README.md +++ b/packages/@aws-cdk/pipelines/README.md @@ -547,7 +547,7 @@ of properties that allow you to customize various aspects of the projects: ```ts new CodeBuildStep('Synth', { - // ...standard RunScript props... + // ...standard ShellStep props... commands: [/* ... */], env: { /* ... */ }, @@ -582,8 +582,8 @@ new CodeBuildStep('Synth', { ``` You can also configure defaults for *all* CodeBuild projects by passing `codeBuildDefaults`, -or just for the asset publishing and self-mutation projects by passing `assetPublishingCodeBuildDefaults` -or `selfMutationCodeBuildDefaults`: +or just for the synth, asset publishing, and self-mutation projects by passing `synthCodeBuildDefaults`, +`assetPublishingCodeBuildDefaults`, or `selfMutationCodeBuildDefaults`: ```ts new CodePipeline(this, 'Pipeline', { @@ -613,6 +613,7 @@ new CodePipeline(this, 'Pipeline', { ], }, + synthCodeBuildDefaults: { /* ... */ }, assetPublishingCodeBuildDefaults: { /* ... */ }, selfMutationCodeBuildDefaults: { /* ... */ }, }); diff --git a/packages/@aws-cdk/pipelines/lib/codepipeline/codepipeline.ts b/packages/@aws-cdk/pipelines/lib/codepipeline/codepipeline.ts index cc4cdeea3aa3f..27a2b15509532 100644 --- a/packages/@aws-cdk/pipelines/lib/codepipeline/codepipeline.ts +++ b/packages/@aws-cdk/pipelines/lib/codepipeline/codepipeline.ts @@ -132,17 +132,24 @@ export interface CodePipelineProps { */ readonly codeBuildDefaults?: CodeBuildOptions; + /** + * Additional customizations to apply to the synthesize CodeBuild projects + * + * @default - Only `codeBuildDefaults` are applied + */ + readonly synthCodeBuildDefaults?: CodeBuildOptions; + /** * Additional customizations to apply to the asset publishing CodeBuild projects * - * @default - Only `codeBuildProjectDefaults` are applied + * @default - Only `codeBuildDefaults` are applied */ readonly assetPublishingCodeBuildDefaults?: CodeBuildOptions; /** * Additional customizations to apply to the self mutation CodeBuild projects * - * @default - Only `codeBuildProjectDefaults` are applied + * @default - Only `codeBuildDefaults` are applied */ readonly selfMutationCodeBuildDefaults?: CodeBuildOptions; @@ -681,8 +688,8 @@ export class CodePipeline extends PipelineBase { const typeBasedCustomizations = { [CodeBuildProjectType.SYNTH]: this.props.dockerEnabledForSynth - ? { buildEnvironment: { privileged: true } } - : {}, + ? mergeCodeBuildOptions(this.props.synthCodeBuildDefaults, { buildEnvironment: { privileged: true } }) + : this.props.synthCodeBuildDefaults, [CodeBuildProjectType.ASSETS]: this.props.assetPublishingCodeBuildDefaults, diff --git a/packages/@aws-cdk/pipelines/test/compliance/synths.test.ts b/packages/@aws-cdk/pipelines/test/compliance/synths.test.ts index 7c47600b66155..247cbd50974e0 100644 --- a/packages/@aws-cdk/pipelines/test/compliance/synths.test.ts +++ b/packages/@aws-cdk/pipelines/test/compliance/synths.test.ts @@ -559,6 +559,14 @@ behavior('Synth can be made to run in a VPC', (suite) => { THEN_codePipelineExpectation(); }); + suite.additional('Modern, using the synthCodeBuildDefaults', () => { + new ModernTestGitHubNpmPipeline(pipelineStack, 'Cdk', { + synthCodeBuildDefaults: { vpc }, + }); + + THEN_codePipelineExpectation(); + }); + suite.additional('Modern, using CodeBuildStep', () => { new ModernTestGitHubNpmPipeline(pipelineStack, 'Cdk', { synth: new CodeBuildStep('Synth', { From 6b32b2fb0c6ed2a21eb929e39930c6c9cf668dae Mon Sep 17 00:00:00 2001 From: nohack <61228138+nohack@users.noreply.github.com> Date: Tue, 10 Aug 2021 23:08:31 +0530 Subject: [PATCH 28/99] feat(aws-elbv2): ALB target group routing algorithms (#15622) Closes #15160 --- .../lib/alb/application-listener.ts | 11 +++++++- .../lib/alb/application-target-group.ts | 12 ++++++++- .../lib/shared/enums.ts | 15 +++++++++++ .../test/alb/listener.test.ts | 25 +++++++++++++++++++ .../test/alb/target-group.test.ts | 23 +++++++++++++++++ 5 files changed, 84 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-listener.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-listener.ts index 8d52d3bc60eb4..a1ea49a3b18a6 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-listener.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-listener.ts @@ -5,7 +5,7 @@ import * as cxapi from '@aws-cdk/cx-api'; import { Construct } from 'constructs'; import { BaseListener, BaseListenerLookupOptions } from '../shared/base-listener'; import { HealthCheck } from '../shared/base-target-group'; -import { ApplicationProtocol, ApplicationProtocolVersion, IpAddressType, SslPolicy } from '../shared/enums'; +import { ApplicationProtocol, ApplicationProtocolVersion, TargetGroupLoadBalancingAlgorithmType, IpAddressType, SslPolicy } from '../shared/enums'; import { IListenerCertificate, ListenerCertificate } from '../shared/listener-certificate'; import { determineProtocolAndPort } from '../shared/util'; import { ListenerAction } from './application-listener-action'; @@ -367,6 +367,7 @@ export class ApplicationListener extends BaseListener implements IApplicationLis slowStart: props.slowStart, stickinessCookieDuration: props.stickinessCookieDuration, stickinessCookieName: props.stickinessCookieName, + loadBalancingAlgorithmType: props.loadBalancingAlgorithmType, targetGroupName: props.targetGroupName, targets: props.targets, vpc: this.loadBalancer.vpc, @@ -887,6 +888,14 @@ export interface AddApplicationTargetsProps extends AddRuleProps { * @default No health check */ readonly healthCheck?: HealthCheck; + + /** + * The load balancing algorithm to select targets for routing requests. + * + * @default round_robin. + */ + readonly loadBalancingAlgorithmType?: TargetGroupLoadBalancingAlgorithmType; + } /** diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-target-group.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-target-group.ts index e7a6b2eef27d1..4c3085f2d5a66 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-target-group.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-target-group.ts @@ -7,7 +7,7 @@ import { BaseTargetGroupProps, ITargetGroup, loadBalancerNameFromListenerArn, LoadBalancerTargetProps, TargetGroupAttributes, TargetGroupBase, TargetGroupImportProps, } from '../shared/base-target-group'; -import { ApplicationProtocol, ApplicationProtocolVersion, Protocol, TargetType } from '../shared/enums'; +import { ApplicationProtocol, ApplicationProtocolVersion, Protocol, TargetType, TargetGroupLoadBalancingAlgorithmType } from '../shared/enums'; import { ImportedTargetGroupBase } from '../shared/imported'; import { determineProtocolAndPort } from '../shared/util'; import { IApplicationListener } from './application-listener'; @@ -78,6 +78,13 @@ export interface ApplicationTargetGroupProps extends BaseTargetGroupProps { */ readonly stickinessCookieName?: string; + /** + * The load balancing algorithm to select targets for routing requests. + * + * @default TargetGroupLoadBalancingAlgorithmType.ROUND_ROBIN + */ + readonly loadBalancingAlgorithmType?: TargetGroupLoadBalancingAlgorithmType; + /** * The targets to add to this target group. * @@ -140,6 +147,9 @@ export class ApplicationTargetGroup extends TargetGroupBase implements IApplicat if (props.stickinessCookieDuration) { this.enableCookieStickiness(props.stickinessCookieDuration, props.stickinessCookieName); } + if (props.loadBalancingAlgorithmType) { + this.setAttribute('load_balancing.algorithm.type', props.loadBalancingAlgorithmType); + } this.addTarget(...(props.targets || [])); } } diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/enums.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/enums.ts index 8c5f183bb2cc2..94a9473ab9bc9 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/enums.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/enums.ts @@ -171,3 +171,18 @@ export enum TargetType { */ LAMBDA = 'lambda', } + +/** + * Load balancing algorithmm type for target groups + */ +export enum TargetGroupLoadBalancingAlgorithmType { + /** + * round_robin + */ + ROUND_ROBIN = 'round_robin', + + /** + * least_outstanding_requests + */ + LEAST_OUTSTANDING_REQUESTS = 'least_outstanding_requests', +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/listener.test.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/listener.test.ts index fffc6e365bcea..2d945aeb2621f 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/listener.test.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/listener.test.ts @@ -866,6 +866,31 @@ describe('tests', () => { }); }); + test('Custom Load balancer algorithm type', () => { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + const lb = new elbv2.ApplicationLoadBalancer(stack, 'LB', { vpc }); + const listener = lb.addListener('Listener', { port: 80 }); + + // WHEN + listener.addTargets('Group', { + port: 80, + targets: [new FakeSelfRegisteringTarget(stack, 'Target', vpc)], + loadBalancingAlgorithmType: elbv2.TargetGroupLoadBalancingAlgorithmType.LEAST_OUTSTANDING_REQUESTS, + }); + + // THEN + expect(stack).toHaveResource('AWS::ElasticLoadBalancingV2::TargetGroup', { + TargetGroupAttributes: [ + { + Key: 'load_balancing.algorithm.type', + Value: 'least_outstanding_requests', + }, + ], + }); + }); + describe('Throws with bad fixed responses', () => { test('status code', () => { diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/target-group.test.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/target-group.test.ts index 965844affb709..97c36c33ce237 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/target-group.test.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/target-group.test.ts @@ -156,6 +156,29 @@ describe('tests', () => { }); }); + test('Custom Load balancer algorithm type', () => { + // GIVEN + const app = new cdk.App(); + const stack = new cdk.Stack(app, 'Stack'); + const vpc = new ec2.Vpc(stack, 'VPC', {}); + + // WHEN + new elbv2.ApplicationTargetGroup(stack, 'TargetGroup', { + loadBalancingAlgorithmType: elbv2.TargetGroupLoadBalancingAlgorithmType.LEAST_OUTSTANDING_REQUESTS, + vpc, + }); + + // THEN + expect(stack).toHaveResource('AWS::ElasticLoadBalancingV2::TargetGroup', { + TargetGroupAttributes: [ + { + Key: 'load_balancing.algorithm.type', + Value: 'least_outstanding_requests', + }, + ], + }); + }); + test('Can set a protocol version', () => { // GIVEN const app = new cdk.App(); From 59245429acb9e54c46c051d9c19f103698c4610d Mon Sep 17 00:00:00 2001 From: Julian Michel Date: Tue, 10 Aug 2021 21:27:21 +0200 Subject: [PATCH 29/99] docs(cognito): describe addDependency for identity provider and app client (#15893) When an app client is created, it receives the name of the identity provider as a string. During the deployment, the identity provider must be created first, then the app client can be created (because it references the identity provider). Due to the fact that the reference is passed as a string, CDK can't add the dependency between the identity provider and the app client automatically. Therefore, `addDependency` must be called manually when both constructs are created in the same stack. The missing dependency was reported two times in the last weeks (issue #15850 and #15692). Because of that I would propose to add this behaviour 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/aws-cognito/README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/packages/@aws-cdk/aws-cognito/README.md b/packages/@aws-cdk/aws-cognito/README.md index 0c9c77ce42fdf..283fd4d6584ea 100644 --- a/packages/@aws-cdk/aws-cognito/README.md +++ b/packages/@aws-cdk/aws-cognito/README.md @@ -565,6 +565,21 @@ pool.addClient('app-client', { }); ``` +If the identity provider and the app client are created in the same stack, specify the dependency between both constructs to make sure that the identity provider already exists when the app client will be created. The app client cannot handle the dependency to the identity provider automatically because the client does not have access to the provider's construct. + +```ts +const provider = new cognito.UserPoolIdentityProviderAmazon(this, 'Amazon', { + // ... +}); +const client = pool.addClient('app-client', { + // ... + supportedIdentityProviders: [ + cognito.UserPoolClientIdentityProvider.AMAZON, + ], +} +client.node.addDependency(provider); +``` + In accordance with the OIDC open standard, Cognito user pool clients provide access tokens, ID tokens and refresh tokens. More information is available at [Using Tokens with User Pools](https://docs.aws.amazon.com/en_us/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html). The expiration time for these tokens can be configured as shown below. From 8cb0e97ea663e0447af77842e1a8efa8aee917eb Mon Sep 17 00:00:00 2001 From: Julian Michel Date: Tue, 10 Aug 2021 22:08:21 +0200 Subject: [PATCH 30/99] feat(cognito): add support for token revocation in UserPoolClient (#15317) Add support for token revocation in UserPoolClient. For new user pool clients, token revocation is enabled by default. Property `enableTokenRevocation` introduces the possibility to enable token revocation for existing user pool clients. Closes #15126 ---- *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-cognito/README.md | 11 +++++ .../aws-cognito/lib/user-pool-client.ts | 8 ++++ .../aws-cognito/test/user-pool-client.test.ts | 47 +++++++++++++++++++ 3 files changed, 66 insertions(+) diff --git a/packages/@aws-cdk/aws-cognito/README.md b/packages/@aws-cdk/aws-cognito/README.md index 283fd4d6584ea..bdb93fc24d566 100644 --- a/packages/@aws-cdk/aws-cognito/README.md +++ b/packages/@aws-cdk/aws-cognito/README.md @@ -618,6 +618,17 @@ pool.addClient('app-client', { }); ``` +[Token revocation](https://docs.aws.amazon.com/cognito/latest/developerguide/token-revocation.html +) can be configured to be able to revoke refresh tokens in app clients. By default, token revocation is enabled for new user pools. The property can be used to enable the token revocation in existing app clients or to change the default behavior. + +```ts +const pool = new cognito.UserPool(this, 'Pool'); +pool.addClient('app-client', { + // ... + enableTokenRevocation: true, +}); +``` + ### Resource Servers A resource server is a server for access-protected resources. It handles authenticated requests from an app that has an diff --git a/packages/@aws-cdk/aws-cognito/lib/user-pool-client.ts b/packages/@aws-cdk/aws-cognito/lib/user-pool-client.ts index d1f89f188c667..99ddaac75e595 100644 --- a/packages/@aws-cdk/aws-cognito/lib/user-pool-client.ts +++ b/packages/@aws-cdk/aws-cognito/lib/user-pool-client.ts @@ -293,6 +293,13 @@ export interface UserPoolClientOptions { * @default - all standard and custom attributes */ readonly writeAttributes?: ClientAttributes; + + /** + * Enable token revocation for this client. + * @see https://docs.aws.amazon.com/cognito/latest/developerguide/token-revocation.html#enable-token-revocation + * @default true for new user pool clients + */ + readonly enableTokenRevocation?: boolean; } /** @@ -381,6 +388,7 @@ export class UserPoolClient extends Resource implements IUserPoolClient { supportedIdentityProviders: this.configureIdentityProviders(props), readAttributes: props.readAttributes?.attributes(), writeAttributes: props.writeAttributes?.attributes(), + enableTokenRevocation: props.enableTokenRevocation, }); this.configureTokenValidity(resource, props); diff --git a/packages/@aws-cdk/aws-cognito/test/user-pool-client.test.ts b/packages/@aws-cdk/aws-cognito/test/user-pool-client.test.ts index dc8dde7779bbc..d6fc81f28c43c 100644 --- a/packages/@aws-cdk/aws-cognito/test/user-pool-client.test.ts +++ b/packages/@aws-cdk/aws-cognito/test/user-pool-client.test.ts @@ -541,6 +541,53 @@ describe('User Pool Client', () => { })).toThrow(/disableOAuth is set/); }); + test('EnableTokenRevocation is absent by default', () => { + // GIVEN + const stack = new Stack(); + const pool = new UserPool(stack, 'Pool'); + + // WHEN + pool.addClient('Client'); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Cognito::UserPoolClient', { + EnableTokenRevocation: Match.absentProperty(), + }); + }); + + test('enableTokenRevocation in addClient', () => { + // GIVEN + const stack = new Stack(); + const pool = new UserPool(stack, 'Pool'); + + // WHEN + pool.addClient('Client', { + enableTokenRevocation: true, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Cognito::UserPoolClient', { + EnableTokenRevocation: true, + }); + }); + + test('enableTokenRevocation in UserPoolClient', () => { + // GIVEN + const stack = new Stack(); + const pool = new UserPool(stack, 'Pool'); + + // WHEN + new UserPoolClient(stack, 'Client1', { + userPool: pool, + enableTokenRevocation: true, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Cognito::UserPoolClient', { + EnableTokenRevocation: true, + }); + }); + describe('token validity', () => { test('default', () => { // GIVEN From 898b05689899c85224e7b062ab2d65f112fe1bc0 Mon Sep 17 00:00:00 2001 From: AWS CDK Team Date: Tue, 10 Aug 2021 21:09:31 +0000 Subject: [PATCH 31/99] chore(release): 1.118.0 --- CHANGELOG.md | 14 ++++++++++++++ version.v1.json | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ef046c0c53529..83cca9c58cb2a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,20 @@ 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.118.0](https://github.com/aws/aws-cdk/compare/v1.117.0...v1.118.0) (2021-08-10) + + +### Features + +* **aws-elbv2:** ALB target group routing algorithms ([#15622](https://github.com/aws/aws-cdk/issues/15622)) ([6b32b2f](https://github.com/aws/aws-cdk/commit/6b32b2fb0c6ed2a21eb929e39930c6c9cf668dae)), closes [#15160](https://github.com/aws/aws-cdk/issues/15160) +* **cognito:** add support for token revocation in UserPoolClient ([#15317](https://github.com/aws/aws-cdk/issues/15317)) ([8cb0e97](https://github.com/aws/aws-cdk/commit/8cb0e97ea663e0447af77842e1a8efa8aee917eb)), closes [#15126](https://github.com/aws/aws-cdk/issues/15126) +* **pipelines:** add `synthCodeBuildDefaults` ([#15627](https://github.com/aws/aws-cdk/issues/15627)) ([04b8d40](https://github.com/aws/aws-cdk/commit/04b8d400b2653aff4f48709e8b420c6adb996ef5)) + + +### Bug Fixes + +* **ec2:** "clientVpnEndoint" => "clientVpnEndpoint" ([#14902](https://github.com/aws/aws-cdk/issues/14902)) ([c3b872a](https://github.com/aws/aws-cdk/commit/c3b872ad47ff3bdf2c841aa195b6fa6922c03769)), closes [#13810](https://github.com/aws/aws-cdk/issues/13810) + ## [1.117.0](https://github.com/aws/aws-cdk/compare/v1.116.0...v1.117.0) (2021-08-05) diff --git a/version.v1.json b/version.v1.json index 95b9ca9e3c2f0..5c8ead95001f8 100644 --- a/version.v1.json +++ b/version.v1.json @@ -1,3 +1,3 @@ { - "version": "1.117.0" + "version": "1.118.0" } From c42b3e8c83337afcb225103effcd94565261a073 Mon Sep 17 00:00:00 2001 From: Madeline Kusters Date: Tue, 10 Aug 2021 16:16:41 -0700 Subject: [PATCH 32/99] chore(pr checks): empty commit to trigger PR checks that are stuck From bf5882f8def0676bbfaee7c2ff4fab6bf39df281 Mon Sep 17 00:00:00 2001 From: akuntsch Date: Wed, 11 Aug 2021 11:08:20 +0200 Subject: [PATCH 33/99] fix(core): asset bundling fails for non-existent user (#15313) Currently, when not explicitly passing a user in BundlingOptions, `os.userInfo()` is called as a default fallback. Even though the user is only used and needed when using docker bundling, it is still called when using local bundling. This can be problematic e.g. when running cdk scripts inside a docker container where the user does not exist inside the container (see #15415). Fixes #15415. ---- *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/asset-staging.ts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/@aws-cdk/core/lib/asset-staging.ts b/packages/@aws-cdk/core/lib/asset-staging.ts index 89f7257ae522a..c948bc377c9a6 100644 --- a/packages/@aws-cdk/core/lib/asset-staging.ts +++ b/packages/@aws-cdk/core/lib/asset-staging.ts @@ -428,16 +428,6 @@ export class AssetStaging extends CoreConstruct { // Chmod the bundleDir to full access. fs.chmodSync(bundleDir, 0o777); - let user: string; - if (options.user) { - user = options.user; - } else { // Default to current user - const userInfo = os.userInfo(); - user = userInfo.uid !== -1 // uid is -1 on Windows - ? `${userInfo.uid}:${userInfo.gid}` - : '1000:1000'; - } - // Always mount input and output dir const volumes = [ { @@ -457,6 +447,16 @@ export class AssetStaging extends CoreConstruct { localBundling = options.local?.tryBundle(bundleDir, options); if (!localBundling) { + let user: string; + if (options.user) { + user = options.user; + } else { // Default to current user + const userInfo = os.userInfo(); + user = userInfo.uid !== -1 // uid is -1 on Windows + ? `${userInfo.uid}:${userInfo.gid}` + : '1000:1000'; + } + options.image.run({ command: options.command, user, From e0d61810ab78f7cab1af53bce82c60790a814f71 Mon Sep 17 00:00:00 2001 From: AWS CDK Automation <43080478+aws-cdk-automation@users.noreply.github.com> Date: Wed, 11 Aug 2021 13:23:25 +0300 Subject: [PATCH 34/99] feat(cfnspec): cloudformation spec v39.9.0 (#15987) Co-authored-by: AWS CDK Team Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- packages/@aws-cdk/cfnspec/CHANGELOG.md | 38 +++++ packages/@aws-cdk/cfnspec/cfn.version | 2 +- ...0_CloudFormationResourceSpecification.json | 161 +++++++++++++++++- 3 files changed, 197 insertions(+), 4 deletions(-) diff --git a/packages/@aws-cdk/cfnspec/CHANGELOG.md b/packages/@aws-cdk/cfnspec/CHANGELOG.md index cbadd0a7eda90..716c917940793 100644 --- a/packages/@aws-cdk/cfnspec/CHANGELOG.md +++ b/packages/@aws-cdk/cfnspec/CHANGELOG.md @@ -1,3 +1,41 @@ +# CloudFormation Resource Specification v39.9.0 + +## New Resource Types + +* AWS::Athena::PreparedStatement + +## Attribute Changes + +* AWS::ApiGateway::Resource ResourceId (__added__) +* AWS::Athena::WorkGroup WorkGroupConfigurationUpdates.EngineVersion.EffectiveEngineVersion (__added__) +* AWS::MWAA::Environment LoggingConfiguration.SchedulerLogs.CloudWatchLogGroupArn (__added__) +* AWS::MWAA::Environment LoggingConfiguration.TaskLogs.CloudWatchLogGroupArn (__added__) +* AWS::MWAA::Environment LoggingConfiguration.WebserverLogs.CloudWatchLogGroupArn (__added__) +* AWS::MWAA::Environment LoggingConfiguration.WorkerLogs.CloudWatchLogGroupArn (__added__) + +## Property Changes + +* AWS::AppSync::GraphQLApi LambdaAuthorizerConfig (__added__) +* AWS::LookoutEquipment::InferenceScheduler ModelName.UpdateType (__changed__) + * Old: Mutable + * New: Immutable +* AWS::LookoutEquipment::InferenceScheduler ServerSideKmsKeyId.UpdateType (__changed__) + * Old: Mutable + * New: Immutable +* AWS::S3::AccessPoint Name (__added__) +* AWS::Synthetics::Canary VisualReference (__added__) + +## Property Type Changes + +* AWS::AppSync::GraphQLApi.LambdaAuthorizerConfig (__added__) +* AWS::SageMaker::Model.RepositoryAuthConfig (__added__) +* AWS::Synthetics::Canary.BaseScreenshot (__added__) +* AWS::Synthetics::Canary.VisualReference (__added__) +* AWS::AppSync::GraphQLApi.AdditionalAuthenticationProvider LambdaAuthorizerConfig (__added__) +* AWS::IoTSiteWise::AssetModel.TumblingWindow Offset (__added__) +* AWS::SageMaker::Model.ImageConfig RepositoryAuthConfig (__added__) + + # CloudFormation Resource Specification v39.8.0 ## New Resource Types diff --git a/packages/@aws-cdk/cfnspec/cfn.version b/packages/@aws-cdk/cfnspec/cfn.version index 212ba4596ef15..ff93cfe146d81 100644 --- a/packages/@aws-cdk/cfnspec/cfn.version +++ b/packages/@aws-cdk/cfnspec/cfn.version @@ -1 +1 @@ -39.8.0 +39.9.0 diff --git a/packages/@aws-cdk/cfnspec/spec-source/000_CloudFormationResourceSpecification.json b/packages/@aws-cdk/cfnspec/spec-source/000_CloudFormationResourceSpecification.json index 5e6a900098e55..2d71e22ab1083 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/000_CloudFormationResourceSpecification.json +++ b/packages/@aws-cdk/cfnspec/spec-source/000_CloudFormationResourceSpecification.json @@ -7114,6 +7114,12 @@ "Required": true, "UpdateType": "Mutable" }, + "LambdaAuthorizerConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appsync-graphqlapi-additionalauthenticationprovider.html#cfn-appsync-graphqlapi-additionalauthenticationprovider-lambdaauthorizerconfig", + "Required": false, + "Type": "LambdaAuthorizerConfig", + "UpdateType": "Mutable" + }, "OpenIDConnectConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appsync-graphqlapi-additionalauthenticationprovider.html#cfn-appsync-graphqlapi-additionalauthenticationprovider-openidconnectconfig", "Required": false, @@ -7158,6 +7164,29 @@ } } }, + "AWS::AppSync::GraphQLApi.LambdaAuthorizerConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appsync-graphqlapi-lambdaauthorizerconfig.html", + "Properties": { + "AuthorizerResultTtlInSeconds": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appsync-graphqlapi-lambdaauthorizerconfig.html#cfn-appsync-graphqlapi-lambdaauthorizerconfig-authorizerresultttlinseconds", + "PrimitiveType": "Double", + "Required": false, + "UpdateType": "Mutable" + }, + "AuthorizerUri": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appsync-graphqlapi-lambdaauthorizerconfig.html#cfn-appsync-graphqlapi-lambdaauthorizerconfig-authorizeruri", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "IdentityValidationExpression": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appsync-graphqlapi-lambdaauthorizerconfig.html#cfn-appsync-graphqlapi-lambdaauthorizerconfig-identityvalidationexpression", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, "AWS::AppSync::GraphQLApi.LogConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appsync-graphqlapi-logconfig.html", "Properties": { @@ -35861,6 +35890,12 @@ "PrimitiveType": "String", "Required": true, "UpdateType": "Mutable" + }, + "Offset": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotsitewise-assetmodel-tumblingwindow.html#cfn-iotsitewise-assetmodel-tumblingwindow-offset", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" } } }, @@ -57003,6 +57038,12 @@ "PrimitiveType": "String", "Required": true, "UpdateType": "Immutable" + }, + "RepositoryAuthConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-model-containerdefinition-imageconfig.html#cfn-sagemaker-model-containerdefinition-imageconfig-repositoryauthconfig", + "Required": false, + "Type": "RepositoryAuthConfig", + "UpdateType": "Immutable" } } }, @@ -57028,6 +57069,17 @@ } } }, + "AWS::SageMaker::Model.RepositoryAuthConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-model-containerdefinition-imageconfig-repositoryauthconfig.html", + "Properties": { + "RepositoryCredentialsProviderArn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-model-containerdefinition-imageconfig-repositoryauthconfig.html#cfn-sagemaker-model-containerdefinition-imageconfig-repositoryauthconfig-repositorycredentialsproviderarn", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + } + } + }, "AWS::SageMaker::Model.VpcConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-model-vpcconfig.html", "Properties": { @@ -59046,6 +59098,24 @@ } } }, + "AWS::Synthetics::Canary.BaseScreenshot": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-synthetics-canary-basescreenshot.html", + "Properties": { + "IgnoreCoordinates": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-synthetics-canary-basescreenshot.html#cfn-synthetics-canary-basescreenshot-ignorecoordinates", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "ScreenshotName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-synthetics-canary-basescreenshot.html#cfn-synthetics-canary-basescreenshot-screenshotname", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } + }, "AWS::Synthetics::Canary.Code": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-synthetics-canary-code.html", "Properties": { @@ -59153,6 +59223,24 @@ } } }, + "AWS::Synthetics::Canary.VisualReference": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-synthetics-canary-visualreference.html", + "Properties": { + "BaseCanaryRunId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-synthetics-canary-visualreference.html#cfn-synthetics-canary-visualreference-basecanaryrunid", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "BaseScreenshots": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-synthetics-canary-visualreference.html#cfn-synthetics-canary-visualreference-basescreenshots", + "ItemType": "BaseScreenshot", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + } + } + }, "AWS::Transfer::Server.EndpointDetails": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-transfer-server-endpointdetails.html", "Properties": { @@ -61525,7 +61613,7 @@ } } }, - "ResourceSpecificationVersion": "39.8.0", + "ResourceSpecificationVersion": "39.9.0", "ResourceTypes": { "AWS::ACMPCA::Certificate": { "Attributes": { @@ -62750,6 +62838,11 @@ } }, "AWS::ApiGateway::Resource": { + "Attributes": { + "ResourceId": { + "PrimitiveType": "String" + } + }, "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-resource.html", "Properties": { "ParentId": { @@ -65302,6 +65395,12 @@ "Required": true, "UpdateType": "Mutable" }, + "LambdaAuthorizerConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appsync-graphqlapi.html#cfn-appsync-graphqlapi-lambdaauthorizerconfig", + "Required": false, + "Type": "LambdaAuthorizerConfig", + "UpdateType": "Mutable" + }, "LogConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appsync-graphqlapi.html#cfn-appsync-graphqlapi-logconfig", "Required": false, @@ -65704,6 +65803,35 @@ } } }, + "AWS::Athena::PreparedStatement": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-athena-preparedstatement.html", + "Properties": { + "Description": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-athena-preparedstatement.html#cfn-athena-preparedstatement-description", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "QueryStatement": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-athena-preparedstatement.html#cfn-athena-preparedstatement-querystatement", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "StatementName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-athena-preparedstatement.html#cfn-athena-preparedstatement-statementname", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "WorkGroup": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-athena-preparedstatement.html#cfn-athena-preparedstatement-workgroup", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + } + } + }, "AWS::Athena::WorkGroup": { "Attributes": { "CreationTime": { @@ -65711,6 +65839,9 @@ }, "WorkGroupConfiguration.EngineVersion.EffectiveEngineVersion": { "PrimitiveType": "String" + }, + "WorkGroupConfigurationUpdates.EngineVersion.EffectiveEngineVersion": { + "PrimitiveType": "String" } }, "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-athena-workgroup.html", @@ -86872,7 +87003,7 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lookoutequipment-inferencescheduler.html#cfn-lookoutequipment-inferencescheduler-modelname", "PrimitiveType": "String", "Required": true, - "UpdateType": "Mutable" + "UpdateType": "Immutable" }, "RoleArn": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lookoutequipment-inferencescheduler.html#cfn-lookoutequipment-inferencescheduler-rolearn", @@ -86884,7 +87015,7 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lookoutequipment-inferencescheduler.html#cfn-lookoutequipment-inferencescheduler-serversidekmskeyid", "PrimitiveType": "String", "Required": false, - "UpdateType": "Mutable" + "UpdateType": "Immutable" }, "Tags": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lookoutequipment-inferencescheduler.html#cfn-lookoutequipment-inferencescheduler-tags", @@ -87072,6 +87203,18 @@ "LoggingConfiguration.DagProcessingLogs.CloudWatchLogGroupArn": { "PrimitiveType": "String" }, + "LoggingConfiguration.SchedulerLogs.CloudWatchLogGroupArn": { + "PrimitiveType": "String" + }, + "LoggingConfiguration.TaskLogs.CloudWatchLogGroupArn": { + "PrimitiveType": "String" + }, + "LoggingConfiguration.WebserverLogs.CloudWatchLogGroupArn": { + "PrimitiveType": "String" + }, + "LoggingConfiguration.WorkerLogs.CloudWatchLogGroupArn": { + "PrimitiveType": "String" + }, "WebserverUrl": { "PrimitiveType": "String" } @@ -94306,6 +94449,12 @@ "Required": true, "UpdateType": "Immutable" }, + "Name": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-s3-accesspoint.html#cfn-s3-accesspoint-name", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, "Policy": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-s3-accesspoint.html#cfn-s3-accesspoint-policy", "PrimitiveType": "Json", @@ -98539,6 +98688,12 @@ "Required": false, "Type": "VPCConfig", "UpdateType": "Mutable" + }, + "VisualReference": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-synthetics-canary.html#cfn-synthetics-canary-visualreference", + "Required": false, + "Type": "VisualReference", + "UpdateType": "Mutable" } } }, From e4f288931ab566d0c3a09c9b0c6f4528f0748c50 Mon Sep 17 00:00:00 2001 From: max-allan-surevine Date: Wed, 11 Aug 2021 12:04:48 +0100 Subject: [PATCH 35/99] docs: improve documentation on the use of "env" with context lookups (#15983) This requires too much documentation to explain fully here in an error message. Bottom line is : You must set an env. So lets tell people that and not suggest they can sidestep creating env by setting CLI environment variables. Whatever you put in the env is up to the user (whether process.env.AWS_DEFAULT_REGION or process.env.CDK_DEFAULT_REGION or a fixed value, doesn't matter as long as you create an env). Lets give people a link to understand "env" instead. ---- *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/context-provider.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk/core/lib/context-provider.ts b/packages/@aws-cdk/core/lib/context-provider.ts index 1eb210623558f..526414a9cf790 100644 --- a/packages/@aws-cdk/core/lib/context-provider.ts +++ b/packages/@aws-cdk/core/lib/context-provider.ts @@ -84,9 +84,9 @@ export class ContextProvider { if (Token.isUnresolved(stack.account) || Token.isUnresolved(stack.region)) { throw new Error(`Cannot retrieve value from context provider ${options.provider} since account/region ` + - 'are not specified at the stack level. Either configure "env" with explicit account and region when ' + - 'you define your stack, or use the environment variables "CDK_DEFAULT_ACCOUNT" and "CDK_DEFAULT_REGION" ' + - 'to inherit environment information from the CLI (not recommended for production stacks)'); + 'are not specified at the stack level. Configure "env" with an account and region when ' + + 'you define your stack.' + + 'See https://docs.aws.amazon.com/cdk/latest/guide/environments.html for more details.'); } const { key, props } = this.getKey(scope, options); From 277b25033060118cd9e0407cb2aaae81ffd4bfa4 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Wed, 11 Aug 2021 13:43:55 +0200 Subject: [PATCH 36/99] docs(codepipeline): explain how cross-account CodeCommit works (#15988) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../lib/codecommit/source-action.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/@aws-cdk/aws-codepipeline-actions/lib/codecommit/source-action.ts b/packages/@aws-cdk/aws-codepipeline-actions/lib/codecommit/source-action.ts index 8708410dfff18..136bf9bba9dc5 100644 --- a/packages/@aws-cdk/aws-codepipeline-actions/lib/codecommit/source-action.ts +++ b/packages/@aws-cdk/aws-codepipeline-actions/lib/codecommit/source-action.ts @@ -106,6 +106,15 @@ export interface CodeCommitSourceActionProps extends codepipeline.CommonAwsActio /** * CodePipeline Source that is provided by an AWS CodeCommit repository. + * + * If the CodeCommit repository is in a different account, you must use + * `CodeCommitTrigger.EVENTS` to trigger the pipeline. + * + * (That is because the Pipeline structure normally only has a `RepositoryName` + * field, and that is not enough for the pipeline to locate the repository's + * source account. However, if the pipeline is triggered via an EventBridge + * event, the event itself has the full repository ARN in there, allowing the + * pipeline to locate the repository). */ export class CodeCommitSourceAction extends Action { /** From 9e4f673cbad3b20c3b99a6d8616307b805e70f18 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Wed, 11 Aug 2021 14:24:39 +0200 Subject: [PATCH 37/99] chore(scripts): safety script incorrectly checks `peerDependencies` (#15989) Our script that checks that Yarn doesn't mess up incorrectly checks `yarn.lock` for `peerDependencies`. Given that `peerDependencies` aren't installed directly, this makes no sense. In fact, the build currently fails with: ``` Dependency jest@>=26.6.3 from @aws-cdk/assert not present in yarn.lock. ``` ---- *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 | 3 +-- yarn.lock | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/scripts/check-yarn-lock.js b/scripts/check-yarn-lock.js index d13e4e08cf64f..8fd59b5a60bc8 100755 --- a/scripts/check-yarn-lock.js +++ b/scripts/check-yarn-lock.js @@ -40,13 +40,12 @@ async function main() { const dependencyId = `${dependencyName}@${dependencyVersion}`; const isLocalDependency = dependencyVersion === '0.0.0' || dependencyVersion === '^0.0.0'; if (!isLocalDependency && !yarnPackages.has(dependencyId)) { - throw new Error(`ERROR! Dependency ${dependencyId} from ${package.name} not present in yarn.lock. Please run yarn update and try again!`); + throw new Error(`ERROR! Dependency ${dependencyId} from ${package.name} not present in yarn.lock. Please run 'yarn install' and try again!`); } } projects.forEach((p) => { Object.entries(p.devDependencies || {}).forEach(([depName, depVersion]) => errorIfNotInYarnLock(p, depName, depVersion)); - Object.entries(p.peerDependencies || {}).forEach(([depName, depVersion]) => errorIfNotInYarnLock(p, depName, depVersion)); Object.entries(p.dependencies || {}).forEach(([depName, depVersion]) => errorIfNotInYarnLock(p, depName, depVersion)); }); } diff --git a/yarn.lock b/yarn.lock index 7e67161d74f5e..66bb214514901 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1628,7 +1628,7 @@ dependencies: "@types/istanbul-lib-report" "*" -"@types/jest@^26.0.24": +"@types/jest@^26.0.22", "@types/jest@^26.0.24": version "26.0.24" resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.24.tgz#943d11976b16739185913a1936e0de0c4a7d595a" integrity sha512-E/X5Vib8BWqZNRlDxj9vYXhsDwPYbPINqKF9BsnSoon4RQ0D9moEuLD8txgyypFLH7J4+Lho9Nr/c8H0Fi+17w== From e17c627c3bcf3404ad844c570dc926eb25584cbf Mon Sep 17 00:00:00 2001 From: Nick Lynch Date: Wed, 11 Aug 2021 15:37:24 +0100 Subject: [PATCH 38/99] test(aws-lambda-python): remove hard-coded references to @aws-cdk/aws-lambda (#15994) Remove the hard coded reference to the @aws-cdk/aws-lambda packages from the test, which should fix the issue that prevent building the package as an alpha module in v2. This was previously done in #15921, but I missed these entries in the tests. related #15586 ---- *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-python/test/function.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.test.ts b/packages/@aws-cdk/aws-lambda-python/test/function.test.ts index 0eda2a419e97c..c0636329b2ecc 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.test.ts +++ b/packages/@aws-cdk/aws-lambda-python/test/function.test.ts @@ -48,7 +48,7 @@ test('PythonFunction with defaults', () => { }); expect(bundle).toHaveBeenCalledWith(expect.objectContaining({ - entry: expect.stringMatching(/@aws-cdk\/aws-lambda-python\/test\/lambda-handler$/), + entry: expect.stringMatching(/aws-lambda-python\/test\/lambda-handler$/), outputPathSuffix: '.', })); @@ -65,7 +65,7 @@ test('PythonFunction with index in a subdirectory', () => { }); expect(bundle).toHaveBeenCalledWith(expect.objectContaining({ - entry: expect.stringMatching(/@aws-cdk\/aws-lambda-python\/test\/lambda-handler-sub$/), + entry: expect.stringMatching(/aws-lambda-python\/test\/lambda-handler-sub$/), outputPathSuffix: '.', })); @@ -142,4 +142,4 @@ test('allows specifying hash type', () => { S3Key: 'MY_CUSTOM_HASH', }, }); -}); \ No newline at end of file +}); From 2b37e29e824dad799f2794bf4f2f1185cd92928d Mon Sep 17 00:00:00 2001 From: Brian Hubbell <655067+brianhubbell@users.noreply.github.com> Date: Wed, 11 Aug 2021 14:35:51 -0700 Subject: [PATCH 39/99] chore(aws-apigatewayv2): docs spelling correction (#15962) Spelling fixes. ---- *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-apigatewayv2/lib/http/api.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/aws-apigatewayv2/lib/http/api.ts b/packages/@aws-cdk/aws-apigatewayv2/lib/http/api.ts index e4b6ce929eb2a..094c0131872d8 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/lib/http/api.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/lib/http/api.ts @@ -84,7 +84,7 @@ export interface IHttpApi extends IApi { */ export interface HttpApiProps { /** - * Name for the HTTP API resoruce + * Name for the HTTP API resource * @default - id of the HttpApi construct. */ readonly apiName?: string; @@ -209,7 +209,7 @@ export interface CorsPreflightOptions { } /** - * Options for the Route with Integration resoruce + * Options for the Route with Integration resource */ export interface AddRoutesOptions extends BatchHttpRouteOptions { /** From 9ba8387892cb789deb27bacbd7f2a495988304dd Mon Sep 17 00:00:00 2001 From: Ayato Tokubi Date: Wed, 11 Aug 2021 22:14:52 +0000 Subject: [PATCH 40/99] chore(apigatewayv2): fix typo in README (#15950) This PR fix typo in README of `aws-apigatewayv2`. I made PR #15227 and was pointed out typo. According to the PR, `webSocketStage` is correct. ---- *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-apigatewayv2/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-apigatewayv2/README.md b/packages/@aws-cdk/aws-apigatewayv2/README.md index 944e328fc8532..c5dc2318b2d53 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/README.md +++ b/packages/@aws-cdk/aws-apigatewayv2/README.md @@ -316,7 +316,7 @@ To retrieve a websocket URL and a callback URL: ```ts const webSocketURL = webSocketStage.url; // wss://${this.api.apiId}.execute-api.${s.region}.${s.urlSuffix}/${urlPath} -const callbackURL = webSocketURL.callbackUrl; +const callbackURL = webSocketStage.callbackUrl; // https://${this.api.apiId}.execute-api.${s.region}.${s.urlSuffix}/${urlPath} ``` From 2e65e72f6b813bad61daa9eba56af34baae908d2 Mon Sep 17 00:00:00 2001 From: Madeline Kusters <80541297+madeline-k@users.noreply.github.com> Date: Wed, 11 Aug 2021 16:23:38 -0700 Subject: [PATCH 41/99] chore(ec2): explicit feature flags to produce a consistent template during tests (#16008) In v1, the default value of the `@aws-cdk/core:newStyleStackSynthesis` flag is `false`. As a consequence, `Template.fromStack()` generates, by default, a template without the rule and parameter related to bootstrap versions. In v2, the default value of this flag is `true`. So this test fails in the v2 branch. By explicitly setting the flag to `false`, we ensure that the tests passes on both v1 and v2, regardless of the default values. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../aws-ec2/test/client-vpn-authorization-rule.test.ts | 9 +++++++-- packages/@aws-cdk/aws-ec2/test/client-vpn-route.test.ts | 9 +++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/packages/@aws-cdk/aws-ec2/test/client-vpn-authorization-rule.test.ts b/packages/@aws-cdk/aws-ec2/test/client-vpn-authorization-rule.test.ts index 6c8911d90a06d..5390eb43adb85 100644 --- a/packages/@aws-cdk/aws-ec2/test/client-vpn-authorization-rule.test.ts +++ b/packages/@aws-cdk/aws-ec2/test/client-vpn-authorization-rule.test.ts @@ -1,11 +1,16 @@ import '@aws-cdk/assert-internal/jest'; -import { Stack } from '@aws-cdk/core'; +import { App, Stack } from '@aws-cdk/core'; import { Connections, IClientVpnEndpoint } from '../lib'; import { ClientVpnAuthorizationRule } from '../lib/client-vpn-authorization-rule'; let stack: Stack; beforeEach(() => { - stack = new Stack(); + const app = new App({ + context: { + '@aws-cdk/core:newStyleStackSynthesis': false, + }, + }); + stack = new Stack(app); }); describe('ClientVpnAuthorizationRule constructor', () => { diff --git a/packages/@aws-cdk/aws-ec2/test/client-vpn-route.test.ts b/packages/@aws-cdk/aws-ec2/test/client-vpn-route.test.ts index 42f094ab4bb9e..fde37f49335ae 100644 --- a/packages/@aws-cdk/aws-ec2/test/client-vpn-route.test.ts +++ b/packages/@aws-cdk/aws-ec2/test/client-vpn-route.test.ts @@ -1,6 +1,6 @@ import '@aws-cdk/assert-internal/jest'; import { SamlMetadataDocument, SamlProvider } from '@aws-cdk/aws-iam'; -import { Stack } from '@aws-cdk/core'; +import { App, Stack } from '@aws-cdk/core'; import * as ec2 from '../lib'; import { ClientVpnRoute, @@ -11,7 +11,12 @@ import { let stack: Stack; let vpc: ec2.IVpc; beforeEach(() => { - stack = new Stack(); + const app = new App({ + context: { + '@aws-cdk/core:newStyleStackSynthesis': false, + }, + }); + stack = new Stack(app); vpc = new ec2.Vpc(stack, 'Vpc'); }); From 111a3c514b243ff18ee6e50a3c039b4190e557ef Mon Sep 17 00:00:00 2001 From: Ben Limmer Date: Thu, 12 Aug 2021 03:16:33 -0600 Subject: [PATCH 42/99] chore(pipelines): improve CodeBuildStep.project error message (#15977) This PR improves the error message when trying to access a CodeBuildStep's `project` property before the pipeline is built. It now matches the verbiage used in the CodePipeline `synthProject` getter: https://github.com/aws/aws-cdk/blob/965d27ffb106763c7562d0b0a333827368ea434e/packages/%40aws-cdk/pipelines/lib/codepipeline/codepipeline.ts#L292-L297 ---- *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/codepipeline/codebuild-step.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/pipelines/lib/codepipeline/codebuild-step.ts b/packages/@aws-cdk/pipelines/lib/codepipeline/codebuild-step.ts index 1454d34a167c3..3047b43c5c755 100644 --- a/packages/@aws-cdk/pipelines/lib/codepipeline/codebuild-step.ts +++ b/packages/@aws-cdk/pipelines/lib/codepipeline/codebuild-step.ts @@ -166,7 +166,7 @@ export class CodeBuildStep extends ShellStep { */ public get project(): codebuild.IProject { if (!this._project) { - throw new Error('Project becomes available after the pipeline has been built'); + throw new Error('Call pipeline.buildPipeline() before reading this property'); } return this._project; } From 8b70badebccc1be93266533df43e39ac0e3e52a8 Mon Sep 17 00:00:00 2001 From: Niranjan Jayakar Date: Thu, 12 Aug 2021 12:46:34 +0100 Subject: [PATCH 43/99] fix(assert): matchTemplate with superset fails when additional parameters are present (#16015) When `matchTemplate()` is used with the `SUPERSET` match style, it does not honour new Parameters and Outputs in the CloudFormation template. The fix is to only fail only when expected Parameters and Outputs are missing or modified. fixes #15946 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../lib/assertions/match-template.ts | 5 +- .../assert-internal/test/cloud-artifact.ts | 29 ++++ .../assert-internal/test/have-output.test.ts | 26 +--- .../test/have-resource.test.ts | 48 ++---- .../test/match-template.test.ts | 144 ++++++++++++++++++ 5 files changed, 188 insertions(+), 64 deletions(-) create mode 100644 packages/@aws-cdk/assert-internal/test/cloud-artifact.ts create mode 100644 packages/@aws-cdk/assert-internal/test/match-template.test.ts diff --git a/packages/@aws-cdk/assert-internal/lib/assertions/match-template.ts b/packages/@aws-cdk/assert-internal/lib/assertions/match-template.ts index e668466d12416..b3787446f1aef 100644 --- a/packages/@aws-cdk/assert-internal/lib/assertions/match-template.ts +++ b/packages/@aws-cdk/assert-internal/lib/assertions/match-template.ts @@ -78,16 +78,15 @@ class StackMatchesTemplateAssertion extends Assertion { } for (const change of Object.values(diff.parameters.changes)) { - if (change.isAddition) { return false; } + if (!change.isAddition) { return false; } } for (const change of Object.values(diff.outputs.changes)) { - if (change.isAddition || change.isUpdate) { return false; } + if (!change.isAddition) { return false; } } return true; } - throw new Error(`Unsupported match style: ${this.matchStyle}`); } public get description(): string { diff --git a/packages/@aws-cdk/assert-internal/test/cloud-artifact.ts b/packages/@aws-cdk/assert-internal/test/cloud-artifact.ts new file mode 100644 index 0000000000000..3cdacf6af5134 --- /dev/null +++ b/packages/@aws-cdk/assert-internal/test/cloud-artifact.ts @@ -0,0 +1,29 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import * as cxschema from '@aws-cdk/cloud-assembly-schema'; +import * as cxapi from '@aws-cdk/cx-api'; + +export function mkStack(template: any): cxapi.CloudFormationStackArtifact { + const assembly = new cxapi.CloudAssemblyBuilder(); + assembly.addArtifact('test', { + type: cxschema.ArtifactType.AWS_CLOUDFORMATION_STACK, + environment: cxapi.EnvironmentUtils.format('123456789012', 'bermuda-triangle-1'), + properties: { + templateFile: 'template.json', + }, + }); + + fs.writeFileSync(path.join(assembly.outdir, 'template.json'), JSON.stringify(template)); + return assembly.buildAssembly().getStackByName('test'); +} + +export function mkResource(props: any): cxapi.CloudFormationStackArtifact { + return mkStack({ + Resources: { + SomeResource: { + Type: 'Some::Resource', + Properties: props, + }, + }, + }); +} \ No newline at end of file diff --git a/packages/@aws-cdk/assert-internal/test/have-output.test.ts b/packages/@aws-cdk/assert-internal/test/have-output.test.ts index a92664f4875a5..ffe6212588748 100644 --- a/packages/@aws-cdk/assert-internal/test/have-output.test.ts +++ b/packages/@aws-cdk/assert-internal/test/have-output.test.ts @@ -1,7 +1,6 @@ -import { unlink, writeFileSync } from 'fs'; -import { join } from 'path'; -import * as cxschema from '@aws-cdk/cloud-assembly-schema'; +import { unlink } from 'fs'; import * as cxapi from '@aws-cdk/cx-api'; +import { mkStack } from './cloud-artifact'; import '../jest'; let templateFilePath: string; @@ -180,23 +179,4 @@ afterEach(done => { } else { done(); } -}); - -function mkStack(template: any): cxapi.CloudFormationStackArtifact { - const templateFileName = 'test-have-output-template.json'; - const stackName = 'test-have-output'; - const assembly = new cxapi.CloudAssemblyBuilder(); - - assembly.addArtifact(stackName, { - type: cxschema.ArtifactType.AWS_CLOUDFORMATION_STACK, - environment: cxapi.EnvironmentUtils.format('123456789012', 'bermuda-triangle-1'), - properties: { - templateFile: templateFileName, - }, - }); - - templateFilePath = join(assembly.outdir, templateFileName); - writeFileSync(templateFilePath, JSON.stringify(template)); - - return assembly.buildAssembly().getStackByName(stackName); -} +}); \ No newline at end of file diff --git a/packages/@aws-cdk/assert-internal/test/have-resource.test.ts b/packages/@aws-cdk/assert-internal/test/have-resource.test.ts index 7772e5f7d193f..324e221114df0 100644 --- a/packages/@aws-cdk/assert-internal/test/have-resource.test.ts +++ b/packages/@aws-cdk/assert-internal/test/have-resource.test.ts @@ -1,8 +1,5 @@ -import { writeFileSync } from 'fs'; -import { join } from 'path'; -import * as cxschema from '@aws-cdk/cloud-assembly-schema'; -import * as cxapi from '@aws-cdk/cx-api'; import { ABSENT, arrayWith, exactValue, expect as cdkExpect, haveResource, haveResourceLike, Capture, anything } from '../lib/index'; +import { mkResource, mkStack } from './cloud-artifact'; test('support resource with no properties', () => { const synthStack = mkStack({ @@ -86,7 +83,7 @@ test('haveResource allows to opt in value extension', () => { describe('property absence', () => { test('pass on absence', () => { - const synthStack = mkSomeResource({ + const synthStack = mkResource({ Prop: 'somevalue', }); @@ -96,7 +93,7 @@ describe('property absence', () => { }); test('fail on presence', () => { - const synthStack = mkSomeResource({ + const synthStack = mkResource({ PropA: 3, }); @@ -108,7 +105,7 @@ describe('property absence', () => { }); test('pass on deep absence', () => { - const synthStack = mkSomeResource({ + const synthStack = mkResource({ Deep: { Prop: 'somevalue', }, @@ -123,7 +120,7 @@ describe('property absence', () => { }); test('fail on deep presence', () => { - const synthStack = mkSomeResource({ + const synthStack = mkResource({ Deep: { Prop: 'somevalue', }, @@ -139,7 +136,7 @@ describe('property absence', () => { }); test('can use matcher to test for list element', () => { - const synthStack = mkSomeResource({ + const synthStack = mkResource({ List: [ { Prop: 'distraction' }, { Prop: 'goal' }, @@ -160,7 +157,7 @@ describe('property absence', () => { }); test('arrayContaining must match all elements in any order', () => { - const synthStack = mkSomeResource({ + const synthStack = mkResource({ List: ['a', 'b'], }); @@ -178,7 +175,7 @@ describe('property absence', () => { }); test('exactValue escapes from deep fuzzy matching', () => { - const synthStack = mkSomeResource({ + const synthStack = mkResource({ Deep: { PropA: 'A', PropB: 'B', @@ -216,7 +213,7 @@ describe('property absence', () => { * it. */ test('objectContainingDeep has deep effect through lists', () => { - const synthStack = mkSomeResource({ + const synthStack = mkResource({ List: [ { PropA: 'A', @@ -240,7 +237,7 @@ describe('property absence', () => { }); test('test capturing', () => { - const synthStack = mkSomeResource({ + const synthStack = mkResource({ Prop: 'somevalue', }); @@ -252,28 +249,3 @@ describe('property absence', () => { expect(propValue.capturedValue).toEqual('somevalue'); }); }); - -function mkStack(template: any): cxapi.CloudFormationStackArtifact { - const assembly = new cxapi.CloudAssemblyBuilder(); - assembly.addArtifact('test', { - type: cxschema.ArtifactType.AWS_CLOUDFORMATION_STACK, - environment: cxapi.EnvironmentUtils.format('123456789', 'us-west-2'), - properties: { - templateFile: 'template.json', - }, - }); - - writeFileSync(join(assembly.outdir, 'template.json'), JSON.stringify(template)); - return assembly.buildAssembly().getStackByName('test'); -} - -function mkSomeResource(props: any): cxapi.CloudFormationStackArtifact { - return mkStack({ - Resources: { - SomeResource: { - Type: 'Some::Resource', - Properties: props, - }, - }, - }); -} \ No newline at end of file diff --git a/packages/@aws-cdk/assert-internal/test/match-template.test.ts b/packages/@aws-cdk/assert-internal/test/match-template.test.ts new file mode 100644 index 0000000000000..dc3a4bfe6fb26 --- /dev/null +++ b/packages/@aws-cdk/assert-internal/test/match-template.test.ts @@ -0,0 +1,144 @@ +import { MatchStyle } from '../lib'; +import { mkStack } from './cloud-artifact'; +import '../jest'; + +describe('matchTemplate', () => { + describe('exact match', () => { + test('match on resources', () => { + const stack = mkStack({ + Resources: { + FooResource: { Type: 'Foo::Bar' }, + }, + }); + + expect(stack).toMatchTemplate({ + Resources: { + FooResource: { Type: 'Foo::Bar' }, + }, + }, MatchStyle.EXACT); + + expect(stack).not.toMatchTemplate({ + Resources: { + FooResource: { Type: 'Foo::Baz' }, + }, + }, MatchStyle.EXACT); + }); + + test('match on parameters', () => { + const stack = mkStack({ + Parameters: { + FooParameter: { Type: 'String' }, + }, + }); + expect(stack).toMatchTemplate({ + Parameters: { + FooParameter: { Type: 'String' }, + }, + }, MatchStyle.EXACT); + + expect(stack).not.toMatchTemplate({ + Parameters: { + BarParameter: { Type: 'String' }, + }, + }, MatchStyle.EXACT); + }); + + test('match on outputs', () => { + const stack = mkStack({ + Outputs: { + FooOutput: { Value: 'Foo' }, + }, + }); + + expect(stack).toMatchTemplate({ + Outputs: { + FooOutput: { Value: 'Foo' }, + }, + }, MatchStyle.EXACT); + + expect(stack).not.toMatchTemplate({ + Outputs: { + BarOutput: { Value: 'Bar' }, + }, + }, MatchStyle.EXACT); + + expect(stack).not.toMatchTemplate({ + Outputs: { + FooOutput: { Value: 'Bar' }, + }, + }, MatchStyle.EXACT); + }); + }); + + describe('superset match', () => { + test('match on resources', () => { + const stack = mkStack({ + Resources: { + FooResource: { + Type: 'Foo::Bar', + }, + BazResource: { + Type: 'Foo::Baz', + }, + }, + }); + expect(stack).toMatchTemplate({ + Resources: { + FooResource: { + Type: 'Foo::Bar', + }, + }, + }, MatchStyle.SUPERSET); + }); + + test('match on parameters', () => { + const stack = mkStack({ + Parameters: { + FooParameter: { Type: 'String' }, + BarParameter: { Type: 'String' }, + }, + }); + expect(stack).toMatchTemplate({ + Parameters: { + FooParameter: { Type: 'String' }, + }, + }, MatchStyle.SUPERSET); + + expect(stack).not.toMatchTemplate({ + Parameters: { + FooParameter: { Type: 'String' }, + BarParameter: { Type: 'Number' }, + }, + }, MatchStyle.SUPERSET); + }); + + test('match on outputs', () => { + const stack = mkStack({ + Outputs: { + FooOutput: { Value: 'Foo' }, + BarOutput: { Value: 'Bar' }, + }, + }); + + expect(stack).toMatchTemplate({ + Outputs: { + FooOutput: { Value: 'Foo' }, + }, + }, MatchStyle.SUPERSET); + + expect(stack).not.toMatchTemplate({ + Outputs: { + FooOutput: { Value: 'Foo' }, + BarOutput: { Value: 'Baz' }, + }, + }, MatchStyle.SUPERSET); + + expect(stack).not.toMatchTemplate({ + Outputs: { + FooOutput: { Value: 'Bar' }, + BazOutput: { Value: 'Bar' }, + }, + }, MatchStyle.SUPERSET); + }); + }); +}); \ No newline at end of file From 97fc29032c05edb7914c48efee0124be0126a5c4 Mon Sep 17 00:00:00 2001 From: Julian Michel Date: Thu, 12 Aug 2021 14:29:42 +0200 Subject: [PATCH 44/99] feat(aws-apigateway): import existing usage plan (#15771) New method `UsagePlan.fromUsagePlanId()` that allows to import an existing usage plan using its id. Closes #12677. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/@aws-cdk/aws-apigateway/README.md | 6 ++ .../@aws-cdk/aws-apigateway/lib/usage-plan.ts | 96 ++++++++++++++----- .../integ.usage-plan.sharing.expected.json | 41 ++++++++ .../test/integ.usage-plan.sharing.ts | 37 +++++++ .../aws-apigateway/test/usage-plan.test.ts | 20 ++++ 5 files changed, 176 insertions(+), 24 deletions(-) create mode 100644 packages/@aws-cdk/aws-apigateway/test/integ.usage-plan.sharing.expected.json create mode 100644 packages/@aws-cdk/aws-apigateway/test/integ.usage-plan.sharing.ts diff --git a/packages/@aws-cdk/aws-apigateway/README.md b/packages/@aws-cdk/aws-apigateway/README.md index 9e33ef2125810..620b728b91435 100644 --- a/packages/@aws-cdk/aws-apigateway/README.md +++ b/packages/@aws-cdk/aws-apigateway/README.md @@ -212,6 +212,12 @@ plan.addApiStage({ }); ``` +Existing usage plans can be imported into a CDK app using its id. + +```ts +const importedUsagePlan = UsagePlan.fromUsagePlanId(stack, 'imported-usage-plan', ''); +``` + The name and value of the API Key can be specified at creation; if not provided, a name and value will be automatically generated by API Gateway. diff --git a/packages/@aws-cdk/aws-apigateway/lib/usage-plan.ts b/packages/@aws-cdk/aws-apigateway/lib/usage-plan.ts index 82f45bc538db6..4db28eb936e80 100644 --- a/packages/@aws-cdk/aws-apigateway/lib/usage-plan.ts +++ b/packages/@aws-cdk/aws-apigateway/lib/usage-plan.ts @@ -1,4 +1,4 @@ -import { FeatureFlags, Lazy, Names, Resource, Token } from '@aws-cdk/core'; +import { FeatureFlags, IResource, Lazy, Names, Resource, Token } from '@aws-cdk/core'; import { APIGATEWAY_USAGEPLANKEY_ORDERINSENSITIVE_ID } from '@aws-cdk/cx-api'; import { Construct } from 'constructs'; import { IApiKey } from './api-key'; @@ -156,35 +156,32 @@ export interface AddApiKeyOptions { readonly overrideLogicalId?: string; } -export class UsagePlan extends Resource { +/** + * A UsagePlan, either managed by this CDK app, or imported. + */ +export interface IUsagePlan extends IResource { /** + * Id of the usage plan * @attribute */ - public readonly usagePlanId: string; - - private readonly apiStages = new Array(); + readonly usagePlanId: string; - constructor(scope: Construct, id: string, props: UsagePlanProps = { }) { - super(scope, id); - let resource: CfnUsagePlan; - - resource = new CfnUsagePlan(this, 'Resource', { - apiStages: Lazy.any({ produce: () => this.renderApiStages(this.apiStages) }), - description: props.description, - quota: this.renderQuota(props), - throttle: this.renderThrottle(props.throttle), - usagePlanName: props.name, - }); - - this.apiStages.push(...(props.apiStages || [])); + /** + * Adds an ApiKey. + * + * @param apiKey the api key to associate with this usage plan + * @param options options that control the behaviour of this method + */ + addApiKey(apiKey: IApiKey, options?: AddApiKeyOptions): void; - this.usagePlanId = resource.ref; +} - // Add ApiKey when - if (props.apiKey) { - this.addApiKey(props.apiKey); - } - } +abstract class UsagePlanBase extends Resource implements IUsagePlan { + /** + * Id of the usage plan + * @attribute + */ + public abstract readonly usagePlanId: string; /** * Adds an ApiKey. @@ -213,6 +210,57 @@ export class UsagePlan extends Resource { } } +} + +export class UsagePlan extends UsagePlanBase { + + /** + * Import an externally defined usage plan using its ARN. + * + * @param scope the construct that will "own" the imported usage plan. + * @param id the id of the imported usage plan in the construct tree. + * @param usagePlanId the id of an existing usage plan. + */ + public static fromUsagePlanId(scope: Construct, id: string, usagePlanId: string): IUsagePlan { + class Import extends UsagePlanBase { + public readonly usagePlanId = usagePlanId; + + constructor() { + super(scope, id); + } + } + return new Import(); + } + + /** + * @attribute + */ + public readonly usagePlanId: string; + + private readonly apiStages = new Array(); + + constructor(scope: Construct, id: string, props: UsagePlanProps = { }) { + super(scope, id); + let resource: CfnUsagePlan; + + resource = new CfnUsagePlan(this, 'Resource', { + apiStages: Lazy.any({ produce: () => this.renderApiStages(this.apiStages) }), + description: props.description, + quota: this.renderQuota(props), + throttle: this.renderThrottle(props.throttle), + usagePlanName: props.name, + }); + + this.apiStages.push(...(props.apiStages || [])); + + this.usagePlanId = resource.ref; + + // Add ApiKey when + if (props.apiKey) { + this.addApiKey(props.apiKey); + } + } + /** * Adds an apiStage. * @param apiStage diff --git a/packages/@aws-cdk/aws-apigateway/test/integ.usage-plan.sharing.expected.json b/packages/@aws-cdk/aws-apigateway/test/integ.usage-plan.sharing.expected.json new file mode 100644 index 0000000000000..9e663c4a1f2c8 --- /dev/null +++ b/packages/@aws-cdk/aws-apigateway/test/integ.usage-plan.sharing.expected.json @@ -0,0 +1,41 @@ +[ + { + "Resources": { + "myusageplan4B391740": { + "Type": "AWS::ApiGateway::UsagePlan" + } + }, + "Outputs": { + "ExportsOutputRefmyusageplan4B391740F6B819BA": { + "Value": { + "Ref": "myusageplan4B391740" + }, + "Export": { + "Name": "test-apigateway-usageplan-create:ExportsOutputRefmyusageplan4B391740F6B819BA" + } + } + } + }, + { + "Resources": { + "myusageplanUsagePlanKeyResourcetestapigatewayusageplanimportmyapikey14CF31667CCB4183": { + "Type": "AWS::ApiGateway::UsagePlanKey", + "Properties": { + "KeyId": { + "Ref": "myapikey5C116C09" + }, + "KeyType": "API_KEY", + "UsagePlanId": { + "Fn::ImportValue": "test-apigateway-usageplan-create:ExportsOutputRefmyusageplan4B391740F6B819BA" + } + } + }, + "myapikey5C116C09": { + "Type": "AWS::ApiGateway::ApiKey", + "Properties": { + "Enabled": true + } + } + } + } +] \ No newline at end of file diff --git a/packages/@aws-cdk/aws-apigateway/test/integ.usage-plan.sharing.ts b/packages/@aws-cdk/aws-apigateway/test/integ.usage-plan.sharing.ts new file mode 100644 index 0000000000000..58ffe84234367 --- /dev/null +++ b/packages/@aws-cdk/aws-apigateway/test/integ.usage-plan.sharing.ts @@ -0,0 +1,37 @@ +/// !cdk-integ * +import * as cdk from '@aws-cdk/core'; +import * as apigateway from '../lib'; +import { IUsagePlan } from '../lib'; + +class Create extends cdk.Stack { + public usagePlan: IUsagePlan; + + constructor(scope: cdk.App, id: string) { + super(scope, id); + + this.usagePlan = new apigateway.UsagePlan(this, 'myusageplan'); + } +} + +interface ImportStackProps extends cdk.StackProps { + usagePlan: apigateway.IUsagePlan; +} + +class Import extends cdk.Stack { + constructor(scope: cdk.App, id: string, props: ImportStackProps) { + super(scope, id); + + const usageplan = apigateway.UsagePlan.fromUsagePlanId(this, 'myusageplan', props.usagePlan.usagePlanId); + const apikey = new apigateway.ApiKey(this, 'myapikey'); + usageplan.addApiKey(apikey); + } +} + +const app = new cdk.App(); + +const test = new Create(app, 'test-apigateway-usageplan-create'); +new Import(app, 'test-apigateway-usageplan-import', { + usagePlan: test.usagePlan, +}); + +app.synth(); diff --git a/packages/@aws-cdk/aws-apigateway/test/usage-plan.test.ts b/packages/@aws-cdk/aws-apigateway/test/usage-plan.test.ts index 88df6f2a04506..2cb6e4ed48ed2 100644 --- a/packages/@aws-cdk/aws-apigateway/test/usage-plan.test.ts +++ b/packages/@aws-cdk/aws-apigateway/test/usage-plan.test.ts @@ -176,6 +176,26 @@ describe('usage plan', () => { }, ResourcePart.Properties); }); + + test('imported', () => { + // GIVEN + const stack = new cdk.Stack(); + const usagePlan: apigateway.IUsagePlan = apigateway.UsagePlan.fromUsagePlanId(stack, 'my-usage-plan', 'imported-id'); + const apiKey: apigateway.ApiKey = new apigateway.ApiKey(stack, 'my-api-key'); + + // WHEN + usagePlan.addApiKey(apiKey); + + // THEN + expect(stack).toHaveResource('AWS::ApiGateway::UsagePlanKey', { + KeyId: { + Ref: 'myapikey1B052F70', + }, + KeyType: 'API_KEY', + UsagePlanId: 'imported-id', + }, ResourcePart.Properties); + }); + test('multiple keys', () => { // GIVEN const stack = new cdk.Stack(); From 400a59d19ee63fbd9318da34760b4ed8c9ba99b9 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Thu, 12 Aug 2021 15:56:12 +0200 Subject: [PATCH 45/99] fix(pipelines): repos with dashes cannot be used as additionalInputs (#16017) Cause: dashes are valid in *artifact names* in CodePipeline, but are *not* valid in *secondary source names* in CodeBuild. Do a sanitization to the intersection of requirements between CodePipeline and CodeBuild. Fixes #15753. ---- *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 | 4 +- .../lib/codepipeline/artifact-map.ts | 23 +++++++++- .../lib/codepipeline/codepipeline.ts | 2 +- .../codepipeline/codepipeline-sources.test.ts | 42 ++++++++++++++++++- .../pipelines/test/compliance/synths.test.ts | 4 +- .../integ.newpipeline-with-vpc.expected.json | 4 +- .../test/integ.newpipeline.expected.json | 4 +- 7 files changed, 70 insertions(+), 13 deletions(-) diff --git a/packages/@aws-cdk/pipelines/lib/codepipeline/_codebuild-factory.ts b/packages/@aws-cdk/pipelines/lib/codepipeline/_codebuild-factory.ts index c4f2eb41ab3fd..ac125aee29f0d 100644 --- a/packages/@aws-cdk/pipelines/lib/codepipeline/_codebuild-factory.ts +++ b/packages/@aws-cdk/pipelines/lib/codepipeline/_codebuild-factory.ts @@ -326,12 +326,12 @@ function generateInputArtifactLinkCommands(artifacts: ArtifactMap, inputs: FileS const fragments = []; if (!['.', '..'].includes(path.dirname(input.directory))) { - fragments.push(`mkdir -p "${input.directory}"`); + fragments.push(`mkdir -p -- "${input.directory}"`); } const artifact = artifacts.toCodePipeline(input.fileSet); - fragments.push(`ln -s "$CODEBUILD_SRC_DIR_${artifact.artifactName}" "${input.directory}"`); + fragments.push(`ln -s -- "$CODEBUILD_SRC_DIR_${artifact.artifactName}" "${input.directory}"`); return fragments.join(' && '); }); diff --git a/packages/@aws-cdk/pipelines/lib/codepipeline/artifact-map.ts b/packages/@aws-cdk/pipelines/lib/codepipeline/artifact-map.ts index 4ec4b086815c7..2d3383bb469bf 100644 --- a/packages/@aws-cdk/pipelines/lib/codepipeline/artifact-map.ts +++ b/packages/@aws-cdk/pipelines/lib/codepipeline/artifact-map.ts @@ -1,3 +1,4 @@ +import * as crypto from 'crypto'; import * as cp from '@aws-cdk/aws-codepipeline'; import { FileSet } from '../blueprint'; import { PipelineGraph } from '../helpers-internal'; @@ -38,9 +39,27 @@ export class ArtifactMap { } } +/** + * Sanitize a string to be a valid artifact name + * + * This must comport to both the rules of artifacts in CodePipeline, as well + * as the names of Source Identifiers in CodeBuild. + * + * Artifact Name limits aren't documented. + * + * Source Identifier limits are documented here: + * https://docs.aws.amazon.com/codebuild/latest/APIReference/API_ProjectSource.html#CodeBuild-Type-ProjectSource-sourceIdentifier + */ function sanitizeArtifactName(x: string): string { - // FIXME: Does this REALLY not allow '.'? The docs don't mention it, but action names etc. do! - return x.replace(/[^A-Za-z0-9@\-_]/g, '_'); + let sani = x.replace(/[^A-Za-z0-9_]/g, '_'); // Charset requirement is imposed by CodeBuild + const maxLength = 100; // Max length of 100 is imposed by CodePipeline library + + if (sani.length > maxLength) { + const fingerprint = crypto.createHash('sha256').update(sani).digest('hex').substr(0, 8); + sani = sani.substr(0, maxLength - fingerprint.length) + fingerprint; + } + + return sani; } /** diff --git a/packages/@aws-cdk/pipelines/lib/codepipeline/codepipeline.ts b/packages/@aws-cdk/pipelines/lib/codepipeline/codepipeline.ts index 27a2b15509532..7b1d0d87d9c22 100644 --- a/packages/@aws-cdk/pipelines/lib/codepipeline/codepipeline.ts +++ b/packages/@aws-cdk/pipelines/lib/codepipeline/codepipeline.ts @@ -830,7 +830,7 @@ enum CodeBuildProjectType { function actionName(node: GraphNode, parent: GraphNode) { const names = node.ancestorPath(parent).map(n => n.id); - return names.map(sanitizeName).join('.'); + return names.map(sanitizeName).join('.').substr(0, 100); // Cannot exceed 100 chars } function sanitizeName(x: string): string { diff --git a/packages/@aws-cdk/pipelines/test/codepipeline/codepipeline-sources.test.ts b/packages/@aws-cdk/pipelines/test/codepipeline/codepipeline-sources.test.ts index 72553c38262d3..84aef10bb171c 100644 --- a/packages/@aws-cdk/pipelines/test/codepipeline/codepipeline-sources.test.ts +++ b/packages/@aws-cdk/pipelines/test/codepipeline/codepipeline-sources.test.ts @@ -1,4 +1,4 @@ -import { anything, arrayWith, objectLike } from '@aws-cdk/assert-internal'; +import { anything, arrayWith, Capture, objectLike } from '@aws-cdk/assert-internal'; import '@aws-cdk/assert-internal/jest'; import * as ccommit from '@aws-cdk/aws-codecommit'; import { CodeCommitTrigger, GitHubTrigger } from '@aws-cdk/aws-codepipeline-actions'; @@ -140,5 +140,43 @@ test('GitHub source does not accept unresolved identifiers', () => { }).toThrow(/Step id cannot be unresolved/); }); +test('Dashes in repo names are removed from artifact names', () => { + new ModernTestGitHubNpmPipeline(pipelineStack, 'Pipeline', { + input: cdkp.CodePipelineSource.gitHub('owner/my-repo', 'main'), + }); + + expect(pipelineStack).toHaveResourceLike('AWS::CodePipeline::Pipeline', { + Stages: arrayWith({ + Name: 'Source', + Actions: [ + objectLike({ + OutputArtifacts: [ + { Name: 'owner_my_repo_Source' }, + ], + }), + ], + }), + }); +}); + +test('artifact names are never longer than 128 characters', () => { + new ModernTestGitHubNpmPipeline(pipelineStack, 'Pipeline', { + input: cdkp.CodePipelineSource.gitHub('owner/' + 'my-repo'.repeat(100), 'main'), + }); + + const artifactId = Capture.aString(); + expect(pipelineStack).toHaveResourceLike('AWS::CodePipeline::Pipeline', { + Stages: arrayWith({ + Name: 'Source', + Actions: [ + objectLike({ + OutputArtifacts: [ + { Name: artifactId.capture() }, + ], + }), + ], + }), + }); -// a-z0-9.@-_ \ No newline at end of file + expect(artifactId.capturedValue.length).toBeLessThanOrEqual(128); +}); \ 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 247cbd50974e0..58bae441ee156 100644 --- a/packages/@aws-cdk/pipelines/test/compliance/synths.test.ts +++ b/packages/@aws-cdk/pipelines/test/compliance/synths.test.ts @@ -948,8 +948,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"', + 'ln -s -- "$CODEBUILD_SRC_DIR_foo_bar_Source" "../sibling"', + 'ln -s -- "$CODEBUILD_SRC_DIR_Prebuild_Output" "sub"', ], }, build: { 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 7a937f57d6a8e..e0075942e6069 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 @@ -766,7 +766,7 @@ "Name": "rix0rrr_cdk-pipelines-demo", "OutputArtifacts": [ { - "Name": "rix0rrr_cdk-pipelines-demo_Source" + "Name": "rix0rrr_cdk_pipelines_demo_Source" } ], "RunOrder": 1 @@ -791,7 +791,7 @@ }, "InputArtifacts": [ { - "Name": "rix0rrr_cdk-pipelines-demo_Source" + "Name": "rix0rrr_cdk_pipelines_demo_Source" } ], "Name": "Synth", diff --git a/packages/@aws-cdk/pipelines/test/integ.newpipeline.expected.json b/packages/@aws-cdk/pipelines/test/integ.newpipeline.expected.json index 96ffa58af1c62..07e65b9bd643f 100644 --- a/packages/@aws-cdk/pipelines/test/integ.newpipeline.expected.json +++ b/packages/@aws-cdk/pipelines/test/integ.newpipeline.expected.json @@ -232,7 +232,7 @@ "Name": "rix0rrr_cdk-pipelines-demo", "OutputArtifacts": [ { - "Name": "rix0rrr_cdk-pipelines-demo_Source" + "Name": "rix0rrr_cdk_pipelines_demo_Source" } ], "RunOrder": 1 @@ -257,7 +257,7 @@ }, "InputArtifacts": [ { - "Name": "rix0rrr_cdk-pipelines-demo_Source" + "Name": "rix0rrr_cdk_pipelines_demo_Source" } ], "Name": "Synth", From 34edd5b18d7266fa807ff42c03190f105fe1e217 Mon Sep 17 00:00:00 2001 From: Nico Tonnhofer Date: Thu, 12 Aug 2021 16:54:03 +0200 Subject: [PATCH 46/99] chore(lambda-python): strip out deprecated symbols (#15958) While other commits already remove most deprecated symbols this was left. ---- *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-python/lib/bundling.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-lambda-python/lib/bundling.ts b/packages/@aws-cdk/aws-lambda-python/lib/bundling.ts index 5a3228a78fef7..0c2b4bf624786 100644 --- a/packages/@aws-cdk/aws-lambda-python/lib/bundling.ts +++ b/packages/@aws-cdk/aws-lambda-python/lib/bundling.ts @@ -100,7 +100,7 @@ export function bundle(options: BundlingOptions): lambda.Code { const image = cdk.DockerImage.fromBuild(stagedir, { buildArgs: { - IMAGE: runtime.bundlingDockerImage.image, + IMAGE: runtime.bundlingImage.image, }, file: dockerfile, }); From ab228a648fa08e8189c010d475426f1ff003ddf7 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Thu, 12 Aug 2021 18:59:07 +0200 Subject: [PATCH 47/99] chore(core): tell which stack is exceeding max resource count (#16019) Previously, the error message gave no indication which stack was violating the resource count, which does not help when you have dozens. ---- *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/stack.ts | 2 +- packages/@aws-cdk/core/test/stack.test.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk/core/lib/stack.ts b/packages/@aws-cdk/core/lib/stack.ts index a74a82e55ccd6..ee80e56334101 100644 --- a/packages/@aws-cdk/core/lib/stack.ts +++ b/packages/@aws-cdk/core/lib/stack.ts @@ -785,7 +785,7 @@ export class Stack extends CoreConstruct implements ITaggable { const numberOfResources = Object.keys(resources).length; if (numberOfResources > this.maxResources) { - throw new Error(`Number of resources: ${numberOfResources} is greater than allowed maximum of ${this.maxResources}`); + throw new Error(`Number of resources in stack '${this.node.path}': ${numberOfResources} is greater than allowed maximum of ${this.maxResources}`); } else if (numberOfResources >= (this.maxResources * 0.8)) { Annotations.of(this).addInfo(`Number of resources: ${numberOfResources} is approaching allowed maximum of ${this.maxResources}`); } diff --git a/packages/@aws-cdk/core/test/stack.test.ts b/packages/@aws-cdk/core/test/stack.test.ts index 11a4a01796031..4473b99e0c2dc 100644 --- a/packages/@aws-cdk/core/test/stack.test.ts +++ b/packages/@aws-cdk/core/test/stack.test.ts @@ -59,7 +59,7 @@ describe('stack', () => { expect(() => { app.synth(); - }).toThrow('Number of resources: 1000 is greater than allowed maximum of 500'); + }).toThrow('Number of resources in stack \'MyStack\': 1000 is greater than allowed maximum of 500'); }); @@ -81,7 +81,7 @@ describe('stack', () => { expect(() => { app.synth(); - }).toThrow('Number of resources: 200 is greater than allowed maximum of 100'); + }).toThrow('Number of resources in stack \'MyStack\': 200 is greater than allowed maximum of 100'); }); From bb5d5874098b4b1047a29b6697e5e3a65f349ff0 Mon Sep 17 00:00:00 2001 From: Sam Wilson Date: Thu, 12 Aug 2021 15:34:42 -0500 Subject: [PATCH 48/99] feat(apigatewayv2): http api - domain url for a stage (#15973) Closes #15801 By adding and `apiMapping` field to base.ts, we can reference the custom domain information from the `HttpStage` construct ---- *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-apigatewayv2/README.md | 6 +++ .../lib/common/api-mapping.ts | 6 +++ .../aws-apigatewayv2/lib/common/base.ts | 11 ++++- .../aws-apigatewayv2/lib/http/stage.ts | 11 +++++ .../aws-apigatewayv2/test/http/stage.test.ts | 47 ++++++++++++++++++- 5 files changed, 78 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk/aws-apigatewayv2/README.md b/packages/@aws-cdk/aws-apigatewayv2/README.md index c5dc2318b2d53..cf0a2ab0552c7 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/README.md +++ b/packages/@aws-cdk/aws-apigatewayv2/README.md @@ -224,6 +224,12 @@ with 3 API mapping resources across different APIs and Stages. | api | beta | `https://${domainName}/bar` | | apiDemo | $default | `https://${domainName}/demo` | +You can retrieve the full domain URL with mapping key using the `domainUrl` property as so - + +```ts +const demoDomainUrl = apiDemo.defaultStage.domainUrl; // returns "https://example.com/demo" +``` + ### Managing access API Gateway supports multiple mechanisms for [controlling and managing access to your HTTP diff --git a/packages/@aws-cdk/aws-apigatewayv2/lib/common/api-mapping.ts b/packages/@aws-cdk/aws-apigatewayv2/lib/common/api-mapping.ts index adbe3fe3efc2c..f9ebfc89b52ca 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/lib/common/api-mapping.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/lib/common/api-mapping.ts @@ -82,6 +82,11 @@ export class ApiMapping extends Resource implements IApiMapping { */ public readonly mappingKey?: string; + /** + * API domain name + */ + public readonly domainName: IDomainName; + constructor(scope: Construct, id: string, props: ApiMappingProps) { super(scope, id); @@ -121,5 +126,6 @@ export class ApiMapping extends Resource implements IApiMapping { this.apiMappingId = resource.ref; this.mappingKey = props.apiMappingKey; + this.domainName = props.domainName; } } diff --git a/packages/@aws-cdk/aws-apigatewayv2/lib/common/base.ts b/packages/@aws-cdk/aws-apigatewayv2/lib/common/base.ts index cd88fceba46b8..006df3f83cd2b 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/lib/common/base.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/lib/common/base.ts @@ -36,6 +36,12 @@ export abstract class StageBase extends Resource implements IStage { public abstract readonly stageName: string; protected abstract readonly baseApi: IApi; + /** + * The created ApiMapping if domain mapping has been added + * @internal + */ + protected _apiMapping?: ApiMapping + /** * The URL to this stage. */ @@ -45,7 +51,10 @@ export abstract class StageBase extends Resource implements IStage { * @internal */ protected _addDomainMapping(domainMapping: DomainMappingOptions) { - new ApiMapping(this, `${domainMapping.domainName}${domainMapping.mappingKey}`, { + if (this._apiMapping) { + throw new Error('Only one ApiMapping allowed per Stage'); + } + this._apiMapping = new ApiMapping(this, `${domainMapping.domainName}${domainMapping.mappingKey}`, { api: this.baseApi, domainName: domainMapping.domainName, stage: this, diff --git a/packages/@aws-cdk/aws-apigatewayv2/lib/http/stage.ts b/packages/@aws-cdk/aws-apigatewayv2/lib/http/stage.ts index 3ad58eea4364b..709f207a04435 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/lib/http/stage.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/lib/http/stage.ts @@ -176,4 +176,15 @@ export class HttpStage extends HttpStageBase { const urlPath = this.stageName === DEFAULT_STAGE_NAME ? '' : this.stageName; return `https://${this.api.apiId}.execute-api.${s.region}.${s.urlSuffix}/${urlPath}`; } + + /** + * The custom domain URL to this stage + */ + public get domainUrl(): string { + if (!this._apiMapping) { + throw new Error('domainUrl is not available when no API mapping is associated with the Stage'); + } + + return `https://${this._apiMapping.domainName.name}/${this._apiMapping.mappingKey ?? ''}`; + } } diff --git a/packages/@aws-cdk/aws-apigatewayv2/test/http/stage.test.ts b/packages/@aws-cdk/aws-apigatewayv2/test/http/stage.test.ts index c56c2ded5d48b..e7a05924719d3 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/test/http/stage.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/test/http/stage.test.ts @@ -1,8 +1,8 @@ import { Template } from '@aws-cdk/assertions'; +import { Certificate } from '@aws-cdk/aws-certificatemanager'; import { Metric } from '@aws-cdk/aws-cloudwatch'; import { Stack } from '@aws-cdk/core'; -import { HttpApi, HttpStage } from '../../lib'; - +import { DomainName, HttpApi, HttpStage } from '../../lib'; describe('HttpStage', () => { test('default', () => { @@ -116,4 +116,47 @@ describe('HttpStage', () => { const metricNames = metrics.map(m => m.metricName); expect(metricNames).toEqual(['4xx', '5xx', 'DataProcessed', 'Latency', 'IntegrationLatency', 'Count']); }); +}); + +describe('HttpStage with domain mapping', () => { + const domainName = 'example.com'; + const certArn = 'arn:aws:acm:us-east-1:111111111111:certificate'; + + test('domainUrl returns the correct path', () => { + const stack = new Stack(); + const api = new HttpApi(stack, 'Api', { + createDefaultStage: false, + }); + + const dn = new DomainName(stack, 'DN', { + domainName, + certificate: Certificate.fromCertificateArn(stack, 'cert', certArn), + }); + + const stage = new HttpStage(stack, 'DefaultStage', { + httpApi: api, + domainMapping: { + domainName: dn, + }, + }); + + expect(stage.domainUrl).toBe(`https://${domainName}/`); + }); + + test('domainUrl throws error if domainMapping is not configured', () => { + const stack = new Stack(); + const api = new HttpApi(stack, 'Api', { + createDefaultStage: false, + }); + + const stage = new HttpStage(stack, 'DefaultStage', { + httpApi: api, + }); + + const t = () => { + stage.domainUrl; + }; + + expect(t).toThrow(/domainUrl is not available when no API mapping is associated with the Stage/); + }); }); \ No newline at end of file From f8d8795a610c3f49e31967001695caa648730d6d Mon Sep 17 00:00:00 2001 From: Sven Kirschbaum Date: Fri, 13 Aug 2021 11:59:48 +0200 Subject: [PATCH 49/99] fix(s3-deployment): BucketDeployment doesn't validate that distribution paths start with "/" (#15865) Cloudfront invalidation paths must start with a leading "/". This pull requests adds a corresponding validation to fail during build instead of during the Cloudformation deployment. closes #9317 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../lib/bucket-deployment.ts | 11 +++++++-- .../test/bucket-deployment.test.ts | 24 +++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/aws-s3-deployment/lib/bucket-deployment.ts b/packages/@aws-cdk/aws-s3-deployment/lib/bucket-deployment.ts index 3a73b950792bf..990a1ec359d0b 100644 --- a/packages/@aws-cdk/aws-s3-deployment/lib/bucket-deployment.ts +++ b/packages/@aws-cdk/aws-s3-deployment/lib/bucket-deployment.ts @@ -196,8 +196,15 @@ export class BucketDeployment extends CoreConstruct { constructor(scope: Construct, id: string, props: BucketDeploymentProps) { super(scope, id); - if (props.distributionPaths && !props.distribution) { - throw new Error('Distribution must be specified if distribution paths are specified'); + if (props.distributionPaths) { + if (!props.distribution) { + throw new Error('Distribution must be specified if distribution paths are specified'); + } + if (!cdk.Token.isUnresolved(props.distributionPaths)) { + if (!props.distributionPaths.every(distributionPath => cdk.Token.isUnresolved(distributionPath) || distributionPath.startsWith('/'))) { + throw new Error('Distribution paths must start with "/"'); + } + } } const handler = new lambda.SingletonFunction(this, 'CustomResourceHandler', { diff --git a/packages/@aws-cdk/aws-s3-deployment/test/bucket-deployment.test.ts b/packages/@aws-cdk/aws-s3-deployment/test/bucket-deployment.test.ts index 2bbe5e34a41a6..893c5ae03b35f 100644 --- a/packages/@aws-cdk/aws-s3-deployment/test/bucket-deployment.test.ts +++ b/packages/@aws-cdk/aws-s3-deployment/test/bucket-deployment.test.ts @@ -491,6 +491,30 @@ test('fails if distribution paths provided but not distribution ID', () => { }); +test('fails if distribution paths don\'t start with "/"', () => { + // GIVEN + const stack = new cdk.Stack(); + const bucket = new s3.Bucket(stack, 'Dest'); + const distribution = new cloudfront.CloudFrontWebDistribution(stack, 'Distribution', { + originConfigs: [ + { + s3OriginSource: { + s3BucketSource: bucket, + }, + behaviors: [{ isDefaultBehavior: true }], + }, + ], + }); + + // THEN + expect(() => new s3deploy.BucketDeployment(stack, 'Deploy', { + sources: [s3deploy.Source.asset(path.join(__dirname, 'my-website.zip'))], + destinationBucket: bucket, + distribution, + distributionPaths: ['images/*'], + })).toThrow(/Distribution paths must start with "\/"/); +}); + testFutureBehavior('lambda execution role gets permissions to read from the source bucket and read/write in destination', s3GrantWriteCtx, cdk.App, (app) => { // GIVEN const stack = new cdk.Stack(app); From fdee43ccc3501cf628eea5204387b37977059539 Mon Sep 17 00:00:00 2001 From: Clarence Date: Fri, 13 Aug 2021 20:38:35 +0800 Subject: [PATCH 50/99] docs(ecs): Fix ecs readme markdown (#16018) ---- *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/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-ecs/README.md b/packages/@aws-cdk/aws-ecs/README.md index 9e8170f86d826..8e3adc1e3d737 100644 --- a/packages/@aws-cdk/aws-ecs/README.md +++ b/packages/@aws-cdk/aws-ecs/README.md @@ -909,7 +909,7 @@ taskDefinition.addContainer('cont', { Please note, ECS Exec leverages AWS Systems Manager (SSM). So as a prerequisite for the exec command to work, you need to have the SSM plugin for the AWS CLI installed locally. For more information, see -[Install Session Manager plugin for AWS CLI] (https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html). +[Install Session Manager plugin for AWS CLI](https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html). To enable the ECS Exec feature for your containers, set the boolean flag `enableExecuteCommand` to `true` in your `Ec2Service` or `FargateService`. From a308cacf1fc48e24311caec246b768ffe6ae9153 Mon Sep 17 00:00:00 2001 From: Romain Marcadier Date: Fri, 13 Aug 2021 15:41:48 +0200 Subject: [PATCH 51/99] fix(ec2): opaque error when insufficient NAT EIPs are configured (#16040) When manually configuring NAT gateways for a VPC, a relatively opaque error is emitted when insufficient EIP allocation IDs are provided, compared to the subnet count. Added a proactive validation of the allocation IDs to improve the actionability of the error message. Fixes #16039 ---- *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/nat.ts | 10 ++++- packages/@aws-cdk/aws-ec2/test/vpc.test.ts | 46 ++++++++++++++++------ 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/packages/@aws-cdk/aws-ec2/lib/nat.ts b/packages/@aws-cdk/aws-ec2/lib/nat.ts index e991e732f38b0..4743799762b51 100644 --- a/packages/@aws-cdk/aws-ec2/lib/nat.ts +++ b/packages/@aws-cdk/aws-ec2/lib/nat.ts @@ -222,6 +222,14 @@ class NatGatewayProvider extends NatProvider { } public configureNat(options: ConfigureNatOptions) { + if ( + this.props.eipAllocationIds != null + && !Token.isUnresolved(this.props.eipAllocationIds) + && this.props.eipAllocationIds.length < options.natSubnets.length + ) { + throw new Error(`Not enough NAT gateway EIP allocation IDs (${this.props.eipAllocationIds.length} provided) for the requested subnet count (${options.natSubnets.length} needed).`); + } + // Create the NAT gateways let i = 0; for (const sub of options.natSubnets) { @@ -413,4 +421,4 @@ function pickN(i: number, xs: string[]) { } return xs[i]; -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/aws-ec2/test/vpc.test.ts b/packages/@aws-cdk/aws-ec2/test/vpc.test.ts index dd22090584a25..d65bc016271be 100644 --- a/packages/@aws-cdk/aws-ec2/test/vpc.test.ts +++ b/packages/@aws-cdk/aws-ec2/test/vpc.test.ts @@ -35,7 +35,7 @@ nodeunitShim({ 'vpc.vpcId returns a token to the VPC ID'(test: Test) { const stack = getTestStack(); const vpc = new Vpc(stack, 'TheVPC'); - test.deepEqual(stack.resolve(vpc.vpcId), { Ref: 'TheVPC92636AB0' } ); + test.deepEqual(stack.resolve(vpc.vpcId), { Ref: 'TheVPC92636AB0' }); test.done(); }, @@ -55,11 +55,11 @@ nodeunitShim({ new Vpc(stack, 'TheVPC'); cdkExpect(stack).to( haveResource('AWS::EC2::VPC', - hasTags( [{ Key: 'Name', Value: 'TestStack/TheVPC' }])), + hasTags([{ Key: 'Name', Value: 'TestStack/TheVPC' }])), ); cdkExpect(stack).to( haveResource('AWS::EC2::InternetGateway', - hasTags( [{ Key: 'Name', Value: 'TestStack/TheVPC' }])), + hasTags([{ Key: 'Name', Value: 'TestStack/TheVPC' }])), ); test.done(); }, @@ -86,7 +86,7 @@ nodeunitShim({ 'dns getters correspond to CFN properties': (() => { - const tests: any = { }; + const tests: any = {}; const inputs = [ { dnsSupport: false, dnsHostnames: false }, @@ -173,8 +173,7 @@ nodeunitShim({ }, ], }); - cdkExpect(stack).to(countResources('AWS::EC2::InternetGateway', 1)) - ; + cdkExpect(stack).to(countResources('AWS::EC2::InternetGateway', 1)); cdkExpect(stack).notTo(haveResource('AWS::EC2::NatGateway')); test.done(); }, @@ -223,7 +222,7 @@ nodeunitShim({ 'with no subnets defined, the VPC should have an IGW, and a NAT Gateway per AZ'(test: Test) { const stack = getTestStack(); const zones = stack.availabilityZones.length; - new Vpc(stack, 'TheVPC', { }); + new Vpc(stack, 'TheVPC', {}); cdkExpect(stack).to(countResources('AWS::EC2::InternetGateway', 1)); cdkExpect(stack).to(countResources('AWS::EC2::NatGateway', zones)); test.done(); @@ -251,7 +250,7 @@ nodeunitShim({ cdkExpect(stack).to(haveResource('AWS::EC2::InternetGateway')); cdkExpect(stack).to(haveResourceLike('AWS::EC2::Route', { DestinationCidrBlock: '8.8.8.8/32', - GatewayId: { }, + GatewayId: {}, })); test.done(); }, @@ -457,7 +456,7 @@ nodeunitShim({ } cdkExpect(stack).to(haveResourceLike('AWS::EC2::Route', { DestinationCidrBlock: '0.0.0.0/0', - NatGatewayId: { }, + NatGatewayId: {}, })); test.done(); @@ -475,7 +474,7 @@ nodeunitShim({ } cdkExpect(stack).to(haveResourceLike('AWS::EC2::Route', { DestinationCidrBlock: '0.0.0.0/0', - NatGatewayId: { }, + NatGatewayId: {}, })); test.done(); }, @@ -489,7 +488,7 @@ nodeunitShim({ cdkExpect(stack).to(countResources('AWS::EC2::NatGateway', 1)); cdkExpect(stack).to(haveResourceLike('AWS::EC2::Route', { DestinationCidrBlock: '0.0.0.0/0', - NatGatewayId: { }, + NatGatewayId: {}, })); test.done(); }, @@ -873,6 +872,31 @@ nodeunitShim({ test.done(); }, + 'NAT gateway provider with insufficient EIP allocations'(test: Test) { + const stack = new Stack(); + const natGatewayProvider = NatProvider.gateway({ eipAllocationIds: ['a'] }); + expect(() => new Vpc(stack, 'VpcNetwork', { natGatewayProvider })) + .toThrow(/Not enough NAT gateway EIP allocation IDs \(1 provided\) for the requested subnet count \(\d+ needed\)/); + + test.done(); + }, + + 'NAT gateway provider with token EIP allocations'(test: Test) { + const stack = new Stack(); + const eipAllocationIds = Fn.split(',', Fn.importValue('myVpcId')); + const natGatewayProvider = NatProvider.gateway({ eipAllocationIds }); + new Vpc(stack, 'VpcNetwork', { natGatewayProvider }); + + cdkExpect(stack).to(haveResource('AWS::EC2::NatGateway', { + AllocationId: stack.resolve(Fn.select(0, eipAllocationIds)), + })); + cdkExpect(stack).to(haveResource('AWS::EC2::NatGateway', { + AllocationId: stack.resolve(Fn.select(1, eipAllocationIds)), + })); + + test.done(); + }, + 'Can add an IPv6 route'(test: Test) { // GIVEN const stack = getTestStack(); From f570c94a7bc99cd5bebc96ee388d152220f9f613 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Fri, 13 Aug 2021 16:45:30 +0200 Subject: [PATCH 52/99] fix(events): cross-account event targets that have a Role are broken (#15717) When we started supporting cross-region event targets, we needed to add a role to the event-bus target. At that point, we also opted to fall back to the role that the event target requested for itself. However, that was wrong: the role used in that place is *only* for passing events between event buses, and *never* for triggering the actual target. Solution: don't fall back, only use a special role for event passing. In fact, don't even do it if the target isn't in a different region, because apparently it's not necessary for cross-account event passing at all. Refactor the `events` code a little to make clear what is happening and why, because it was starting to get messy. Fixes #15639. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../codecommit-source-action.test.ts | 87 +++++- packages/@aws-cdk/aws-events/lib/rule.ts | 276 ++++++++++-------- .../@aws-cdk/aws-events/test/test.rule.ts | 54 +++- 3 files changed, 291 insertions(+), 126 deletions(-) diff --git a/packages/@aws-cdk/aws-codepipeline-actions/test/codecommit/codecommit-source-action.test.ts b/packages/@aws-cdk/aws-codepipeline-actions/test/codecommit/codecommit-source-action.test.ts index 8c668be7f47d8..da226dd37a74d 100644 --- a/packages/@aws-cdk/aws-codepipeline-actions/test/codecommit/codecommit-source-action.test.ts +++ b/packages/@aws-cdk/aws-codepipeline-actions/test/codecommit/codecommit-source-action.test.ts @@ -1,4 +1,4 @@ -import { arrayWith, countResources, expect, haveResourceLike, not, objectLike } from '@aws-cdk/assert-internal'; +import { ABSENT, arrayWith, countResources, expect, haveResourceLike, not, objectLike } from '@aws-cdk/assert-internal'; import * as codebuild from '@aws-cdk/aws-codebuild'; import * as codecommit from '@aws-cdk/aws-codecommit'; import * as codepipeline from '@aws-cdk/aws-codepipeline'; @@ -38,6 +38,91 @@ nodeunitShim({ test.done(); }, + 'cross-account CodeCommit Repository Source does not use target role in source stack'(test: Test) { + // Test for https://github.com/aws/aws-cdk/issues/15639 + const app = new App(); + const sourceStack = new Stack(app, 'SourceStack', { env: { account: '1234', region: 'north-pole' } }); + const targetStack = new Stack(app, 'TargetStack', { env: { account: '5678', region: 'north-pole' } }); + + const repo = new codecommit.Repository(sourceStack, 'MyRepo', { + repositoryName: 'my-repo', + }); + + const sourceOutput = new codepipeline.Artifact(); + new codepipeline.Pipeline(targetStack, 'MyPipeline', { + stages: [ + { + stageName: 'Source', + actions: [ + new cpactions.CodeCommitSourceAction({ actionName: 'Source', repository: repo, output: sourceOutput }), + ], + }, + { + stageName: 'Build', + actions: [ + new cpactions.CodeBuildAction({ actionName: 'Build', project: new codebuild.PipelineProject(targetStack, 'MyProject'), input: sourceOutput }), + ], + }, + ], + }); + + // THEN - creates a Rule in the source stack targeting the pipeline stack's event bus using a generated role + expect(sourceStack).to(haveResourceLike('AWS::Events::Rule', { + EventPattern: { + source: ['aws.codecommit'], + resources: [ + { 'Fn::GetAtt': ['MyRepoF4F48043', 'Arn'] }, + ], + }, + Targets: [{ + RoleARN: ABSENT, + Arn: { + 'Fn::Join': ['', [ + 'arn:', + { 'Ref': 'AWS::Partition' }, + ':events:north-pole:5678:event-bus/default', + ]], + }, + }], + })); + + // THEN - creates a Rule in the pipeline stack using the role to start the pipeline + expect(targetStack).to(haveResourceLike('AWS::Events::Rule', { + 'EventPattern': { + 'source': [ + 'aws.codecommit', + ], + 'resources': [ + { + 'Fn::Join': [ + '', + [ + 'arn:', + { 'Ref': 'AWS::Partition' }, + ':codecommit:north-pole:1234:my-repo', + ], + ], + }, + ], + }, + 'Targets': [ + { + 'Arn': { + 'Fn::Join': ['', [ + 'arn:', + { 'Ref': 'AWS::Partition' }, + ':codepipeline:north-pole:5678:', + { 'Ref': 'MyPipelineAED38ECF' }, + ]], + }, + 'RoleArn': { 'Fn::GetAtt': ['MyPipelineEventsRoleFAB99F32', 'Arn'] }, + }, + ], + })); + + test.done(); + }, + 'does not poll for source changes and uses Events for CodeCommitTrigger.EVENTS'(test: Test) { const stack = new Stack(); diff --git a/packages/@aws-cdk/aws-events/lib/rule.ts b/packages/@aws-cdk/aws-events/lib/rule.ts index 08ecb18bbc1d7..47f5d05201a53 100644 --- a/packages/@aws-cdk/aws-events/lib/rule.ts +++ b/packages/@aws-cdk/aws-events/lib/rule.ts @@ -1,5 +1,5 @@ import { IRole, PolicyStatement, Role, ServicePrincipal } from '@aws-cdk/aws-iam'; -import { App, IConstruct, IResource, Lazy, Names, Resource, Stack, Token, PhysicalName } from '@aws-cdk/core'; +import { App, IResource, Lazy, Names, Resource, Stack, Token, PhysicalName } from '@aws-cdk/core'; import { Node, Construct } from 'constructs'; import { IEventBus } from './event-bus'; import { EventPattern } from './event-pattern'; @@ -9,10 +9,6 @@ import { Schedule } from './schedule'; import { IRuleTarget } from './target'; import { mergeEventPattern, renderEventPattern, sameEnvDimension } from './util'; -// keep this import separate from other imports to reduce chance for merge conflicts with v2-main -// eslint-disable-next-line no-duplicate-imports, import/order -import { Construct as CoreConstruct } from '@aws-cdk/core'; - /** * Properties for defining an EventBridge Rule */ @@ -118,7 +114,9 @@ export class Rule extends Resource implements IRule { private readonly eventPattern: EventPattern = { }; private readonly scheduleExpression?: string; private readonly description?: string; - private readonly targetAccounts: {[key: string]: Set} = {}; + + /** Set to keep track of what target accounts and regions we've already created event buses for */ + private readonly _xEnvTargetsAdded = new Set(); constructor(scope: Construct, id: string, props: RuleProps = { }) { super(scope, id, { @@ -194,63 +192,19 @@ export class Rule extends Resource implements IRule { // based on: // https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-cross-account.html - // for cross-account or cross-region events, we cannot create new components for an imported resource - // because we don't have the target stack - const isImportedResource = !sameEnvDimension(targetStack.account, targetAccount) || !sameEnvDimension(targetStack.region, targetRegion); //(targetAccount !== targetStack.account) || (targetRegion !== targetStack.region); - if (isImportedResource) { - throw new Error('Cannot create a cross-account or cross-region rule with an imported resource'); - } - - // for cross-account or cross-region events, we require concrete accounts + // for cross-account or cross-region events, we require a concrete target account and region if (!targetAccount || Token.isUnresolved(targetAccount)) { throw new Error('You need to provide a concrete account for the target stack when using cross-account or cross-region events'); } - if (Token.isUnresolved(sourceAccount)) { - throw new Error('You need to provide a concrete account for the source stack when using cross-account or cross-region events'); - } - // and the target region has to be concrete as well if (!targetRegion || Token.isUnresolved(targetRegion)) { throw new Error('You need to provide a concrete region for the target stack when using cross-account or cross-region events'); } - - // the _actual_ target is just the event bus of the target's account - // make sure we only add it once per account per region - let targetAccountExists = false; - const accountKey = Object.keys(this.targetAccounts).find(account => account === targetAccount); - if (accountKey) { - targetAccountExists = this.targetAccounts[accountKey].has(targetRegion); - } - - if (!targetAccountExists) { - // add the current account-region pair to tracking structure - const regionsSet = this.targetAccounts[targetAccount]; - if (!regionsSet) { - this.targetAccounts[targetAccount] = new Set(); - } - this.targetAccounts[targetAccount].add(targetRegion); - - const eventBusArn = targetStack.formatArn({ - service: 'events', - resource: 'event-bus', - resourceName: 'default', - region: targetRegion, - account: targetAccount, - }); - - this.targets.push({ - id, - arn: eventBusArn, - // for cross-region we now require a role with PutEvents permissions - roleArn: roleArn ?? this.singletonEventRole(this, [this.putEventStatement(eventBusArn)]).roleArn, - }); + if (Token.isUnresolved(sourceAccount)) { + throw new Error('You need to provide a concrete account for the source stack when using cross-account or cross-region events'); } - // Grant the source account in the source region permissions to publish events to the event bus of the target account in the target region. - // Do it in a separate stack instead of the target stack (which seems like the obvious place to put it), - // because it needs to be deployed before the rule containing the above event-bus target in the source stack - // (EventBridge verifies whether you have permissions to the targets on rule creation), - // but it's common for the target stack to depend on the source stack - // (that's the case with CodePipeline, for example) + // Don't exactly understand why this code was here (seems unlikely this rule would be violated), but + // let's leave it in nonetheless. const sourceApp = this.node.root; if (!sourceApp || !App.isApp(sourceApp)) { throw new Error('Event stack which uses cross-account or cross-region targets must be part of a CDK app'); @@ -263,60 +217,28 @@ export class Rule extends Resource implements IRule { throw new Error('Event stack and target stack must belong to the same CDK app'); } - // if different accounts, we need to add the permissions to the target eventbus - if (!sameEnvDimension(sourceAccount, targetAccount)) { - const stackId = `EventBusPolicy-${sourceAccount}-${targetRegion}-${targetAccount}`; - let eventBusPolicyStack: Stack = sourceApp.node.tryFindChild(stackId) as Stack; - if (!eventBusPolicyStack) { - eventBusPolicyStack = new Stack(sourceApp, stackId, { - env: { - account: targetAccount, - region: targetRegion, - }, - stackName: `${targetStack.stackName}-EventBusPolicy-support-${targetRegion}-${sourceAccount}`, - }); - new CfnEventBusPolicy(eventBusPolicyStack, 'GivePermToOtherAccount', { - action: 'events:PutEvents', - statementId: `Allow-account-${sourceAccount}`, - principal: sourceAccount, - }); - } - // deploy the event bus permissions before the source stack - sourceStack.addDependency(eventBusPolicyStack); - } - - // The actual rule lives in the target stack. - // Other than the account, it's identical to this one - - // eventPattern is mutable through addEventPattern(), so we need to lazy evaluate it - // but only Tokens can be lazy in the framework, so make a subclass instead - const self = this; - - class CopyRule extends Rule { - public _renderEventPattern(): any { - return self._renderEventPattern(); - } - - // we need to override validate(), as it uses the - // value of the eventPattern field, - // which might be empty in the case of the copied rule - // (as the patterns in the original might be added through addEventPattern(), - // not passed through the constructor). - // Anyway, even if the original rule is invalid, - // we would get duplicate errors if we didn't override this, - // which is probably a bad idea in and of itself - protected validate(): string[] { - return []; - } - - } - - new CopyRule(targetStack, `${Names.uniqueId(this)}-${id}`, { + // The target of this Rule will be the default event bus of the target environment + this.ensureXEnvTargetEventBus(targetStack, targetAccount, targetRegion, id); + + // The actual rule lives in the target stack. Other than the account, it's identical to this one, + // but only evaluated at render time (via a special subclass). + // + // FIXME: the MirrorRule is a bit silly, forwarding the exact same event to another event bus + // and trigger on it there (there will be issues with construct references, for example). Especially + // in the case of scheduled events, we will just trigger both rules in parallel in both environments. + // + // A better solution would be to have the source rule add a unique token to the the event, + // and have the mirror rule trigger on that token only (thereby properly separating triggering, which + // happens in the source env; and activating, which happens in the target env). + // + // Don't have time to do that right now. + const mirrorRuleScope = this.obtainMirrorRuleScope(targetStack, targetAccount, targetRegion); + new MirrorRule(mirrorRuleScope, `${Names.uniqueId(this)}-${id}`, { targets: [target], eventPattern: this.eventPattern, schedule: this.scheduleExpression ? Schedule.expression(this.scheduleExpression) : undefined, description: this.description, - }); + }, this); return; } @@ -413,32 +335,140 @@ export class Rule extends Resource implements IRule { } /** - * Obtain the Role for the EventBridge event - * - * If a role already exists, it will be returned. This ensures that if multiple - * events have the same target, they will share a role. - * @internal - */ - private singletonEventRole(scope: IConstruct, policyStatements: PolicyStatement[]): IRole { - const id = 'EventsRole'; - const existing = scope.node.tryFindChild(id) as IRole; - if (existing) { return existing; } + * Make sure we add the target environments event bus as a target, and the target has permissions set up to receive our events + * + * For cross-account rules, uses a support stack to set up a policy on the target event bus. + */ + private ensureXEnvTargetEventBus(targetStack: Stack, targetAccount: string, targetRegion: string, id: string) { + // the _actual_ target is just the event bus of the target's account + // make sure we only add it once per account per region + const key = `${targetAccount}:${targetRegion}`; + if (this._xEnvTargetsAdded.has(key)) { return; } + this._xEnvTargetsAdded.add(key); + + const eventBusArn = targetStack.formatArn({ + service: 'events', + resource: 'event-bus', + resourceName: 'default', + region: targetRegion, + account: targetAccount, + }); - const role = new Role(scope as CoreConstruct, id, { - roleName: PhysicalName.GENERATE_IF_NEEDED, - assumedBy: new ServicePrincipal('events.amazonaws.com'), + // For some reason, cross-region requires a Role (with `PutEvents` on the + // target event bus) while cross-account doesn't + const roleArn = !sameEnvDimension(targetRegion, Stack.of(this).region) + ? this.crossRegionPutEventsRole(eventBusArn).roleArn + : undefined; + + this.targets.push({ + id, + arn: eventBusArn, + roleArn, }); - policyStatements.forEach(role.addToPolicy.bind(role)); + // Add a policy to the target Event Bus to allow the source account/region to publish into it. + // + // Since this Event Bus permission needs to be deployed before the stack containing the Rule is deployed + // (as EventBridge verifies whether you have permissions to the targets on rule creation), this needs + // to be in a support stack. + + const sourceApp = this.node.root as App; + const sourceAccount = Stack.of(this).account; + + // If different accounts, we need to add the permissions to the target eventbus + // + // For different region, no need for a policy on the target event bus (but a need + // for a role). + if (!sameEnvDimension(sourceAccount, targetAccount)) { + const stackId = `EventBusPolicy-${sourceAccount}-${targetRegion}-${targetAccount}`; + let eventBusPolicyStack: Stack = sourceApp.node.tryFindChild(stackId) as Stack; + if (!eventBusPolicyStack) { + eventBusPolicyStack = new Stack(sourceApp, stackId, { + env: { + account: targetAccount, + region: targetRegion, + }, + // The region in the stack name is rather redundant (it will always be the target region) + // Leaving it in for backwards compatibility. + stackName: `${targetStack.stackName}-EventBusPolicy-support-${targetRegion}-${sourceAccount}`, + }); + new CfnEventBusPolicy(eventBusPolicyStack, 'GivePermToOtherAccount', { + action: 'events:PutEvents', + statementId: `Allow-account-${sourceAccount}`, + principal: sourceAccount, + }); + } + // deploy the event bus permissions before the source stack + Stack.of(this).addDependency(eventBusPolicyStack); + } + } - return role; + /** + * Return the scope where the mirror rule should be created for x-env event targets + * + * This is the target resource's containing stack if it shares the same region (owned + * resources), or should be a fresh support stack for imported resources. + * + * We don't implement the second yet, as I have to think long and hard on whether we + * can reuse the existing support stack or not, and I don't have time for that right now. + */ + private obtainMirrorRuleScope(targetStack: Stack, targetAccount: string, targetRegion: string): Construct { + // for cross-account or cross-region events, we cannot create new components for an imported resource + // because we don't have the target stack + if (sameEnvDimension(targetStack.account, targetAccount) && sameEnvDimension(targetStack.region, targetRegion)) { + return targetStack; + } + + // For now, we don't do the work for the support stack yet + throw new Error('Cannot create a cross-account or cross-region rule for an imported resource (create a stack with the right environment for the imported resource)'); } - private putEventStatement(eventBusArn: string) { - return new PolicyStatement({ + /** + * Obtain the Role for the EventBridge event + * + * If a role already exists, it will be returned. This ensures that if multiple + * events have the same target, they will share a role. + * @internal + */ + private crossRegionPutEventsRole(eventBusArn: string): IRole { + const id = 'EventsRole'; + let role = this.node.tryFindChild(id) as IRole; + if (!role) { + role = new Role(this, id, { + roleName: PhysicalName.GENERATE_IF_NEEDED, + assumedBy: new ServicePrincipal('events.amazonaws.com'), + }); + } + + role.addToPrincipalPolicy(new PolicyStatement({ actions: ['events:PutEvents'], resources: [eventBusArn], - }); + })); + + return role; } } +/** + * A rule that mirrors another rule + */ +class MirrorRule extends Rule { + constructor(scope: Construct, id: string, props: RuleProps, private readonly source: Rule) { + super(scope, id, props); + } + + public _renderEventPattern(): any { + return this.source._renderEventPattern(); + } + + /** + * Override validate to be a no-op + * + * The rules are never stored on this object so there's nothing to validate. + * + * Instead, we mirror the other rule at render time. + */ + protected validate(): string[] { + return []; + } +} diff --git a/packages/@aws-cdk/aws-events/test/test.rule.ts b/packages/@aws-cdk/aws-events/test/test.rule.ts index 352ee30132733..b6ff7b62d86d4 100644 --- a/packages/@aws-cdk/aws-events/test/test.rule.ts +++ b/packages/@aws-cdk/aws-events/test/test.rule.ts @@ -1,3 +1,4 @@ +/* eslint-disable object-curly-newline */ import { expect, haveResource, haveResourceLike } from '@aws-cdk/assert-internal'; import * as iam from '@aws-cdk/aws-iam'; import * as cdk from '@aws-cdk/core'; @@ -417,6 +418,55 @@ export = { test.done(); }, + 'in cross-account scenario, target role is only used in target account'(test: Test) { + // GIVEN + const app = new cdk.App(); + const ruleStack = new cdk.Stack(app, 'RuleStack', { env: { account: '1234', region: 'us-east-1' } }); + const targetStack = new cdk.Stack(app, 'TargeTStack', { env: { account: '5678', region: 'us-east-1' } }); + + const rule = new Rule(ruleStack, 'EventRule', { + schedule: Schedule.rate(cdk.Duration.minutes(1)), + }); + + const role = new iam.Role(targetStack, 'SomeRole', { + assumedBy: new iam.ServicePrincipal('nobody'), + }); + + // a plain string should just be stringified (i.e. double quotes added and escaped) + rule.addTarget({ + bind: () => ({ + id: '', + arn: 'ARN2', + role, + targetResource: role, // Not really but good enough + }), + }); + + // THEN + expect(ruleStack).to(haveResourceLike('AWS::Events::Rule', { + Targets: [ + { + Arn: { 'Fn::Join': ['', [ + 'arn:', + { 'Ref': 'AWS::Partition' }, + ':events:us-east-1:5678:event-bus/default', + ]] }, + }, + ], + })); + expect(targetStack).to(haveResourceLike('AWS::Events::Rule', { + 'Targets': [ + { + 'Arn': 'ARN2', + 'Id': 'Target0', + 'RoleArn': { 'Fn::GetAtt': ['SomeRole6DDC54DD', 'Arn'] }, + }, + ], + })); + + test.done(); + }, + 'asEventRuleTarget can use the ruleArn and a uniqueId of the rule'(test: Test) { const stack = new cdk.Stack(); @@ -618,7 +668,7 @@ export = { test.throws(() => { rule.addTarget(new SomeTarget('T', resource)); - }, /You need to provide a concrete account for the source stack when using cross-account or cross-region events/); + }, /You need to provide a concrete region/); test.done(); }, @@ -843,7 +893,7 @@ export = { const resource = EventBus.fromEventBusArn(sourceStack, 'TargetEventBus', `arn:aws:events:${targetRegion}:${targetAccount}:event-bus/default`); test.throws(() => { rule.addTarget(new SomeTarget('T', resource)); - }, /Cannot create a cross-account or cross-region rule with an imported resource/); + }, /Cannot create a cross-account or cross-region rule for an imported resource/); test.done(); }, From 9618fd4ad1c4a8d5c555d75b259da05ade5c002b Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Fri, 13 Aug 2021 17:26:16 +0200 Subject: [PATCH 53/99] chore(ecs): allow selecting Bottlerocket via `machineImage` (#16038) As introduced in #10097, Bottlerocket had to be explicitly (and only) selected via setting `machineImageType`, which would pick an appropriate `machineImage`. Setting `machineImage` to `new BottleRocketImage()` would not be sufficient, since the feature also requires configuring additional UserData commands which are only added if `machineImageType` was set. This method of configuration does not allow customization of the AMI, such as introduced in #16021. Instead, we reverse the logic: `machineImageType` may still be necessary to autoconfigure UserData if we can't know what the machineImage is (for example in case of a preconfigured AutoScalingGroup), but otherwise is derived from what `machineImage` is being used. We allow configuring both fields at the same time for the case when the autodetection fails. ---- *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/README.md | 14 ++++---- packages/@aws-cdk/aws-ecs/lib/cluster.ts | 31 ++++++++++++------ .../@aws-cdk/aws-ecs/test/cluster.test.ts | 32 +++++++++++++------ 3 files changed, 51 insertions(+), 26 deletions(-) diff --git a/packages/@aws-cdk/aws-ecs/README.md b/packages/@aws-cdk/aws-ecs/README.md index 8e3adc1e3d737..180710a7e2cb3 100644 --- a/packages/@aws-cdk/aws-ecs/README.md +++ b/packages/@aws-cdk/aws-ecs/README.md @@ -141,15 +141,13 @@ purpose-built by AWS for running containers. You can launch Amazon ECS container The following example will create a capacity with self-managed Amazon EC2 capacity of 2 `c5.large` Linux instances running with `Bottlerocket` AMI. -Note that you must specify either a `machineImage` or `machineImageType`, at least one, not both. - The following example adds Bottlerocket capacity to the cluster: ```ts cluster.addCapacity('bottlerocket-asg', { minCapacity: 2, instanceType: new ec2.InstanceType('c5.large'), - machineImageType: ecs.MachineImageType.BOTTLEROCKET, + machineImage: new ecs.BottleRocketImage(), }); ``` @@ -214,7 +212,7 @@ some supporting containers which are used to support the main container, doings things like upload logs or metrics to monitoring services. To run a task or service with Amazon EC2 launch type, use the `Ec2TaskDefinition`. For AWS Fargate tasks/services, use the -`FargateTaskDefinition`. For AWS ECS Anywhere use the `ExternalTaskDefinition`. These classes +`FargateTaskDefinition`. For AWS ECS Anywhere use the `ExternalTaskDefinition`. These classes provide simplified APIs that only contain properties relevant for each specific launch type. For a `FargateTaskDefinition`, specify the task size (`memoryLimitMiB` and `cpu`): @@ -736,7 +734,7 @@ const service = new ecs.Ec2Service(stack, 'Service', { }); ``` -With `bridge` or `host` network modes, only `SRV` DNS record types are supported. +With `bridge` or `host` network modes, only `SRV` DNS record types are supported. By default, `SRV` DNS record types will target the default container and default port. However, you may target a different container and port on the same ECS task: @@ -893,7 +891,7 @@ const taskDefinition = new ecs.Ec2TaskDefinition(stack, 'Ec2TaskDef', { To enable using the inference accelerators in the containers, add `inferenceAcceleratorResources` field and set it to a list of device names used for the inference accelerators. Each value in the -list should match a `DeviceName` for an `InferenceAccelerator` specified in the task definition. +list should match a `DeviceName` for an `InferenceAccelerator` specified in the task definition. ```ts const inferenceAcceleratorResources = ['device1']; @@ -927,11 +925,11 @@ const service = new ecs.Ec2Service(stack, 'Service', { You can enable sending logs of your execute session commands to a CloudWatch log group or S3 bucket by configuring the `executeCommandConfiguration` property for your cluster. The default configuration will send the logs to the CloudWatch Logs using the `awslogs` log driver that is configured in your task definition. Please note, -when using your own `logConfiguration` the log group or S3 Bucket specified must already be created. +when using your own `logConfiguration` the log group or S3 Bucket specified must already be created. To encrypt data using your own KMS Customer Key (CMK), you must create a CMK and provide the key in the `kmsKey` field of the `executeCommandConfiguration`. To use this key for encrypting CloudWatch log data or S3 bucket, make sure to associate the key -to these resources on creation. +to these resources on creation. ```ts const kmsKey = new kms.Key(stack, 'KmsKey'); diff --git a/packages/@aws-cdk/aws-ecs/lib/cluster.ts b/packages/@aws-cdk/aws-ecs/lib/cluster.ts index 5b9da054a9fe2..1fce9b00d4500 100644 --- a/packages/@aws-cdk/aws-ecs/lib/cluster.ts +++ b/packages/@aws-cdk/aws-ecs/lib/cluster.ts @@ -294,12 +294,13 @@ export class Cluster extends Resource implements ICluster { * @deprecated Use {@link Cluster.addAsgCapacityProvider} instead. */ public addCapacity(id: string, options: AddCapacityOptions): autoscaling.AutoScalingGroup { - if (options.machineImage && options.machineImageType) { - throw new Error('You can only specify either machineImage or machineImageType, not both.'); - } + // Do 2-way defaulting here: if the machineImageType is BOTTLEROCKET, pick the right AMI. + // Otherwise, determine the machineImageType from the given AMI. + const machineImage = options.machineImage ?? + (options.machineImageType === MachineImageType.BOTTLEROCKET ? new BottleRocketImage() : new EcsOptimizedAmi()); - const machineImage = options.machineImage ?? options.machineImageType === MachineImageType.BOTTLEROCKET ? - new BottleRocketImage() : new EcsOptimizedAmi(); + const machineImageType = options.machineImageType ?? + (isBottleRocketImage(machineImage) ? MachineImageType.BOTTLEROCKET : MachineImageType.AMAZON_LINUX_2); const autoScalingGroup = new autoscaling.AutoScalingGroup(this, id, { vpc: this.vpc, @@ -309,7 +310,7 @@ export class Cluster extends Resource implements ICluster { }); this.addAutoScalingGroup(autoScalingGroup, { - machineImageType: options.machineImageType, + machineImageType: machineImageType, ...options, }); @@ -1016,11 +1017,18 @@ export interface AddAutoScalingGroupCapacityOptions { */ readonly topicEncryptionKey?: kms.IKey; - /** - * Specify the machine image type. + * What type of machine image this is + * + * Depending on the setting, different UserData will automatically be added + * to the `AutoScalingGroup` to configure it properly for use with ECS. * - * @default MachineImageType.AMAZON_LINUX_2 + * If you create an `AutoScalingGroup` yourself and are adding it via + * `addAutoScalingGroup()`, you must specify this value. If you are adding an + * `autoScalingGroup` via `addCapacity`, this value will be determined + * from the `machineImage` you pass. + * + * @default - Automatically determined from `machineImage`, if available, otherwise `MachineImageType.AMAZON_LINUX_2`. */ readonly machineImageType?: MachineImageType; } @@ -1356,3 +1364,8 @@ class MaybeCreateCapacityProviderAssociations implements IAspect { } } } + + +function isBottleRocketImage(image: ec2.IMachineImage) { + return image instanceof BottleRocketImage; +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ecs/test/cluster.test.ts b/packages/@aws-cdk/aws-ecs/test/cluster.test.ts index cd144f87bfb12..8b6dd4626ddb6 100644 --- a/packages/@aws-cdk/aws-ecs/test/cluster.test.ts +++ b/packages/@aws-cdk/aws-ecs/test/cluster.test.ts @@ -1589,7 +1589,7 @@ nodeunitShim({ test.done(); }, - 'cluster capacity with bottlerocket AMI'(test: Test) { + 'cluster capacity with bottlerocket AMI, by setting machineImageType'(test: Test) { // GIVEN const app = new cdk.App(); const stack = new cdk.Stack(app, 'test'); @@ -1682,20 +1682,34 @@ nodeunitShim({ test.done(); }, - 'throws when machineImage and machineImageType both specified'(test: Test) { + 'cluster capacity with bottlerocket AMI, by setting the machineImage'(test: Test) { // GIVEN const app = new cdk.App(); const stack = new cdk.Stack(app, 'test'); + const cluster = new ecs.Cluster(stack, 'EcsCluster'); + cluster.addCapacity('bottlerocket-asg', { + instanceType: new ec2.InstanceType('c5.large'), + machineImage: new ecs.BottleRocketImage(), + }); // THEN - test.throws(() => { - cluster.addCapacity('bottlerocket-asg', { - instanceType: new ec2.InstanceType('c5.large'), - machineImageType: ecs.MachineImageType.BOTTLEROCKET, - machineImage: new ecs.EcsOptimizedAmi(), - }); - }, /You can only specify either machineImage or machineImageType, not both./); + expect(stack).to(haveResourceLike('AWS::AutoScaling::LaunchConfiguration', { + UserData: { + 'Fn::Base64': { + 'Fn::Join': [ + '', + [ + '\n[settings.ecs]\ncluster = "', + { + Ref: 'EcsCluster97242B84', + }, + '"', + ], + ], + }, + }, + })); test.done(); }, From 1b29ca8e8805fe47eb534d2f564d18ca297e956f Mon Sep 17 00:00:00 2001 From: Nick Lynch Date: Fri, 13 Aug 2021 17:18:49 +0100 Subject: [PATCH 54/99] chore(cdk-release): track and bump separate alpha version (#16043) As part of the project to release our alpha modules as independent modules, this change extends our `cdk-release` tool to support tracking and bumping two versions: the primary, stable version, and an additional, optional alpha version. If the local `version.vX.json` file has an `alphaVersion` property, this version will be bumped alongside the main (stable) version. If the main version is also a prerelease, then the alphaVersion is simply incremented (e.g., `2.0.0-alpha.0` -> `2.0.0-alpha.1`); if the main version is stable, the alpha is incremented to match (e.g., the `2.1.0` release will get an alpha of `2.1.0-alpha.0`). If no `alphaVersion` is present, it is simply ignored. This is still only part of the work to release the alpha modules. Remaining: - Create the indepedent module CHANGELOGs, and aggregate into the main CHANGELOG - Change the `align-versions` script to read and apply the alphaVersion if the module is an alpha module. - Create the first alpha version in the v2-main branch. *Implementation details:* I was frustrated by the generic 'Updater' and 'UpdaterModule' pattern that I needed to work around, so I decided to just simplify by removing the generic capabilities that we're not using. This involved deleting a lot of code that wasn't doing much. Lots of refactoring ensured. Similarly, there simply weren't nearly enough tests in this module yet; I added at least a few more to improve coverage in anticipation of the next tasks (which will require even more tests). My apologies to the reviewer(s) for the muddled diff, but I strongly believe these simplifications will make it easier to maintain `cdk-release` going forward. related #15591 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- scripts/bump.js | 3 + tools/cdk-release/lib/conventional-commits.ts | 2 +- tools/cdk-release/lib/defaults.ts | 19 +--- tools/cdk-release/lib/index.ts | 48 +++------ tools/cdk-release/lib/lifecycles/bump.ts | 92 ++++++++-------- tools/cdk-release/lib/lifecycles/changelog.ts | 33 ++++-- tools/cdk-release/lib/private/files.ts | 7 +- tools/cdk-release/lib/private/print.ts | 12 ++- tools/cdk-release/lib/types.ts | 35 ++---- tools/cdk-release/lib/updaters/index.ts | 59 ----------- tools/cdk-release/lib/updaters/types/json.ts | 28 ----- .../lib/updaters/types/plain-text.ts | 12 --- tools/cdk-release/test/bump.test.ts | 77 ++++++++++++++ tools/cdk-release/test/changelog.test.ts | 60 ++--------- .../test/conventional-commits.test.ts | 100 ++++++++++++++++++ 15 files changed, 294 insertions(+), 293 deletions(-) delete mode 100644 tools/cdk-release/lib/updaters/index.ts delete mode 100644 tools/cdk-release/lib/updaters/types/json.ts delete mode 100644 tools/cdk-release/lib/updaters/types/plain-text.ts create mode 100644 tools/cdk-release/test/bump.test.ts create mode 100644 tools/cdk-release/test/conventional-commits.test.ts diff --git a/scripts/bump.js b/scripts/bump.js index a0a05f398669f..b7e364bc0ab16 100755 --- a/scripts/bump.js +++ b/scripts/bump.js @@ -67,6 +67,9 @@ async function main() { // this is incredible, but passing this option to standard-version actually makes it crash! // good thing we're getting rid of it... opts.verbose = !!process.env.VERBOSE; + // Rename some options to match cdk-release inputs (replaces bumpFiles, packageFiles, and infile) + opts.versionFile = ver.versionFile; + opts.changelogFile = ver.changelogFile; console.error("🎉 Calling our 'cdk-release' package to make the bump"); console.error("ℹ️ Set the LEGACY_BUMP env variable to use the old 'standard-version' bump instead"); const cdkRelease = require('cdk-release'); diff --git a/tools/cdk-release/lib/conventional-commits.ts b/tools/cdk-release/lib/conventional-commits.ts index 4ad2b88e33005..ed42884bc8b08 100644 --- a/tools/cdk-release/lib/conventional-commits.ts +++ b/tools/cdk-release/lib/conventional-commits.ts @@ -72,10 +72,10 @@ export async function getConventionalCommitsFromGitHistory(args: ReleaseOptions, const ret = new Array(); return new Promise((resolve, reject) => { const conventionalCommitsStream = gitRawCommits({ + // Raw body (subject + body) + '\n-hash-\n' + commit hash format: '%B%n-hash-%n%H', // our tags have the 'v' prefix from: gitTag, - // path: options.path, }).pipe(conventionalCommitsParser()); conventionalCommitsStream.on('data', function (data: any) { diff --git a/tools/cdk-release/lib/defaults.ts b/tools/cdk-release/lib/defaults.ts index 22f53ebe806aa..84d823c094b5b 100644 --- a/tools/cdk-release/lib/defaults.ts +++ b/tools/cdk-release/lib/defaults.ts @@ -1,31 +1,14 @@ import { ReleaseOptions } from './types'; -const defaultPackageFiles = [ - 'package.json', - 'bower.json', - 'manifest.json', -]; - -export const defaultBumpFiles = defaultPackageFiles.concat([ - 'package-lock.json', - 'npm-shrinkwrap.json', -]); - export const defaults: Partial = { - infile: 'CHANGELOG.md', - // firstRelease: false, + changelogFile: 'CHANGELOG.md', sign: false, - // noVerify: false, - // commitAll: false, silent: false, scripts: {}, skip: { tag: true, }, - packageFiles: defaultPackageFiles, - bumpFiles: defaultBumpFiles, dryRun: false, - // gitTagFallback: true, releaseCommitMessageFormat: 'chore(release): {{currentTag}}', changeLogHeader: '# Changelog\n\nAll notable changes to this project will be documented in this file. ' + 'See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.\n', diff --git a/tools/cdk-release/lib/index.ts b/tools/cdk-release/lib/index.ts index 0f72cdda7fe2e..04159170ffd81 100644 --- a/tools/cdk-release/lib/index.ts +++ b/tools/cdk-release/lib/index.ts @@ -6,8 +6,7 @@ import { bump } from './lifecycles/bump'; import { changelog } from './lifecycles/changelog'; import { commit } from './lifecycles/commit'; import { debug, debugObject } from './private/print'; -import { ReleaseOptions } from './types'; -import { resolveUpdaterObjectFromArgument } from './updaters'; +import { ReleaseOptions, Versions } from './types'; module.exports = async function main(opts: ReleaseOptions): Promise { // handle the default options @@ -17,41 +16,28 @@ module.exports = async function main(opts: ReleaseOptions): Promise { }; debugObject(args, 'options are (including defaults)', args); - const packageInfo = determinePackageInfo(args); - debugObject(args, 'packageInfo is', packageInfo); + const currentVersion = readVersion(args.versionFile); + debugObject(args, 'Current version info', currentVersion); - const currentVersion = packageInfo.version; - debug(args, 'Current version is: ' + currentVersion); - - const commits = await getConventionalCommitsFromGitHistory(args, `v${currentVersion}`); + const commits = await getConventionalCommitsFromGitHistory(args, `v${currentVersion.stableVersion}`); const filteredCommits = filterCommits(args, commits); debugObject(args, 'Found and filtered commits', filteredCommits); - const bumpResult = await bump(args, currentVersion); - const newVersion = bumpResult.newVersion; - debug(args, 'New version is: ' + newVersion); + const newVersion = await bump(args, currentVersion); + debugObject(args, 'New version is', newVersion); - const changelogResult = await changelog(args, currentVersion, newVersion, filteredCommits); + debug(args, 'Writing Changelog'); + await changelog(args, currentVersion.stableVersion, newVersion.stableVersion, filteredCommits); - await commit(args, newVersion, [...bumpResult.changedFiles, ...changelogResult.changedFiles]); + debug(args, 'Committing result'); + await commit(args, newVersion.stableVersion, [args.versionFile, args.changelogFile]); }; -interface PackageInfo { - version: string; - private: string | boolean | null | undefined; -} - -function determinePackageInfo(args: ReleaseOptions): PackageInfo { - for (const packageFile of args.packageFiles ?? []) { - const updater = resolveUpdaterObjectFromArgument(packageFile); - const pkgPath = path.resolve(process.cwd(), updater.filename); - const contents = fs.readFileSync(pkgPath, 'utf8'); - // we stop on the first (successful) option - return { - version: updater.updater.readVersion(contents), - private: typeof updater.updater.isPrivate === 'function' ? updater.updater.isPrivate(contents) : false, - }; - } - - throw new Error('Could not establish the version to bump!'); +export function readVersion(versionFile: string): Versions { + const versionPath = path.resolve(process.cwd(), versionFile); + const contents = JSON.parse(fs.readFileSync(versionPath, { encoding: 'utf-8' })); + return { + stableVersion: contents.version, + alphaVersion: contents.alphaVersion, + }; } diff --git a/tools/cdk-release/lib/lifecycles/bump.ts b/tools/cdk-release/lib/lifecycles/bump.ts index bb4465461f2d5..0a6417cb080d6 100644 --- a/tools/cdk-release/lib/lifecycles/bump.ts +++ b/tools/cdk-release/lib/lifecycles/bump.ts @@ -1,31 +1,48 @@ -import * as fs from 'fs'; import * as path from 'path'; import * as semver from 'semver'; import { writeFile } from '../private/files'; import { notify } from '../private/print'; -import { ReleaseOptions, ReleaseType } from '../types'; -import { resolveUpdaterObjectFromArgument } from '../updaters/index'; +import { LifecyclesSkip, ReleaseType, Versions } from '../types'; -export interface BumpResult { - readonly newVersion: string; - readonly changedFiles: string[]; +export interface BumpOptions { + releaseAs: ReleaseType; + skip?: LifecyclesSkip; + versionFile: string; + prerelease?: string; + + dryRun?: boolean; + verbose?: boolean; + silent?: boolean; } -export async function bump(args: ReleaseOptions, currentVersion: string): Promise { +export async function bump(args: BumpOptions, currentVersion: Versions): Promise { if (args.skip?.bump) { - return { - newVersion: currentVersion, - changedFiles: [], - }; + return currentVersion; } - const releaseType = getReleaseType(args.prerelease, args.releaseAs, currentVersion); - const newVersion = semver.inc(currentVersion, releaseType, args.prerelease); - if (!newVersion) { - throw new Error('Could not increment version: ' + currentVersion); + const releaseType = getReleaseType(args.prerelease, args.releaseAs, currentVersion.stableVersion); + const newStableVersion = semver.inc(currentVersion.stableVersion, releaseType, args.prerelease); + if (!newStableVersion) { + throw new Error('Could not increment version: ' + currentVersion.stableVersion); } - const changedFiles = updateBumpFiles(args, newVersion); - return { newVersion, changedFiles }; + + const newVersion: Versions = { + stableVersion: newStableVersion, + alphaVersion: bumpAlphaReleaseVersion(currentVersion, releaseType), + }; + + notify(args, + 'bumping version in ' + args.versionFile + ' from %s to %s', + [currentVersion, newVersion], + ); + const versionPath = path.resolve(process.cwd(), args.versionFile); + const versionFileContents = JSON.stringify({ + version: newVersion.stableVersion, + alphaVersion: newVersion.alphaVersion, + }, undefined, 2); + writeFile(args, versionPath, versionFileContents); + + return newVersion; } function getReleaseType(prerelease: string | undefined, expectedReleaseType: ReleaseType, currentVersion: string): semver.ReleaseType { @@ -89,34 +106,21 @@ function getTypePriority(type: string): number { } /** - * attempt to update the version number in provided `bumpFiles` - * @param args config object - * @param newVersion version number to update to. - * @return the collection of file paths that were actually changed + * https://github.com/aws/aws-cdk/issues/15581 + * We version any alpha modules in one of two ways, depending on the main/stable release. + * If the main release is itself a prerelease (e.g., 2.0.0-rc.17), + * we will increment the current alpha release. + * If the main release is not a prerelease, we use the main release version, but with an alpha tag. */ -function updateBumpFiles(args: ReleaseOptions, newVersion: string): string[] { - const ret = new Array(); +function bumpAlphaReleaseVersion(currentVersion: Versions, releaseType: semver.ReleaseType): string | undefined { + if (!currentVersion.alphaVersion) { return undefined; } - for (const bumpFile of (args.bumpFiles ?? [])) { - const updater = resolveUpdaterObjectFromArgument(bumpFile); - if (!updater) { - continue; - } - const configPath = path.resolve(process.cwd(), updater.filename); - const stat = fs.lstatSync(configPath); - if (!stat.isFile()) { - continue; - } - const contents = fs.readFileSync(configPath, 'utf8'); - notify(args, - 'bumping version in ' + updater.filename + ' from %s to %s', - [updater.updater.readVersion(contents), newVersion], - ); - writeFile(args, configPath, - updater.updater.writeVersion(contents, newVersion), - ); - ret.push(updater.filename); - } + const newAlphaVersion = releaseType.startsWith('pre') + ? semver.inc(currentVersion.alphaVersion, releaseType, 'alpha') + : semver.inc(currentVersion.stableVersion, 'pre' + releaseType as semver.ReleaseType, 'alpha'); - return ret; + if (!newAlphaVersion) { + throw new Error('Could not increment alpha version: ' + currentVersion.alphaVersion); + } + return newAlphaVersion; } diff --git a/tools/cdk-release/lib/lifecycles/changelog.ts b/tools/cdk-release/lib/lifecycles/changelog.ts index f961fe53b175c..7e1052068ffd9 100644 --- a/tools/cdk-release/lib/lifecycles/changelog.ts +++ b/tools/cdk-release/lib/lifecycles/changelog.ts @@ -3,7 +3,7 @@ import * as fs from 'fs-extra'; import { ConventionalCommit } from '../conventional-commits'; import { writeFile } from '../private/files'; import { notify, debug, debugObject } from '../private/print'; -import { ReleaseOptions } from '../types'; +import { LifecyclesSkip } from '../types'; // eslint-disable-next-line @typescript-eslint/no-require-imports const conventionalChangelogPresetLoader = require('conventional-changelog-preset-loader'); // eslint-disable-next-line @typescript-eslint/no-require-imports @@ -11,13 +11,25 @@ const conventionalChangelogWriter = require('conventional-changelog-writer'); const START_OF_LAST_RELEASE_PATTERN = /(^#+ \[?[0-9]+\.[0-9]+\.[0-9]+| { if (args.skip?.changelog) { return { @@ -28,7 +40,7 @@ export async function changelog( createChangelogIfMissing(args); // find the position of the last release and remove header - let oldContent = args.dryRun ? '' : fs.readFileSync(args.infile!, 'utf-8'); + let oldContent = args.dryRun ? '' : fs.readFileSync(args.changelogFile, 'utf-8'); const oldContentStart = oldContent.search(START_OF_LAST_RELEASE_PATTERN); if (oldContentStart !== -1) { oldContent = oldContent.substring(oldContentStart); @@ -100,24 +112,23 @@ export async function changelog( content += buffer.toString(); }); changelogStream.on('end', function () { - notify(args, 'outputting changes to %s', [args.infile]); + notify(args, 'outputting changes to %s', [args.changelogFile]); if (args.dryRun) { debug(args, `\n---\n${content.trim()}\n---\n`); } else { - writeFile(args, args.infile!, args.changeLogHeader + '\n' + (content + oldContent).replace(/\n+$/, '\n')); + writeFile(args, args.changelogFile, args.changeLogHeader + '\n' + (content + oldContent).replace(/\n+$/, '\n')); } return resolve({ contents: content, - changedFiles: [args.infile!], + changedFiles: [args.changelogFile], }); }); }); } -function createChangelogIfMissing(args: ReleaseOptions) { - if (!fs.existsSync(args.infile!)) { - notify(args, 'created %s', [args.infile]); - // args.outputUnreleased = true - writeFile(args, args.infile!, '\n'); +function createChangelogIfMissing(args: ChangelogOptions) { + if (!fs.existsSync(args.changelogFile)) { + notify(args, 'created %s', [args.changelogFile]); + writeFile(args, args.changelogFile, '\n'); } } diff --git a/tools/cdk-release/lib/private/files.ts b/tools/cdk-release/lib/private/files.ts index 1850e8a79ad4a..d9a68dd894c87 100644 --- a/tools/cdk-release/lib/private/files.ts +++ b/tools/cdk-release/lib/private/files.ts @@ -1,7 +1,10 @@ import * as fs from 'fs'; -import { ReleaseOptions } from '../types'; -export function writeFile(args: ReleaseOptions, filePath: string, content: string): void { +interface WriteFileOpts { + readonly dryRun?: boolean; +} + +export function writeFile(args: WriteFileOpts, filePath: string, content: string): void { if (args.dryRun) { return; } diff --git a/tools/cdk-release/lib/private/print.ts b/tools/cdk-release/lib/private/print.ts index 84b7758a5c4b3..282f47e203040 100644 --- a/tools/cdk-release/lib/private/print.ts +++ b/tools/cdk-release/lib/private/print.ts @@ -1,21 +1,25 @@ import * as util from 'util'; -import { ReleaseOptions } from '../types'; -export function debug(opts: ReleaseOptions, message: string): void { +export interface LoggingOptions { + verbose?: boolean; + silent?: boolean; +} + +export function debug(opts: LoggingOptions, message: string): void { if (opts.verbose) { // eslint-disable-next-line no-console console.log(`[cdk-release] ${message}`); } } -export function debugObject(opts: ReleaseOptions, message: string, object: any): void { +export function debugObject(opts: LoggingOptions, message: string, object: any): void { if (opts.verbose) { // eslint-disable-next-line no-console console.log(`[cdk-release] ${message}:\n`, object); } } -export function notify(opts: ReleaseOptions, msg: string, args: any[]) { +export function notify(opts: LoggingOptions, msg: string, args: any[]) { if (!opts.silent) { // eslint-disable-next-line no-console console.info('✔ ' + util.format(msg, ...args)); diff --git a/tools/cdk-release/lib/types.ts b/tools/cdk-release/lib/types.ts index f6314261cd5f1..822a5beba84d2 100644 --- a/tools/cdk-release/lib/types.ts +++ b/tools/cdk-release/lib/types.ts @@ -9,47 +9,24 @@ export interface Lifecycles { tag?: string; } -type LifecyclesSkip = { +export type LifecyclesSkip = { [key in keyof Lifecycles]: boolean; } -/* ****** Updaters ******** */ - -export interface UpdaterModule { - isPrivate?: (contents: string) => string | boolean | null | undefined; - readVersion(contents: string): string; - writeVersion(contents: string, version: string): string; -} - -export interface ArgUpdater { - filename: string; - type?: string; - updater?: UpdaterModule | string; -} - -export type ArgFile = string | ArgUpdater; - -export interface Updater { - filename: string; - updater: UpdaterModule; +export interface Versions { + stableVersion: string; + alphaVersion?: string; } export type ReleaseType = 'major' | 'minor' | 'patch'; -export interface ConventionalCommitType { - type: string; - section?: string; - hidden?: boolean; -} - /* ****** main options ******** */ export interface ReleaseOptions { releaseAs: ReleaseType; skip?: LifecyclesSkip; - packageFiles?: ArgFile[]; - bumpFiles?: ArgFile[]; - infile?: string; + versionFile: string; + changelogFile: string; prerelease?: string; scripts?: Lifecycles; dryRun?: boolean; diff --git a/tools/cdk-release/lib/updaters/index.ts b/tools/cdk-release/lib/updaters/index.ts deleted file mode 100644 index fd61828925316..0000000000000 --- a/tools/cdk-release/lib/updaters/index.ts +++ /dev/null @@ -1,59 +0,0 @@ -import * as path from 'path'; -import { defaultBumpFiles } from '../defaults'; -import { UpdaterModule, ArgFile, Updater } from '../types'; -import jsonUpdaterModule from './types/json'; -import plainTextUpdaterModule from './types/plain-text'; - -export function resolveUpdaterObjectFromArgument(arg: ArgFile): Updater { - arg = typeof arg === 'string' ? { filename: arg } : arg; - let updaterModule: UpdaterModule; - - if (arg.updater) { - updaterModule = getCustomUpdater(arg.updater); - } else if (arg.type) { - updaterModule = getUpdaterByType(arg.type); - } else { - updaterModule = getUpdaterByFilename(arg.filename); - } - - return { - updater: updaterModule, - filename: arg.filename, - }; -} - -function getCustomUpdater(updater: string | UpdaterModule): UpdaterModule { - if (typeof updater === 'string') { - // eslint-disable-next-line @typescript-eslint/no-require-imports - return require(path.resolve(process.cwd(), updater)); - } - if ( - typeof updater.readVersion === 'function' && - typeof updater.writeVersion === 'function' - ) { - return updater; - } - throw new Error('Updater must be a string path or an object with readVersion and writeVersion methods'); -} - -const JSON_BUMP_FILES = defaultBumpFiles; -function getUpdaterByFilename(filename: any): UpdaterModule { - if (JSON_BUMP_FILES.includes(path.basename(filename))) { - return getUpdaterByType('json'); - } - throw Error( - `Unsupported file (${filename}) provided for bumping.\n Please specify the updater \`type\` or use a custom \`updater\`.`, - ); -} - -const updatersByType: { [key: string]: UpdaterModule } = { - 'json': jsonUpdaterModule, - 'plain-text': plainTextUpdaterModule, -}; -function getUpdaterByType(type: string): UpdaterModule { - const updater = updatersByType[type]; - if (!updater) { - throw Error(`Unable to locate updater for provided type (${type}).`); - } - return updater; -} diff --git a/tools/cdk-release/lib/updaters/types/json.ts b/tools/cdk-release/lib/updaters/types/json.ts deleted file mode 100644 index 23e8490f56f5c..0000000000000 --- a/tools/cdk-release/lib/updaters/types/json.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { UpdaterModule } from '../../types'; - -// eslint-disable-next-line @typescript-eslint/no-require-imports -const detectIndent = require('detect-indent'); -// eslint-disable-next-line @typescript-eslint/no-require-imports -const detectNewline = require('detect-newline'); -// eslint-disable-next-line @typescript-eslint/no-require-imports -const stringifyPackage = require('stringify-package'); - -class JsonUpdaterModule implements UpdaterModule { - public readVersion(contents: string): string { - return JSON.parse(contents).version; - }; - - public writeVersion(contents: string, version: string): string { - const json = JSON.parse(contents); - const indent = detectIndent(contents).indent; - const newline = detectNewline(contents); - json.version = version; - return stringifyPackage(json, indent, newline); - }; - - public isPrivate(contents: string): string | boolean | null | undefined { - return JSON.parse(contents).private; - }; -} -const jsonUpdaterModule = new JsonUpdaterModule(); -export default jsonUpdaterModule; diff --git a/tools/cdk-release/lib/updaters/types/plain-text.ts b/tools/cdk-release/lib/updaters/types/plain-text.ts deleted file mode 100644 index 84ed4de20d563..0000000000000 --- a/tools/cdk-release/lib/updaters/types/plain-text.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { UpdaterModule } from '../../types'; - -const plainTextUpdaterModule: UpdaterModule = { - readVersion(contents: string): string { - return contents; - }, - - writeVersion(_contents: string, version: string): string { - return version; - }, -}; -export default plainTextUpdaterModule; diff --git a/tools/cdk-release/test/bump.test.ts b/tools/cdk-release/test/bump.test.ts new file mode 100644 index 0000000000000..df0d08eaae828 --- /dev/null +++ b/tools/cdk-release/test/bump.test.ts @@ -0,0 +1,77 @@ +import * as path from 'path'; +import { bump } from '../lib/lifecycles/bump'; + +// Mock file and console output +import * as files from '../lib/private/files'; +import * as print from '../lib/private/print'; +const mockWriteFile = jest.spyOn(files, 'writeFile').mockImplementation(() => jest.fn()); +jest.spyOn(print, 'notify').mockImplementation(() => jest.fn()); + +beforeEach(() => { jest.resetAllMocks(); }); + +test('skips bump if skip.bump is set', async () => { + const currentVersion = { stableVersion: '1.1.1', alphaVersion: '1.1.1-alpha.0' }; + const bumpedVersion = await bump({ releaseAs: 'major', versionFile: 'version.json', skip: { bump: true } }, currentVersion); + + expect(bumpedVersion).toEqual(currentVersion); +}); + +describe('stable versions', () => { + + test('does a prerelease bump with provided tag if given', async () => { + const currentVersion = { stableVersion: '1.2.3' }; + const bumpedVersion = await bump({ releaseAs: 'minor', versionFile: 'version.json', prerelease: 'rc' }, currentVersion); + + expect(bumpedVersion.stableVersion).toEqual('1.3.0-rc.0'); + }); + + test('does a normal bump if no prerelease tag is given', async () => { + const currentVersion = { stableVersion: '1.2.3' }; + const bumpedVersion = await bump({ releaseAs: 'minor', versionFile: 'version.json' }, currentVersion); + + expect(bumpedVersion.stableVersion).toEqual('1.3.0'); + }); + + test('writes output to version file', async () => { + const currentVersion = { stableVersion: '1.2.3' }; + await bump({ releaseAs: 'minor', versionFile: 'version.json' }, currentVersion); + + const versionPath = path.join(process.cwd(), 'version.json'); + const version = '{\n "version": "1.3.0"\n}'; + expect(mockWriteFile).toBeCalledWith(expect.any(Object), versionPath, version); + }); + +}); + +describe('alpha versions', () => { + + test('for prerelease, bumps existing alpha counter as a prerelease', async () => { + const currentVersion = { stableVersion: '1.2.0-rc.4', alphaVersion: '1.2.0-alpha.0' }; + const bumpedVersion = await bump({ releaseAs: 'minor', versionFile: 'version.json', prerelease: 'rc' }, currentVersion); + + expect(bumpedVersion).toEqual({ + stableVersion: '1.2.0-rc.5', + alphaVersion: '1.2.0-alpha.1', + }); + }); + + test('for normal releases, bumps alpha as a prerelease of stable release', async () => { + const currentVersion = { stableVersion: '1.2.0', alphaVersion: '1.1.0-alpha.0' }; + const bumpedVersion = await bump({ releaseAs: 'minor', versionFile: 'version.json' }, currentVersion); + + expect(bumpedVersion).toEqual({ + stableVersion: '1.3.0', + alphaVersion: '1.3.0-alpha.0', + }); + }); + + test('writes output to version file', async () => { + const currentVersion = { stableVersion: '1.2.0', alphaVersion: '1.1.0-alpha.0' }; + await bump({ releaseAs: 'minor', versionFile: 'version.json' }, currentVersion); + + const versionPath = path.join(process.cwd(), 'version.json'); + const version = '{\n "version": "1.3.0",\n "alphaVersion": "1.3.0-alpha.0"\n}'; + expect(mockWriteFile).toBeCalledWith(expect.any(Object), versionPath, version); + }); + +}); diff --git a/tools/cdk-release/test/changelog.test.ts b/tools/cdk-release/test/changelog.test.ts index 7079aee1d2ac8..67e01477e4ced 100644 --- a/tools/cdk-release/test/changelog.test.ts +++ b/tools/cdk-release/test/changelog.test.ts @@ -1,10 +1,9 @@ -import { ConventionalCommit, filterCommits, getConventionalCommitsFromGitHistory } from '../lib/conventional-commits'; -import { changelog } from '../lib/lifecycles/changelog'; -import { ReleaseOptions } from '../lib/types'; +import { ConventionalCommit } from '../lib/conventional-commits'; +import { changelog, ChangelogOptions } from '../lib/lifecycles/changelog'; describe('Changelog generation', () => { - const args: ReleaseOptions = { - releaseAs: 'minor', + const args: ChangelogOptions = { + changelogFile: 'CHANGELOG.md', dryRun: true, silent: true, includeDateInChangelog: false, @@ -53,52 +52,6 @@ describe('Changelog generation', () => { `); }); - - test("correctly skips experimental modules, even with 'BREAKING CHANGES'", async () => { - const commits: ConventionalCommit[] = [ - buildCommit({ - type: 'feat', - scope: 'scope', - subject: 'super important feature', - }), - buildCommit({ - type: 'fix', - scope: 'example-construct-library', // really hope we don't stabilize this one - subject: 'hairy bugfix', - notes: [ - { - title: 'BREAKING CHANGE', - text: 'this is a breaking change', - }, - ], - }), - ]; - - const changelogContents = await invokeChangelogFrom1_23_0to1_24_0({ - ...args, - stripExperimentalChanges: true, - }, commits); - - expect(changelogContents).toBe( - `## [1.24.0](https://github.com/aws/aws-cdk/compare/v1.23.0...v1.24.0) - -### Features - -* **scope:** super important feature - -`); - }); - - test('makes it so that no Git commits are queried if Changelog generation is skipped', async () => { - const commits = await getConventionalCommitsFromGitHistory({ - ...args, - skip: { - changelog: true, - }, - }, '3.9.2'); - - expect(commits).toHaveLength(0); - }); }); interface PartialCommit extends Partial { @@ -115,7 +68,6 @@ function buildCommit(commit: PartialCommit): ConventionalCommit { }; } -async function invokeChangelogFrom1_23_0to1_24_0(args: ReleaseOptions, commits: ConventionalCommit[]): Promise { - const changelogResult = await changelog(args, '1.23.0', '1.24.0', filterCommits(args, commits)); - return changelogResult.contents; +async function invokeChangelogFrom1_23_0to1_24_0(args: ChangelogOptions, commits: ConventionalCommit[]): Promise { + return (await changelog(args, '1.23.0', '1.24.0', commits)).contents; } diff --git a/tools/cdk-release/test/conventional-commits.test.ts b/tools/cdk-release/test/conventional-commits.test.ts new file mode 100644 index 0000000000000..773f229849e5d --- /dev/null +++ b/tools/cdk-release/test/conventional-commits.test.ts @@ -0,0 +1,100 @@ +import * as crypto from 'crypto'; +import * as stream from 'stream'; +import { ConventionalCommit, filterCommits, getConventionalCommitsFromGitHistory } from '../lib/conventional-commits'; +import { ReleaseOptions } from '../lib/types'; + +// mock out Git interactions +jest.mock('git-raw-commits', () => { return jest.fn(); }); +// eslint-disable-next-line @typescript-eslint/no-require-imports +const gitRawCommits = require('git-raw-commits'); + +const args: ReleaseOptions = { + changelogFile: 'CHANGELOG.md', + dryRun: true, + silent: true, + includeDateInChangelog: false, + releaseAs: 'minor', + versionFile: 'version.json', +}; + +describe('getConventionalCommitsFromGitHistory', () => { + beforeEach(() => { + jest.resetAllMocks(); + }); + + test('makes it so that no Git commits are queried if Changelog generation is skipped', async () => { + const commits = await getConventionalCommitsFromGitHistory({ ...args, skip: { changelog: true } }, '3.9.2'); + + expect(commits).toHaveLength(0); + expect(gitRawCommits).not.toHaveBeenCalled(); + }); + + test('skips commits without types', async () => { + const commitMessages = ['some commit without a type', 'chore(cdk-release): do trivial stuff']; + gitRawCommits.mockImplementation(() => mockGitCommits(commitMessages)); + + const commits = await getConventionalCommitsFromGitHistory(args, '3.9.2'); + + expect(commits).toHaveLength(1); + }); +}); + +// NOTE - These test currently use real package.json data to determine package's stability. +describe('filterCommits', () => { + const commits: ConventionalCommit[] = [ + buildCommit({ + type: 'feat', + scope: 'scope', + subject: 'super important feature', + }), + buildCommit({ + type: 'fix', + scope: 'example-construct-library', // really hope we don't stabilize this one + subject: 'hairy bugfix', + notes: [ + { + title: 'BREAKING CHANGE', + text: 'this is a breaking change', + }, + ], + }), + ]; + + test('if stripExperimental is not set, returns original commits', async () => { + const filteredCommits = filterCommits(args, commits); + + expect(filteredCommits.length).toEqual(2); + }); + + test("skips experimental modules if requested, even with 'BREAKING CHANGES'", async () => { + const filteredCommits = filterCommits({ ...args, stripExperimentalChanges: true }, commits); + + expect(filteredCommits.length).toEqual(1); + expect(filteredCommits[0].subject).toEqual('super important feature'); + }); +}); + +function mockGitCommits(messages: string[]) { + const rStream = new stream.Readable(); + messages.forEach(msg => { + rStream.push([ + msg, '-hash-', crypto.createHash('sha256').update(msg).digest('hex'), + ].join('\n')); + }); + rStream.push(null); + return rStream; +} + +interface PartialCommit extends Partial { + readonly type: string; + readonly subject: string; +} + +function buildCommit(commit: PartialCommit): ConventionalCommit { + return { + notes: [], + references: [], + header: `${commit.type}${commit.scope ? '(' + commit.scope + ')' : ''}: ${commit.subject}`, + ...commit, + }; +} From 84a831ab804244d426321504fc0971d74f6181fd Mon Sep 17 00:00:00 2001 From: Jonathan Goldwasser Date: Sun, 15 Aug 2021 09:55:07 +0200 Subject: [PATCH 55/99] feat(assets): exclude "cdk.out" from docker assets (#16034) This PR is intended to cover a small bug that creates an infinite loop generating folders in cdk.out if the project root path is specified as the build directory. With this fix 'cdk.out' folder will be added as glob exclude pattern no matters what. More details in issue #14841 Original PR from @AlexGue Closes #14841 Closes #14842 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../test/integ.docker-asset.lit.expected.json | 2 +- .../aws-ecr-assets/lib/image-asset.ts | 9 +++- .../aws-ecr-assets/test/image-asset.test.ts | 24 ++++----- .../test/integ.assets-docker.expected.json | 2 +- .../integ.nested-stacks-docker.expected.json | 18 +++---- ...on-load-balanced-ecs-service.expected.json | 12 ++--- ...integ.scheduled-ecs-task.lit.expected.json | 6 +-- ...eg.alb-fargate-service-https.expected.json | 14 ++--- .../fargate/integ.asset-image.expected.json | 14 ++--- ...oad-balanced-fargate-service.expected.json | 36 ++++++------- ...e-processing-fargate-service.expected.json | 18 +++---- .../fargate/integ.executionrole.expected.json | 12 ++--- .../fargate/integ.l3-autocreate.expected.json | 12 ++--- .../fargate/integ.l3-vpconly.expected.json | 12 ++--- .../test/fargate/integ.l3.expected.json | 12 ++--- ...oad-balanced-fargate-service.expected.json | 12 ++--- ...ing-fargate-service-isolated.expected.json | 2 +- ...ssing-fargate-service-public.expected.json | 20 +++---- ...e-processing-fargate-service.expected.json | 14 ++--- ...g.scheduled-fargate-task.lit.expected.json | 42 +++++++-------- .../integ.special-listener.expected.json | 12 ++--- .../aws-ecs/test/container-definition.test.ts | 10 ++-- .../test/ec2/ec2-task-definition.test.ts | 2 +- .../integ.event-ec2-task.lit.expected.json | 2 +- .../integ.event-fargate-task.expected.json | 2 +- .../test/integ.function.expected.json | 18 +++---- .../test/integ.function.pipenv.expected.json | 54 +++++++++---------- .../test/integ.function.poetry.expected.json | 54 +++++++++---------- .../test/integ.function.project.expected.json | 36 ++++++------- .../test/integ.function.py38.expected.json | 18 +++---- ...unction.requirements.removed.expected.json | 18 +++---- .../test/integ.function.vpc.expected.json | 18 +++---- .../@aws-cdk/aws-lambda/test/code.test.ts | 2 +- .../test/integ.lambda.docker.expected.json | 2 +- .../test/bucket-deployment.test.ts | 6 +-- .../batch/integ.run-batch-job.expected.json | 2 +- .../test/batch/integ.submit-job.expected.json | 2 +- .../test/ecs/integ.ec2-run-task.expected.json | 2 +- .../test/ecs/integ.ec2-task.expected.json | 2 +- .../ecs/integ.fargate-run-task.expected.json | 2 +- .../test/ecs/integ.fargate-task.expected.json | 2 +- packages/@aws-cdk/core/lib/fs/fingerprint.ts | 4 -- .../core/test/fs/fs-fingerprint.test.ts | 30 ----------- 43 files changed, 282 insertions(+), 311 deletions(-) diff --git a/packages/@aws-cdk/aws-codebuild/test/integ.docker-asset.lit.expected.json b/packages/@aws-cdk/aws-codebuild/test/integ.docker-asset.lit.expected.json index 043ed7ee5642d..e8574d481b17f 100644 --- a/packages/@aws-cdk/aws-codebuild/test/integ.docker-asset.lit.expected.json +++ b/packages/@aws-cdk/aws-codebuild/test/integ.docker-asset.lit.expected.json @@ -146,7 +146,7 @@ { "Ref": "AWS::URLSuffix" }, - "/aws-cdk/assets:2564b8c8e3f9e82a6394872a4e555c4d0c06ab6f47b9aca360c22c9ed622487c" + "/aws-cdk/assets:4af07cfea2e112710555eb86325bfd4d7d4b97e4fa9f1bf6c053c72f992c7fe5" ] ] }, diff --git a/packages/@aws-cdk/aws-ecr-assets/lib/image-asset.ts b/packages/@aws-cdk/aws-ecr-assets/lib/image-asset.ts index 928fb286cb3a0..7003fc6931826 100644 --- a/packages/@aws-cdk/aws-ecr-assets/lib/image-asset.ts +++ b/packages/@aws-cdk/aws-ecr-assets/lib/image-asset.ts @@ -1,7 +1,7 @@ import * as fs from 'fs'; import * as path from 'path'; import * as ecr from '@aws-cdk/aws-ecr'; -import { Annotations, AssetStaging, FeatureFlags, FileFingerprintOptions, IgnoreMode, Stack, SymlinkFollowMode, Token } from '@aws-cdk/core'; +import { Annotations, AssetStaging, FeatureFlags, FileFingerprintOptions, IgnoreMode, Stack, SymlinkFollowMode, Token, Stage } from '@aws-cdk/core'; import * as cxapi from '@aws-cdk/cx-api'; import { Construct } from 'constructs'; @@ -62,6 +62,8 @@ export interface DockerImageAssetOptions extends FingerprintOptions, FileFingerp export interface DockerImageAssetProps extends DockerImageAssetOptions { /** * The directory where the Dockerfile is stored + * + * Any directory inside with a name that matches the CDK output folder (cdk.out by default) will be excluded from the asset */ readonly directory: string; } @@ -138,13 +140,16 @@ export class DockerImageAsset extends CoreConstruct implements IAsset { // Ensure the Dockerfile is included no matter what. exclude.push('!' + path.basename(file)); + // Ensure the cdk.out folder is not included to avoid infinite loops. + const cdkout = Stage.of(this)?.outdir ?? 'cdk.out'; + exclude.push(cdkout); if (props.repositoryName) { Annotations.of(this).addWarning('DockerImageAsset.repositoryName is deprecated. Override "core.Stack.addDockerImageAsset" to control asset locations'); } // include build context in "extra" so it will impact the hash - const extraHash: { [field: string]: any } = { }; + const extraHash: { [field: string]: any } = {}; if (props.extraHash) { extraHash.user = props.extraHash; } if (props.buildArgs) { extraHash.buildArgs = props.buildArgs; } if (props.target) { extraHash.target = props.target; } diff --git a/packages/@aws-cdk/aws-ecr-assets/test/image-asset.test.ts b/packages/@aws-cdk/aws-ecr-assets/test/image-asset.test.ts index 76dac04f66852..e156209458878 100644 --- a/packages/@aws-cdk/aws-ecr-assets/test/image-asset.test.ts +++ b/packages/@aws-cdk/aws-ecr-assets/test/image-asset.test.ts @@ -10,7 +10,7 @@ import { DockerImageAsset } from '../lib'; /* eslint-disable quote-props */ -const DEMO_IMAGE_ASSET_HASH = 'b2c69bfbfe983b634456574587443159b3b7258849856a118ad3d2772238f1a5'; +const DEMO_IMAGE_ASSET_HASH = '8c1d9ca9f5d37b1c4870c13a9f855301bb42c1848dbcdd5edc8fe2c6c7261d48'; const flags = { [cxapi.DOCKER_IGNORE_SUPPORT]: true }; @@ -29,11 +29,11 @@ describe('image asset', () => { expect(artifact.assets).toEqual([ { repositoryName: 'aws-cdk/assets', - imageTag: 'b2c69bfbfe983b634456574587443159b3b7258849856a118ad3d2772238f1a5', - id: 'b2c69bfbfe983b634456574587443159b3b7258849856a118ad3d2772238f1a5', + imageTag: '8c1d9ca9f5d37b1c4870c13a9f855301bb42c1848dbcdd5edc8fe2c6c7261d48', + id: '8c1d9ca9f5d37b1c4870c13a9f855301bb42c1848dbcdd5edc8fe2c6c7261d48', packaging: 'container-image', - path: 'asset.b2c69bfbfe983b634456574587443159b3b7258849856a118ad3d2772238f1a5', - sourceHash: 'b2c69bfbfe983b634456574587443159b3b7258849856a118ad3d2772238f1a5', + path: 'asset.8c1d9ca9f5d37b1c4870c13a9f855301bb42c1848dbcdd5edc8fe2c6c7261d48', + sourceHash: '8c1d9ca9f5d37b1c4870c13a9f855301bb42c1848dbcdd5edc8fe2c6c7261d48', }, ]); @@ -283,13 +283,13 @@ describe('image asset', () => { const asset6 = new DockerImageAsset(stack, 'Asset6', { directory, extraHash: 'random-extra' }); const asset7 = new DockerImageAsset(stack, 'Asset7', { directory, repositoryName: 'foo' }); - expect(asset1.assetHash).toEqual('ab01ecd4419f59e1ec0ac9e57a60dbb653be68a29af0223fa8cb24b4b747bc73'); - expect(asset2.assetHash).toEqual('7fb12f6148098e3f5c56c788a865d2af689125ead403b795fe6a262ec34384b3'); - expect(asset3.assetHash).toEqual('fc3b6d802ba198ba2ee55079dbef27682bcd1288d5849eb5bbd5cd69038359b3'); - expect(asset4.assetHash).toEqual('30439ea6dfeb4ddfd9175097286895c78393ef52a78c68f92db08abc4513cad6'); - expect(asset5.assetHash).toEqual('5775170880e26ba31799745241b90d4340c674bb3b1c01d758e416ee3f1c386f'); - expect(asset6.assetHash).toEqual('ba82fd351a4d3e3f5c5d948b9948e7e829badc3da90f97e00bb7724afbeacfd4'); - expect(asset7.assetHash).toEqual('26ec194928431cab6ec5af24ea9f01af2cf7b20e361128b07b2a7405d2951f95'); + expect(asset1.assetHash).toEqual('365b5d951fc5f725f78093a07e3e1cc7819b4cbe582ca71a4c344752c23bf409'); + expect(asset2.assetHash).toEqual('9560a36f786f317c5e1abb986b58269b2453ed1cab16c36fd9b76646c837078c'); + expect(asset3.assetHash).toEqual('4f4e16f5b0cfab21be4298a04b20f62f63cd91a649ef4620d6d3c948d29f3cb4'); + expect(asset4.assetHash).toEqual('72b961f96e358b8dad935719cfc2704c3d14a46434871825ac81e3b94caa4853'); + expect(asset5.assetHash).toEqual('c23d34b3a1dac5a80c42e8fa6c88a0ac697eb709a6f36ebdb6e36ee8c75edc75'); + expect(asset6.assetHash).toEqual('7e950a9b08c58d371c1658e04d377c0ec59d89a47fc245a86a50525b36a8949b'); + expect(asset7.assetHash).toEqual('313dd1f45a939b77fa8a4eb7780190aa7a20a40c95f503eca9e099186643d717'); }); }); diff --git a/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-docker.expected.json b/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-docker.expected.json index ad86ae9cd34da..e2aefa9185424 100644 --- a/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-docker.expected.json +++ b/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-docker.expected.json @@ -70,7 +70,7 @@ { "Ref": "AWS::URLSuffix" }, - "/aws-cdk/assets:b2c69bfbfe983b634456574587443159b3b7258849856a118ad3d2772238f1a5" + "/aws-cdk/assets:8c1d9ca9f5d37b1c4870c13a9f855301bb42c1848dbcdd5edc8fe2c6c7261d48" ] ] } diff --git a/packages/@aws-cdk/aws-ecr-assets/test/integ.nested-stacks-docker.expected.json b/packages/@aws-cdk/aws-ecr-assets/test/integ.nested-stacks-docker.expected.json index f86d0e5fea7ab..7e23b25796d4e 100644 --- a/packages/@aws-cdk/aws-ecr-assets/test/integ.nested-stacks-docker.expected.json +++ b/packages/@aws-cdk/aws-ecr-assets/test/integ.nested-stacks-docker.expected.json @@ -17,7 +17,7 @@ }, "/", { - "Ref": "AssetParameters41589ef1a760129e41441e85e58fe02db5f019ed532b8a4a20729f3245b0593bS3BucketFB15A731" + "Ref": "AssetParameters08bf71a5b9aa57c58cc7510137ed079260aac01394d01f4c29a9778ac890b816S3Bucket40925BAC" }, "/", { @@ -27,7 +27,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters41589ef1a760129e41441e85e58fe02db5f019ed532b8a4a20729f3245b0593bS3VersionKeyF38F9C9A" + "Ref": "AssetParameters08bf71a5b9aa57c58cc7510137ed079260aac01394d01f4c29a9778ac890b816S3VersionKey30F5671B" } ] } @@ -40,7 +40,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters41589ef1a760129e41441e85e58fe02db5f019ed532b8a4a20729f3245b0593bS3VersionKeyF38F9C9A" + "Ref": "AssetParameters08bf71a5b9aa57c58cc7510137ed079260aac01394d01f4c29a9778ac890b816S3VersionKey30F5671B" } ] } @@ -55,17 +55,17 @@ } }, "Parameters": { - "AssetParameters41589ef1a760129e41441e85e58fe02db5f019ed532b8a4a20729f3245b0593bS3BucketFB15A731": { + "AssetParameters08bf71a5b9aa57c58cc7510137ed079260aac01394d01f4c29a9778ac890b816S3Bucket40925BAC": { "Type": "String", - "Description": "S3 bucket for asset \"41589ef1a760129e41441e85e58fe02db5f019ed532b8a4a20729f3245b0593b\"" + "Description": "S3 bucket for asset \"08bf71a5b9aa57c58cc7510137ed079260aac01394d01f4c29a9778ac890b816\"" }, - "AssetParameters41589ef1a760129e41441e85e58fe02db5f019ed532b8a4a20729f3245b0593bS3VersionKeyF38F9C9A": { + "AssetParameters08bf71a5b9aa57c58cc7510137ed079260aac01394d01f4c29a9778ac890b816S3VersionKey30F5671B": { "Type": "String", - "Description": "S3 key for asset version \"41589ef1a760129e41441e85e58fe02db5f019ed532b8a4a20729f3245b0593b\"" + "Description": "S3 key for asset version \"08bf71a5b9aa57c58cc7510137ed079260aac01394d01f4c29a9778ac890b816\"" }, - "AssetParameters41589ef1a760129e41441e85e58fe02db5f019ed532b8a4a20729f3245b0593bArtifactHashEC633CC8": { + "AssetParameters08bf71a5b9aa57c58cc7510137ed079260aac01394d01f4c29a9778ac890b816ArtifactHash98F3F6F7": { "Type": "String", - "Description": "Artifact hash for asset \"41589ef1a760129e41441e85e58fe02db5f019ed532b8a4a20729f3245b0593b\"" + "Description": "Artifact hash for asset \"08bf71a5b9aa57c58cc7510137ed079260aac01394d01f4c29a9778ac890b816\"" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/integ.multiple-application-load-balanced-ecs-service.expected.json b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/integ.multiple-application-load-balanced-ecs-service.expected.json index 0412778adb2e8..5ce81fe00ad59 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/integ.multiple-application-load-balanced-ecs-service.expected.json +++ b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/integ.multiple-application-load-balanced-ecs-service.expected.json @@ -95,15 +95,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "Tags": [ { "Key": "Name", @@ -192,15 +192,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "Tags": [ { "Key": "Name", diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/integ.scheduled-ecs-task.lit.expected.json b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/integ.scheduled-ecs-task.lit.expected.json index e3afaddbeb7c6..e96ad6a2bbad7 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/integ.scheduled-ecs-task.lit.expected.json +++ b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/integ.scheduled-ecs-task.lit.expected.json @@ -95,15 +95,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "Tags": [ { "Key": "Name", diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-https.expected.json b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-https.expected.json index 5a67a969707c8..76713f6d4ef64 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-https.expected.json +++ b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.alb-fargate-service-https.expected.json @@ -95,15 +95,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "Tags": [ { "Key": "Name", @@ -192,15 +192,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "Tags": [ { "Key": "Name", @@ -766,4 +766,4 @@ } } } -} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.asset-image.expected.json b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.asset-image.expected.json index 4fdde5753fdf6..dc589f5d6c48f 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.asset-image.expected.json +++ b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.asset-image.expected.json @@ -95,15 +95,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "Tags": [ { "Key": "Name", @@ -192,15 +192,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "Tags": [ { "Key": "Name", @@ -497,7 +497,7 @@ { "Ref": "AWS::URLSuffix" }, - "/aws-cdk/assets:b2c69bfbfe983b634456574587443159b3b7258849856a118ad3d2772238f1a5" + "/aws-cdk/assets:8c1d9ca9f5d37b1c4870c13a9f855301bb42c1848dbcdd5edc8fe2c6c7261d48" ] ] }, diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.circuit-breaker-load-balanced-fargate-service.expected.json b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.circuit-breaker-load-balanced-fargate-service.expected.json index 19af7964b18be..24b4bb012e384 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.circuit-breaker-load-balanced-fargate-service.expected.json +++ b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.circuit-breaker-load-balanced-fargate-service.expected.json @@ -95,15 +95,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "Tags": [ { "Key": "Name", @@ -192,15 +192,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "Tags": [ { "Key": "Name", @@ -684,19 +684,19 @@ }, "myServiceServiceURL1258C56B": { "Value": { - "Fn::Join":[ - "", - [ - "http://", - { - "Fn::GetAtt": [ - "myServiceLB168895E1", - "DNSName" - ] - } - ] + "Fn::Join": [ + "", + [ + "http://", + { + "Fn::GetAtt": [ + "myServiceLB168895E1", + "DNSName" + ] + } + ] ] } } } -} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.circuit-breaker-queue-processing-fargate-service.expected.json b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.circuit-breaker-queue-processing-fargate-service.expected.json index 3b8fad89fcf97..74e53d75a507a 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.circuit-breaker-queue-processing-fargate-service.expected.json +++ b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.circuit-breaker-queue-processing-fargate-service.expected.json @@ -95,15 +95,15 @@ "VPCPublicSubnet1NATGatewayE0556630": { "Type": "AWS::EC2::NatGateway", "Properties": { + "SubnetId": { + "Ref": "VPCPublicSubnet1SubnetB4246D30" + }, "AllocationId": { "Fn::GetAtt": [ "VPCPublicSubnet1EIP6AD938E8", "AllocationId" ] }, - "SubnetId": { - "Ref": "VPCPublicSubnet1SubnetB4246D30" - }, "Tags": [ { "Key": "Name", @@ -192,15 +192,15 @@ "VPCPublicSubnet2NATGateway3C070193": { "Type": "AWS::EC2::NatGateway", "Properties": { + "SubnetId": { + "Ref": "VPCPublicSubnet2Subnet74179F39" + }, "AllocationId": { "Fn::GetAtt": [ "VPCPublicSubnet2EIP4947BC00", "AllocationId" ] }, - "SubnetId": { - "Ref": "VPCPublicSubnet2Subnet74179F39" - }, "Tags": [ { "Key": "Name", @@ -460,7 +460,7 @@ { "Ref": "AWS::URLSuffix" }, - "/aws-cdk/assets:3a8ba3ad06ed212b075efa3157fb407649c5996812bc64eeb5209e220aab4be5" + "/aws-cdk/assets:d6b024485c22795b5f5379edcd5cd6485f5bec6eb80bd072b20526f8eb2e0c64" ] ] }, @@ -590,7 +590,7 @@ "Cluster": { "Ref": "EcsDefaultClusterMnL3mNNYNVPC9C1EC7A3" }, - "DeploymentConfiguration": { + "DeploymentConfiguration": { "DeploymentCircuitBreaker": { "Enable": true, "Rollback": true @@ -845,4 +845,4 @@ } } } -} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.executionrole.expected.json b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.executionrole.expected.json index 93c7a7307a6ee..b3921b410fabd 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.executionrole.expected.json +++ b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.executionrole.expected.json @@ -95,15 +95,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "Tags": [ { "Key": "Name", @@ -192,15 +192,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "Tags": [ { "Key": "Name", diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.l3-autocreate.expected.json b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.l3-autocreate.expected.json index 778523d6bc6df..61b34b57938cd 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.l3-autocreate.expected.json +++ b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.l3-autocreate.expected.json @@ -405,15 +405,15 @@ "EcsDefaultClusterMnL3mNNYNVpcPublicSubnet1NATGateway5E3732C1": { "Type": "AWS::EC2::NatGateway", "Properties": { + "SubnetId": { + "Ref": "EcsDefaultClusterMnL3mNNYNVpcPublicSubnet1Subnet3C273B99" + }, "AllocationId": { "Fn::GetAtt": [ "EcsDefaultClusterMnL3mNNYNVpcPublicSubnet1EIP8704DB2F", "AllocationId" ] }, - "SubnetId": { - "Ref": "EcsDefaultClusterMnL3mNNYNVpcPublicSubnet1Subnet3C273B99" - }, "Tags": [ { "Key": "Name", @@ -502,15 +502,15 @@ "EcsDefaultClusterMnL3mNNYNVpcPublicSubnet2NATGateway4C855E00": { "Type": "AWS::EC2::NatGateway", "Properties": { + "SubnetId": { + "Ref": "EcsDefaultClusterMnL3mNNYNVpcPublicSubnet2Subnet95FF715A" + }, "AllocationId": { "Fn::GetAtt": [ "EcsDefaultClusterMnL3mNNYNVpcPublicSubnet2EIPF0764873", "AllocationId" ] }, - "SubnetId": { - "Ref": "EcsDefaultClusterMnL3mNNYNVpcPublicSubnet2Subnet95FF715A" - }, "Tags": [ { "Key": "Name", diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.l3-vpconly.expected.json b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.l3-vpconly.expected.json index f221c99ccf4fc..d63db295a39cc 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.l3-vpconly.expected.json +++ b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.l3-vpconly.expected.json @@ -95,15 +95,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "Tags": [ { "Key": "Name", @@ -192,15 +192,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "Tags": [ { "Key": "Name", diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.l3.expected.json b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.l3.expected.json index efd340e79b5cf..886e4a35dcf63 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.l3.expected.json +++ b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.l3.expected.json @@ -95,15 +95,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "Tags": [ { "Key": "Name", @@ -192,15 +192,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "Tags": [ { "Key": "Name", diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.multiple-network-load-balanced-fargate-service.expected.json b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.multiple-network-load-balanced-fargate-service.expected.json index 2cdd6991792e8..643ff38905d69 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.multiple-network-load-balanced-fargate-service.expected.json +++ b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.multiple-network-load-balanced-fargate-service.expected.json @@ -95,15 +95,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "Tags": [ { "Key": "Name", @@ -192,15 +192,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "Tags": [ { "Key": "Name", diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.queue-processing-fargate-service-isolated.expected.json b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.queue-processing-fargate-service-isolated.expected.json index 6124fba473584..2414ce426a716 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.queue-processing-fargate-service-isolated.expected.json +++ b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.queue-processing-fargate-service-isolated.expected.json @@ -769,7 +769,7 @@ { "Ref": "AWS::URLSuffix" }, - "/aws-cdk/assets:3a8ba3ad06ed212b075efa3157fb407649c5996812bc64eeb5209e220aab4be5" + "/aws-cdk/assets:d6b024485c22795b5f5379edcd5cd6485f5bec6eb80bd072b20526f8eb2e0c64" ] ] }, diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.queue-processing-fargate-service-public.expected.json b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.queue-processing-fargate-service-public.expected.json index de873260aa209..ae18adac13bbf 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.queue-processing-fargate-service-public.expected.json +++ b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.queue-processing-fargate-service-public.expected.json @@ -95,15 +95,15 @@ "VPCPublicSubnet1NATGatewayE0556630": { "Type": "AWS::EC2::NatGateway", "Properties": { + "SubnetId": { + "Ref": "VPCPublicSubnet1SubnetB4246D30" + }, "AllocationId": { "Fn::GetAtt": [ "VPCPublicSubnet1EIP6AD938E8", "AllocationId" ] }, - "SubnetId": { - "Ref": "VPCPublicSubnet1SubnetB4246D30" - }, "Tags": [ { "Key": "Name", @@ -192,15 +192,15 @@ "VPCPublicSubnet2NATGateway3C070193": { "Type": "AWS::EC2::NatGateway", "Properties": { + "SubnetId": { + "Ref": "VPCPublicSubnet2Subnet74179F39" + }, "AllocationId": { "Fn::GetAtt": [ "VPCPublicSubnet2EIP4947BC00", "AllocationId" ] }, - "SubnetId": { - "Ref": "VPCPublicSubnet2Subnet74179F39" - }, "Tags": [ { "Key": "Name", @@ -289,15 +289,15 @@ "VPCPublicSubnet3NATGatewayD3048F5C": { "Type": "AWS::EC2::NatGateway", "Properties": { + "SubnetId": { + "Ref": "VPCPublicSubnet3Subnet631C5E25" + }, "AllocationId": { "Fn::GetAtt": [ "VPCPublicSubnet3EIPAD4BC883", "AllocationId" ] }, - "SubnetId": { - "Ref": "VPCPublicSubnet3Subnet631C5E25" - }, "Tags": [ { "Key": "Name", @@ -619,7 +619,7 @@ { "Ref": "AWS::URLSuffix" }, - "/aws-cdk/assets:3a8ba3ad06ed212b075efa3157fb407649c5996812bc64eeb5209e220aab4be5" + "/aws-cdk/assets:d6b024485c22795b5f5379edcd5cd6485f5bec6eb80bd072b20526f8eb2e0c64" ] ] }, diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.queue-processing-fargate-service.expected.json b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.queue-processing-fargate-service.expected.json index 6fbcb79ecfa00..f43e4e5aa4e0b 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.queue-processing-fargate-service.expected.json +++ b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.queue-processing-fargate-service.expected.json @@ -95,15 +95,15 @@ "VPCPublicSubnet1NATGatewayE0556630": { "Type": "AWS::EC2::NatGateway", "Properties": { + "SubnetId": { + "Ref": "VPCPublicSubnet1SubnetB4246D30" + }, "AllocationId": { "Fn::GetAtt": [ "VPCPublicSubnet1EIP6AD938E8", "AllocationId" ] }, - "SubnetId": { - "Ref": "VPCPublicSubnet1SubnetB4246D30" - }, "Tags": [ { "Key": "Name", @@ -192,15 +192,15 @@ "VPCPublicSubnet2NATGateway3C070193": { "Type": "AWS::EC2::NatGateway", "Properties": { + "SubnetId": { + "Ref": "VPCPublicSubnet2Subnet74179F39" + }, "AllocationId": { "Fn::GetAtt": [ "VPCPublicSubnet2EIP4947BC00", "AllocationId" ] }, - "SubnetId": { - "Ref": "VPCPublicSubnet2Subnet74179F39" - }, "Tags": [ { "Key": "Name", @@ -460,7 +460,7 @@ { "Ref": "AWS::URLSuffix" }, - "/aws-cdk/assets:3a8ba3ad06ed212b075efa3157fb407649c5996812bc64eeb5209e220aab4be5" + "/aws-cdk/assets:d6b024485c22795b5f5379edcd5cd6485f5bec6eb80bd072b20526f8eb2e0c64" ] ] }, diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.scheduled-fargate-task.lit.expected.json b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.scheduled-fargate-task.lit.expected.json index 8ffdd12ce4046..e580c83502abd 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.scheduled-fargate-task.lit.expected.json +++ b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.scheduled-fargate-task.lit.expected.json @@ -95,15 +95,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "Tags": [ { "Key": "Name", @@ -293,7 +293,7 @@ { "Ref": "AWS::URLSuffix" }, - "/aws-cdk/assets:b2c69bfbfe983b634456574587443159b3b7258849856a118ad3d2772238f1a5" + "/aws-cdk/assets:8c1d9ca9f5d37b1c4870c13a9f855301bb42c1848dbcdd5edc8fe2c6c7261d48" ] ] }, @@ -417,22 +417,6 @@ ] } }, - "ScheduledFargateTaskScheduledTaskDefSecurityGroupE075BC19": { - "Type": "AWS::EC2::SecurityGroup", - "Properties": { - "GroupDescription": "aws-fargate-integ/ScheduledFargateTask/ScheduledTaskDef/SecurityGroup", - "SecurityGroupEgress": [ - { - "CidrIp": "0.0.0.0/0", - "Description": "Allow all outbound traffic by default", - "IpProtocol": "-1" - } - ], - "VpcId": { - "Ref": "Vpc8378EB38" - } - } - }, "ScheduledFargateTaskScheduledTaskDefEventsRole6CE19522": { "Type": "AWS::IAM::Role", "Properties": { @@ -502,6 +486,22 @@ } ] } + }, + "ScheduledFargateTaskScheduledTaskDefSecurityGroupE075BC19": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "aws-fargate-integ/ScheduledFargateTask/ScheduledTaskDef/SecurityGroup", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } } } -} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.special-listener.expected.json b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.special-listener.expected.json index 5075f6511573b..7fa930b16d66d 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.special-listener.expected.json +++ b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/integ.special-listener.expected.json @@ -95,15 +95,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "Tags": [ { "Key": "Name", @@ -192,15 +192,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "Tags": [ { "Key": "Name", diff --git a/packages/@aws-cdk/aws-ecs/test/container-definition.test.ts b/packages/@aws-cdk/aws-ecs/test/container-definition.test.ts index 3a8671cdf22f7..b5c60ae1c5c0c 100644 --- a/packages/@aws-cdk/aws-ecs/test/container-definition.test.ts +++ b/packages/@aws-cdk/aws-ecs/test/container-definition.test.ts @@ -1892,7 +1892,7 @@ describe('container definition', () => { { Ref: 'AWS::Region' }, '.', { Ref: 'AWS::URLSuffix' }, - '/aws-cdk/assets:b2c69bfbfe983b634456574587443159b3b7258849856a118ad3d2772238f1a5', + '/aws-cdk/assets:8c1d9ca9f5d37b1c4870c13a9f855301bb42c1848dbcdd5edc8fe2c6c7261d48', ], ], }, @@ -1948,11 +1948,11 @@ describe('container definition', () => { const asm = app.synth(); expect(asm.getStackArtifact(stack.artifactId).assets[0]).toEqual({ repositoryName: 'aws-cdk/assets', - imageTag: 'ce3419d7c5d2d44e2789b13ccbd2d54ddf682557669f68bcee753231f5f1c0a5', - id: 'ce3419d7c5d2d44e2789b13ccbd2d54ddf682557669f68bcee753231f5f1c0a5', + imageTag: '9d913132f812bc1ad436aeb5a51f9216c5776b8079318c1883ad2f79f0ef1a4b', + id: '9d913132f812bc1ad436aeb5a51f9216c5776b8079318c1883ad2f79f0ef1a4b', packaging: 'container-image', - path: 'asset.ce3419d7c5d2d44e2789b13ccbd2d54ddf682557669f68bcee753231f5f1c0a5', - sourceHash: 'ce3419d7c5d2d44e2789b13ccbd2d54ddf682557669f68bcee753231f5f1c0a5', + path: 'asset.9d913132f812bc1ad436aeb5a51f9216c5776b8079318c1883ad2f79f0ef1a4b', + sourceHash: '9d913132f812bc1ad436aeb5a51f9216c5776b8079318c1883ad2f79f0ef1a4b', target: 'build-target', file: 'index.py', }); diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/ec2-task-definition.test.ts b/packages/@aws-cdk/aws-ecs/test/ec2/ec2-task-definition.test.ts index 06f891868feb8..793dff5c3b97b 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/ec2-task-definition.test.ts +++ b/packages/@aws-cdk/aws-ecs/test/ec2/ec2-task-definition.test.ts @@ -759,7 +759,7 @@ describe('ec2 task definition', () => { { Ref: 'AWS::URLSuffix', }, - '/aws-cdk/assets:b2c69bfbfe983b634456574587443159b3b7258849856a118ad3d2772238f1a5', + '/aws-cdk/assets:8c1d9ca9f5d37b1c4870c13a9f855301bb42c1848dbcdd5edc8fe2c6c7261d48', ], ], }, diff --git a/packages/@aws-cdk/aws-events-targets/test/ecs/integ.event-ec2-task.lit.expected.json b/packages/@aws-cdk/aws-events-targets/test/ecs/integ.event-ec2-task.lit.expected.json index dbdb415e57e63..a03a81e7255da 100644 --- a/packages/@aws-cdk/aws-events-targets/test/ecs/integ.event-ec2-task.lit.expected.json +++ b/packages/@aws-cdk/aws-events-targets/test/ecs/integ.event-ec2-task.lit.expected.json @@ -714,7 +714,7 @@ { "Ref": "AWS::URLSuffix" }, - "/aws-cdk/assets:709fd91ba301f9b460ce1066dbc339f6a29bd4a07609ff98fb0e0faa475b650d" + "/aws-cdk/assets:3fc39b45c4fd074ceef5d0f8528b74fa7fe6e8fa0aa4a6ffe7fb5e016cf8dc04" ] ] }, diff --git a/packages/@aws-cdk/aws-events-targets/test/ecs/integ.event-fargate-task.expected.json b/packages/@aws-cdk/aws-events-targets/test/ecs/integ.event-fargate-task.expected.json index 123578699510c..40e42600e5413 100644 --- a/packages/@aws-cdk/aws-events-targets/test/ecs/integ.event-fargate-task.expected.json +++ b/packages/@aws-cdk/aws-events-targets/test/ecs/integ.event-fargate-task.expected.json @@ -237,7 +237,7 @@ { "Ref": "AWS::URLSuffix" }, - "/aws-cdk/assets:709fd91ba301f9b460ce1066dbc339f6a29bd4a07609ff98fb0e0faa475b650d" + "/aws-cdk/assets:3fc39b45c4fd074ceef5d0f8528b74fa7fe6e8fa0aa4a6ffe7fb5e016cf8dc04" ] ] }, diff --git a/packages/@aws-cdk/aws-lambda-python/test/integ.function.expected.json b/packages/@aws-cdk/aws-lambda-python/test/integ.function.expected.json index 6ed7f497e9ee0..e48b9c2e0ad92 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/integ.function.expected.json +++ b/packages/@aws-cdk/aws-lambda-python/test/integ.function.expected.json @@ -36,7 +36,7 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParameters5b8ff93384af5b488025e13b274c2dd894e474a810f1a406af1aeb4edbba6a3cS3Bucket5B146B0B" + "Ref": "AssetParametersfc7bfbf72c74b955f7bc25d2bb123c0eeec9557cda17481146d51672768907b2S3Bucket383ED51E" }, "S3Key": { "Fn::Join": [ @@ -49,7 +49,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters5b8ff93384af5b488025e13b274c2dd894e474a810f1a406af1aeb4edbba6a3cS3VersionKeyC0C8A627" + "Ref": "AssetParametersfc7bfbf72c74b955f7bc25d2bb123c0eeec9557cda17481146d51672768907b2S3VersionKeyA520554C" } ] } @@ -62,7 +62,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters5b8ff93384af5b488025e13b274c2dd894e474a810f1a406af1aeb4edbba6a3cS3VersionKeyC0C8A627" + "Ref": "AssetParametersfc7bfbf72c74b955f7bc25d2bb123c0eeec9557cda17481146d51672768907b2S3VersionKeyA520554C" } ] } @@ -87,17 +87,17 @@ } }, "Parameters": { - "AssetParameters5b8ff93384af5b488025e13b274c2dd894e474a810f1a406af1aeb4edbba6a3cS3Bucket5B146B0B": { + "AssetParametersfc7bfbf72c74b955f7bc25d2bb123c0eeec9557cda17481146d51672768907b2S3Bucket383ED51E": { "Type": "String", - "Description": "S3 bucket for asset \"5b8ff93384af5b488025e13b274c2dd894e474a810f1a406af1aeb4edbba6a3c\"" + "Description": "S3 bucket for asset \"fc7bfbf72c74b955f7bc25d2bb123c0eeec9557cda17481146d51672768907b2\"" }, - "AssetParameters5b8ff93384af5b488025e13b274c2dd894e474a810f1a406af1aeb4edbba6a3cS3VersionKeyC0C8A627": { + "AssetParametersfc7bfbf72c74b955f7bc25d2bb123c0eeec9557cda17481146d51672768907b2S3VersionKeyA520554C": { "Type": "String", - "Description": "S3 key for asset version \"5b8ff93384af5b488025e13b274c2dd894e474a810f1a406af1aeb4edbba6a3c\"" + "Description": "S3 key for asset version \"fc7bfbf72c74b955f7bc25d2bb123c0eeec9557cda17481146d51672768907b2\"" }, - "AssetParameters5b8ff93384af5b488025e13b274c2dd894e474a810f1a406af1aeb4edbba6a3cArtifactHashB6A7723E": { + "AssetParametersfc7bfbf72c74b955f7bc25d2bb123c0eeec9557cda17481146d51672768907b2ArtifactHashB863A6ED": { "Type": "String", - "Description": "Artifact hash for asset \"5b8ff93384af5b488025e13b274c2dd894e474a810f1a406af1aeb4edbba6a3c\"" + "Description": "Artifact hash for asset \"fc7bfbf72c74b955f7bc25d2bb123c0eeec9557cda17481146d51672768907b2\"" } }, "Outputs": { diff --git a/packages/@aws-cdk/aws-lambda-python/test/integ.function.pipenv.expected.json b/packages/@aws-cdk/aws-lambda-python/test/integ.function.pipenv.expected.json index 6766584717e3d..2b64c7f650529 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/integ.function.pipenv.expected.json +++ b/packages/@aws-cdk/aws-lambda-python/test/integ.function.pipenv.expected.json @@ -36,7 +36,7 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParameters1a697367cf267ba8a72f772b462c503dd5a6e7bcdd8cb353d89604e9d18802eeS3BucketADC4FFB3" + "Ref": "AssetParameters2f7cfa4e9b9d7c70c9af6f1820a340c116a1e139fcac4dde381f541331ba5e46S3Bucket84213B6F" }, "S3Key": { "Fn::Join": [ @@ -49,7 +49,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters1a697367cf267ba8a72f772b462c503dd5a6e7bcdd8cb353d89604e9d18802eeS3VersionKey784D7689" + "Ref": "AssetParameters2f7cfa4e9b9d7c70c9af6f1820a340c116a1e139fcac4dde381f541331ba5e46S3VersionKeyC495D2FD" } ] } @@ -62,7 +62,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters1a697367cf267ba8a72f772b462c503dd5a6e7bcdd8cb353d89604e9d18802eeS3VersionKey784D7689" + "Ref": "AssetParameters2f7cfa4e9b9d7c70c9af6f1820a340c116a1e139fcac4dde381f541331ba5e46S3VersionKeyC495D2FD" } ] } @@ -121,7 +121,7 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParameters8eb49c58869010ec84a5b407369006e9cb5fdf9667d8609638d6fa59265fc3ecS3Bucket5B706387" + "Ref": "AssetParameters7157876e6cb8bea4bc3b6e272edab8a4d202a0be6bdcecf33b95008fbacc2335S3Bucket1E236877" }, "S3Key": { "Fn::Join": [ @@ -134,7 +134,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters8eb49c58869010ec84a5b407369006e9cb5fdf9667d8609638d6fa59265fc3ecS3VersionKey48CF3C03" + "Ref": "AssetParameters7157876e6cb8bea4bc3b6e272edab8a4d202a0be6bdcecf33b95008fbacc2335S3VersionKeyD0D6DBBF" } ] } @@ -147,7 +147,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters8eb49c58869010ec84a5b407369006e9cb5fdf9667d8609638d6fa59265fc3ecS3VersionKey48CF3C03" + "Ref": "AssetParameters7157876e6cb8bea4bc3b6e272edab8a4d202a0be6bdcecf33b95008fbacc2335S3VersionKeyD0D6DBBF" } ] } @@ -206,7 +206,7 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParameters992750d379dbbe94426dbd352099e3344b9edcfd098a56691b53eafaeb227b10S3Bucket9E9FE80F" + "Ref": "AssetParameters1d8b9cdbaaf7c36dc94604966b3b1f6fb2a972fbddc5cfd62fef7a7a8efd5888S3BucketC4EB0B32" }, "S3Key": { "Fn::Join": [ @@ -219,7 +219,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters992750d379dbbe94426dbd352099e3344b9edcfd098a56691b53eafaeb227b10S3VersionKeyFFAE128A" + "Ref": "AssetParameters1d8b9cdbaaf7c36dc94604966b3b1f6fb2a972fbddc5cfd62fef7a7a8efd5888S3VersionKeyB8755D2B" } ] } @@ -232,7 +232,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters992750d379dbbe94426dbd352099e3344b9edcfd098a56691b53eafaeb227b10S3VersionKeyFFAE128A" + "Ref": "AssetParameters1d8b9cdbaaf7c36dc94604966b3b1f6fb2a972fbddc5cfd62fef7a7a8efd5888S3VersionKeyB8755D2B" } ] } @@ -257,41 +257,41 @@ } }, "Parameters": { - "AssetParameters1a697367cf267ba8a72f772b462c503dd5a6e7bcdd8cb353d89604e9d18802eeS3BucketADC4FFB3": { + "AssetParameters2f7cfa4e9b9d7c70c9af6f1820a340c116a1e139fcac4dde381f541331ba5e46S3Bucket84213B6F": { "Type": "String", - "Description": "S3 bucket for asset \"1a697367cf267ba8a72f772b462c503dd5a6e7bcdd8cb353d89604e9d18802ee\"" + "Description": "S3 bucket for asset \"2f7cfa4e9b9d7c70c9af6f1820a340c116a1e139fcac4dde381f541331ba5e46\"" }, - "AssetParameters1a697367cf267ba8a72f772b462c503dd5a6e7bcdd8cb353d89604e9d18802eeS3VersionKey784D7689": { + "AssetParameters2f7cfa4e9b9d7c70c9af6f1820a340c116a1e139fcac4dde381f541331ba5e46S3VersionKeyC495D2FD": { "Type": "String", - "Description": "S3 key for asset version \"1a697367cf267ba8a72f772b462c503dd5a6e7bcdd8cb353d89604e9d18802ee\"" + "Description": "S3 key for asset version \"2f7cfa4e9b9d7c70c9af6f1820a340c116a1e139fcac4dde381f541331ba5e46\"" }, - "AssetParameters1a697367cf267ba8a72f772b462c503dd5a6e7bcdd8cb353d89604e9d18802eeArtifactHash76BB0F66": { + "AssetParameters2f7cfa4e9b9d7c70c9af6f1820a340c116a1e139fcac4dde381f541331ba5e46ArtifactHashBBA8D438": { "Type": "String", - "Description": "Artifact hash for asset \"1a697367cf267ba8a72f772b462c503dd5a6e7bcdd8cb353d89604e9d18802ee\"" + "Description": "Artifact hash for asset \"2f7cfa4e9b9d7c70c9af6f1820a340c116a1e139fcac4dde381f541331ba5e46\"" }, - "AssetParameters8eb49c58869010ec84a5b407369006e9cb5fdf9667d8609638d6fa59265fc3ecS3Bucket5B706387": { + "AssetParameters7157876e6cb8bea4bc3b6e272edab8a4d202a0be6bdcecf33b95008fbacc2335S3Bucket1E236877": { "Type": "String", - "Description": "S3 bucket for asset \"8eb49c58869010ec84a5b407369006e9cb5fdf9667d8609638d6fa59265fc3ec\"" + "Description": "S3 bucket for asset \"7157876e6cb8bea4bc3b6e272edab8a4d202a0be6bdcecf33b95008fbacc2335\"" }, - "AssetParameters8eb49c58869010ec84a5b407369006e9cb5fdf9667d8609638d6fa59265fc3ecS3VersionKey48CF3C03": { + "AssetParameters7157876e6cb8bea4bc3b6e272edab8a4d202a0be6bdcecf33b95008fbacc2335S3VersionKeyD0D6DBBF": { "Type": "String", - "Description": "S3 key for asset version \"8eb49c58869010ec84a5b407369006e9cb5fdf9667d8609638d6fa59265fc3ec\"" + "Description": "S3 key for asset version \"7157876e6cb8bea4bc3b6e272edab8a4d202a0be6bdcecf33b95008fbacc2335\"" }, - "AssetParameters8eb49c58869010ec84a5b407369006e9cb5fdf9667d8609638d6fa59265fc3ecArtifactHashD17A32B8": { + "AssetParameters7157876e6cb8bea4bc3b6e272edab8a4d202a0be6bdcecf33b95008fbacc2335ArtifactHash3C95A517": { "Type": "String", - "Description": "Artifact hash for asset \"8eb49c58869010ec84a5b407369006e9cb5fdf9667d8609638d6fa59265fc3ec\"" + "Description": "Artifact hash for asset \"7157876e6cb8bea4bc3b6e272edab8a4d202a0be6bdcecf33b95008fbacc2335\"" }, - "AssetParameters992750d379dbbe94426dbd352099e3344b9edcfd098a56691b53eafaeb227b10S3Bucket9E9FE80F": { + "AssetParameters1d8b9cdbaaf7c36dc94604966b3b1f6fb2a972fbddc5cfd62fef7a7a8efd5888S3BucketC4EB0B32": { "Type": "String", - "Description": "S3 bucket for asset \"992750d379dbbe94426dbd352099e3344b9edcfd098a56691b53eafaeb227b10\"" + "Description": "S3 bucket for asset \"1d8b9cdbaaf7c36dc94604966b3b1f6fb2a972fbddc5cfd62fef7a7a8efd5888\"" }, - "AssetParameters992750d379dbbe94426dbd352099e3344b9edcfd098a56691b53eafaeb227b10S3VersionKeyFFAE128A": { + "AssetParameters1d8b9cdbaaf7c36dc94604966b3b1f6fb2a972fbddc5cfd62fef7a7a8efd5888S3VersionKeyB8755D2B": { "Type": "String", - "Description": "S3 key for asset version \"992750d379dbbe94426dbd352099e3344b9edcfd098a56691b53eafaeb227b10\"" + "Description": "S3 key for asset version \"1d8b9cdbaaf7c36dc94604966b3b1f6fb2a972fbddc5cfd62fef7a7a8efd5888\"" }, - "AssetParameters992750d379dbbe94426dbd352099e3344b9edcfd098a56691b53eafaeb227b10ArtifactHashCAE919EE": { + "AssetParameters1d8b9cdbaaf7c36dc94604966b3b1f6fb2a972fbddc5cfd62fef7a7a8efd5888ArtifactHash46327689": { "Type": "String", - "Description": "Artifact hash for asset \"992750d379dbbe94426dbd352099e3344b9edcfd098a56691b53eafaeb227b10\"" + "Description": "Artifact hash for asset \"1d8b9cdbaaf7c36dc94604966b3b1f6fb2a972fbddc5cfd62fef7a7a8efd5888\"" } }, "Outputs": { diff --git a/packages/@aws-cdk/aws-lambda-python/test/integ.function.poetry.expected.json b/packages/@aws-cdk/aws-lambda-python/test/integ.function.poetry.expected.json index 9b5e2aba2f075..6e305994bd801 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/integ.function.poetry.expected.json +++ b/packages/@aws-cdk/aws-lambda-python/test/integ.function.poetry.expected.json @@ -36,7 +36,7 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParameters75ddddb47479a218a15821c4afd818c51d26c8340cbbe49f6eca0b7b802e3923S3Bucket1A5FBFC5" + "Ref": "AssetParameters5e3cce416e15bd5ddb77e3ffc9fa3d8f5eac73b0db8c1db7ae3d7f6197c0ecb3S3Bucket666BD1AB" }, "S3Key": { "Fn::Join": [ @@ -49,7 +49,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters75ddddb47479a218a15821c4afd818c51d26c8340cbbe49f6eca0b7b802e3923S3VersionKey67EF2E81" + "Ref": "AssetParameters5e3cce416e15bd5ddb77e3ffc9fa3d8f5eac73b0db8c1db7ae3d7f6197c0ecb3S3VersionKeyA31B2B4A" } ] } @@ -62,7 +62,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters75ddddb47479a218a15821c4afd818c51d26c8340cbbe49f6eca0b7b802e3923S3VersionKey67EF2E81" + "Ref": "AssetParameters5e3cce416e15bd5ddb77e3ffc9fa3d8f5eac73b0db8c1db7ae3d7f6197c0ecb3S3VersionKeyA31B2B4A" } ] } @@ -121,7 +121,7 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParameters929810b8fc5030a232173abd44cd2d54f4735eece74ac8cf1c34e7b9dd9161a3S3Bucket0ECFE319" + "Ref": "AssetParameters12a01ed3f74f4bee61a4c67c4ca842472390f70c4b8bdd2cceb033abe16d7764S3BucketFA6FBCEA" }, "S3Key": { "Fn::Join": [ @@ -134,7 +134,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters929810b8fc5030a232173abd44cd2d54f4735eece74ac8cf1c34e7b9dd9161a3S3VersionKeyA373952D" + "Ref": "AssetParameters12a01ed3f74f4bee61a4c67c4ca842472390f70c4b8bdd2cceb033abe16d7764S3VersionKey55B7E38F" } ] } @@ -147,7 +147,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters929810b8fc5030a232173abd44cd2d54f4735eece74ac8cf1c34e7b9dd9161a3S3VersionKeyA373952D" + "Ref": "AssetParameters12a01ed3f74f4bee61a4c67c4ca842472390f70c4b8bdd2cceb033abe16d7764S3VersionKey55B7E38F" } ] } @@ -206,7 +206,7 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParameters5a08158e59eb223498febeed20bc4005c3e81534f6c47bd7d8a2079f256f25d0S3BucketDB10730C" + "Ref": "AssetParameters22d2bf270f7c8f776322a3bad39e8c690cbaa95a442ae2fec419b259df5632f0S3BucketC2F9D441" }, "S3Key": { "Fn::Join": [ @@ -219,7 +219,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters5a08158e59eb223498febeed20bc4005c3e81534f6c47bd7d8a2079f256f25d0S3VersionKeyE7AE1114" + "Ref": "AssetParameters22d2bf270f7c8f776322a3bad39e8c690cbaa95a442ae2fec419b259df5632f0S3VersionKeyB53188B8" } ] } @@ -232,7 +232,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters5a08158e59eb223498febeed20bc4005c3e81534f6c47bd7d8a2079f256f25d0S3VersionKeyE7AE1114" + "Ref": "AssetParameters22d2bf270f7c8f776322a3bad39e8c690cbaa95a442ae2fec419b259df5632f0S3VersionKeyB53188B8" } ] } @@ -257,41 +257,41 @@ } }, "Parameters": { - "AssetParameters75ddddb47479a218a15821c4afd818c51d26c8340cbbe49f6eca0b7b802e3923S3Bucket1A5FBFC5": { + "AssetParameters5e3cce416e15bd5ddb77e3ffc9fa3d8f5eac73b0db8c1db7ae3d7f6197c0ecb3S3Bucket666BD1AB": { "Type": "String", - "Description": "S3 bucket for asset \"75ddddb47479a218a15821c4afd818c51d26c8340cbbe49f6eca0b7b802e3923\"" + "Description": "S3 bucket for asset \"5e3cce416e15bd5ddb77e3ffc9fa3d8f5eac73b0db8c1db7ae3d7f6197c0ecb3\"" }, - "AssetParameters75ddddb47479a218a15821c4afd818c51d26c8340cbbe49f6eca0b7b802e3923S3VersionKey67EF2E81": { + "AssetParameters5e3cce416e15bd5ddb77e3ffc9fa3d8f5eac73b0db8c1db7ae3d7f6197c0ecb3S3VersionKeyA31B2B4A": { "Type": "String", - "Description": "S3 key for asset version \"75ddddb47479a218a15821c4afd818c51d26c8340cbbe49f6eca0b7b802e3923\"" + "Description": "S3 key for asset version \"5e3cce416e15bd5ddb77e3ffc9fa3d8f5eac73b0db8c1db7ae3d7f6197c0ecb3\"" }, - "AssetParameters75ddddb47479a218a15821c4afd818c51d26c8340cbbe49f6eca0b7b802e3923ArtifactHash122807F1": { + "AssetParameters5e3cce416e15bd5ddb77e3ffc9fa3d8f5eac73b0db8c1db7ae3d7f6197c0ecb3ArtifactHash8BEEBB0C": { "Type": "String", - "Description": "Artifact hash for asset \"75ddddb47479a218a15821c4afd818c51d26c8340cbbe49f6eca0b7b802e3923\"" + "Description": "Artifact hash for asset \"5e3cce416e15bd5ddb77e3ffc9fa3d8f5eac73b0db8c1db7ae3d7f6197c0ecb3\"" }, - "AssetParameters929810b8fc5030a232173abd44cd2d54f4735eece74ac8cf1c34e7b9dd9161a3S3Bucket0ECFE319": { + "AssetParameters12a01ed3f74f4bee61a4c67c4ca842472390f70c4b8bdd2cceb033abe16d7764S3BucketFA6FBCEA": { "Type": "String", - "Description": "S3 bucket for asset \"929810b8fc5030a232173abd44cd2d54f4735eece74ac8cf1c34e7b9dd9161a3\"" + "Description": "S3 bucket for asset \"12a01ed3f74f4bee61a4c67c4ca842472390f70c4b8bdd2cceb033abe16d7764\"" }, - "AssetParameters929810b8fc5030a232173abd44cd2d54f4735eece74ac8cf1c34e7b9dd9161a3S3VersionKeyA373952D": { + "AssetParameters12a01ed3f74f4bee61a4c67c4ca842472390f70c4b8bdd2cceb033abe16d7764S3VersionKey55B7E38F": { "Type": "String", - "Description": "S3 key for asset version \"929810b8fc5030a232173abd44cd2d54f4735eece74ac8cf1c34e7b9dd9161a3\"" + "Description": "S3 key for asset version \"12a01ed3f74f4bee61a4c67c4ca842472390f70c4b8bdd2cceb033abe16d7764\"" }, - "AssetParameters929810b8fc5030a232173abd44cd2d54f4735eece74ac8cf1c34e7b9dd9161a3ArtifactHash196D379D": { + "AssetParameters12a01ed3f74f4bee61a4c67c4ca842472390f70c4b8bdd2cceb033abe16d7764ArtifactHashF654A092": { "Type": "String", - "Description": "Artifact hash for asset \"929810b8fc5030a232173abd44cd2d54f4735eece74ac8cf1c34e7b9dd9161a3\"" + "Description": "Artifact hash for asset \"12a01ed3f74f4bee61a4c67c4ca842472390f70c4b8bdd2cceb033abe16d7764\"" }, - "AssetParameters5a08158e59eb223498febeed20bc4005c3e81534f6c47bd7d8a2079f256f25d0S3BucketDB10730C": { + "AssetParameters22d2bf270f7c8f776322a3bad39e8c690cbaa95a442ae2fec419b259df5632f0S3BucketC2F9D441": { "Type": "String", - "Description": "S3 bucket for asset \"5a08158e59eb223498febeed20bc4005c3e81534f6c47bd7d8a2079f256f25d0\"" + "Description": "S3 bucket for asset \"22d2bf270f7c8f776322a3bad39e8c690cbaa95a442ae2fec419b259df5632f0\"" }, - "AssetParameters5a08158e59eb223498febeed20bc4005c3e81534f6c47bd7d8a2079f256f25d0S3VersionKeyE7AE1114": { + "AssetParameters22d2bf270f7c8f776322a3bad39e8c690cbaa95a442ae2fec419b259df5632f0S3VersionKeyB53188B8": { "Type": "String", - "Description": "S3 key for asset version \"5a08158e59eb223498febeed20bc4005c3e81534f6c47bd7d8a2079f256f25d0\"" + "Description": "S3 key for asset version \"22d2bf270f7c8f776322a3bad39e8c690cbaa95a442ae2fec419b259df5632f0\"" }, - "AssetParameters5a08158e59eb223498febeed20bc4005c3e81534f6c47bd7d8a2079f256f25d0ArtifactHashF5CC0D13": { + "AssetParameters22d2bf270f7c8f776322a3bad39e8c690cbaa95a442ae2fec419b259df5632f0ArtifactHash63D0E537": { "Type": "String", - "Description": "Artifact hash for asset \"5a08158e59eb223498febeed20bc4005c3e81534f6c47bd7d8a2079f256f25d0\"" + "Description": "Artifact hash for asset \"22d2bf270f7c8f776322a3bad39e8c690cbaa95a442ae2fec419b259df5632f0\"" } }, "Outputs": { diff --git a/packages/@aws-cdk/aws-lambda-python/test/integ.function.project.expected.json b/packages/@aws-cdk/aws-lambda-python/test/integ.function.project.expected.json index 68838ca5bb2f0..0e27a16d95cac 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/integ.function.project.expected.json +++ b/packages/@aws-cdk/aws-lambda-python/test/integ.function.project.expected.json @@ -5,7 +5,7 @@ "Properties": { "Content": { "S3Bucket": { - "Ref": "AssetParameters66cf329731482a1903f36e710c64efa07dd7fc320739e9a1c0d915fe3cfa3aa0S3BucketF123FCA1" + "Ref": "AssetParameterse6dde8a412edfc6d967ce7244c803ebd6523ebc30b4c5562919028c6edf8f137S3Bucket3B546DC9" }, "S3Key": { "Fn::Join": [ @@ -18,7 +18,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters66cf329731482a1903f36e710c64efa07dd7fc320739e9a1c0d915fe3cfa3aa0S3VersionKey6FABFCA9" + "Ref": "AssetParameterse6dde8a412edfc6d967ce7244c803ebd6523ebc30b4c5562919028c6edf8f137S3VersionKeyAB88DB86" } ] } @@ -31,7 +31,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters66cf329731482a1903f36e710c64efa07dd7fc320739e9a1c0d915fe3cfa3aa0S3VersionKey6FABFCA9" + "Ref": "AssetParameterse6dde8a412edfc6d967ce7244c803ebd6523ebc30b4c5562919028c6edf8f137S3VersionKeyAB88DB86" } ] } @@ -82,7 +82,7 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParameters2355f1daf8ff0670c3287d5f2b9bf5061dce576b20f03dddb2f016ba7a203c86S3Bucket03A296A2" + "Ref": "AssetParameters4364b96840104e125d2c47166f8bada01e9a636f3c23d4cddf681c685d494856S3Bucket091DB419" }, "S3Key": { "Fn::Join": [ @@ -95,7 +95,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters2355f1daf8ff0670c3287d5f2b9bf5061dce576b20f03dddb2f016ba7a203c86S3VersionKey90B885D0" + "Ref": "AssetParameters4364b96840104e125d2c47166f8bada01e9a636f3c23d4cddf681c685d494856S3VersionKey635CFDCB" } ] } @@ -108,7 +108,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters2355f1daf8ff0670c3287d5f2b9bf5061dce576b20f03dddb2f016ba7a203c86S3VersionKey90B885D0" + "Ref": "AssetParameters4364b96840104e125d2c47166f8bada01e9a636f3c23d4cddf681c685d494856S3VersionKey635CFDCB" } ] } @@ -138,29 +138,29 @@ } }, "Parameters": { - "AssetParameters66cf329731482a1903f36e710c64efa07dd7fc320739e9a1c0d915fe3cfa3aa0S3BucketF123FCA1": { + "AssetParameterse6dde8a412edfc6d967ce7244c803ebd6523ebc30b4c5562919028c6edf8f137S3Bucket3B546DC9": { "Type": "String", - "Description": "S3 bucket for asset \"66cf329731482a1903f36e710c64efa07dd7fc320739e9a1c0d915fe3cfa3aa0\"" + "Description": "S3 bucket for asset \"e6dde8a412edfc6d967ce7244c803ebd6523ebc30b4c5562919028c6edf8f137\"" }, - "AssetParameters66cf329731482a1903f36e710c64efa07dd7fc320739e9a1c0d915fe3cfa3aa0S3VersionKey6FABFCA9": { + "AssetParameterse6dde8a412edfc6d967ce7244c803ebd6523ebc30b4c5562919028c6edf8f137S3VersionKeyAB88DB86": { "Type": "String", - "Description": "S3 key for asset version \"66cf329731482a1903f36e710c64efa07dd7fc320739e9a1c0d915fe3cfa3aa0\"" + "Description": "S3 key for asset version \"e6dde8a412edfc6d967ce7244c803ebd6523ebc30b4c5562919028c6edf8f137\"" }, - "AssetParameters66cf329731482a1903f36e710c64efa07dd7fc320739e9a1c0d915fe3cfa3aa0ArtifactHash0384F1C8": { + "AssetParameterse6dde8a412edfc6d967ce7244c803ebd6523ebc30b4c5562919028c6edf8f137ArtifactHashE6CFFE39": { "Type": "String", - "Description": "Artifact hash for asset \"66cf329731482a1903f36e710c64efa07dd7fc320739e9a1c0d915fe3cfa3aa0\"" + "Description": "Artifact hash for asset \"e6dde8a412edfc6d967ce7244c803ebd6523ebc30b4c5562919028c6edf8f137\"" }, - "AssetParameters2355f1daf8ff0670c3287d5f2b9bf5061dce576b20f03dddb2f016ba7a203c86S3Bucket03A296A2": { + "AssetParameters4364b96840104e125d2c47166f8bada01e9a636f3c23d4cddf681c685d494856S3Bucket091DB419": { "Type": "String", - "Description": "S3 bucket for asset \"2355f1daf8ff0670c3287d5f2b9bf5061dce576b20f03dddb2f016ba7a203c86\"" + "Description": "S3 bucket for asset \"4364b96840104e125d2c47166f8bada01e9a636f3c23d4cddf681c685d494856\"" }, - "AssetParameters2355f1daf8ff0670c3287d5f2b9bf5061dce576b20f03dddb2f016ba7a203c86S3VersionKey90B885D0": { + "AssetParameters4364b96840104e125d2c47166f8bada01e9a636f3c23d4cddf681c685d494856S3VersionKey635CFDCB": { "Type": "String", - "Description": "S3 key for asset version \"2355f1daf8ff0670c3287d5f2b9bf5061dce576b20f03dddb2f016ba7a203c86\"" + "Description": "S3 key for asset version \"4364b96840104e125d2c47166f8bada01e9a636f3c23d4cddf681c685d494856\"" }, - "AssetParameters2355f1daf8ff0670c3287d5f2b9bf5061dce576b20f03dddb2f016ba7a203c86ArtifactHash937218E0": { + "AssetParameters4364b96840104e125d2c47166f8bada01e9a636f3c23d4cddf681c685d494856ArtifactHashB70D4FAA": { "Type": "String", - "Description": "Artifact hash for asset \"2355f1daf8ff0670c3287d5f2b9bf5061dce576b20f03dddb2f016ba7a203c86\"" + "Description": "Artifact hash for asset \"4364b96840104e125d2c47166f8bada01e9a636f3c23d4cddf681c685d494856\"" } }, "Outputs": { diff --git a/packages/@aws-cdk/aws-lambda-python/test/integ.function.py38.expected.json b/packages/@aws-cdk/aws-lambda-python/test/integ.function.py38.expected.json index df601bc92acd9..41d154158be8a 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/integ.function.py38.expected.json +++ b/packages/@aws-cdk/aws-lambda-python/test/integ.function.py38.expected.json @@ -36,7 +36,7 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParameters29cd01a5fe529da311cdec40c163fb1c04b1b3dc8caadff0ea696fb6e63610feS3Bucket38F00249" + "Ref": "AssetParametersc3efdfac6089b6c2ee8dce3aac310085091823af614fce0fb5e42799930f526dS3Bucket2D6AE647" }, "S3Key": { "Fn::Join": [ @@ -49,7 +49,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters29cd01a5fe529da311cdec40c163fb1c04b1b3dc8caadff0ea696fb6e63610feS3VersionKey60957E7E" + "Ref": "AssetParametersc3efdfac6089b6c2ee8dce3aac310085091823af614fce0fb5e42799930f526dS3VersionKeyF8CA384F" } ] } @@ -62,7 +62,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters29cd01a5fe529da311cdec40c163fb1c04b1b3dc8caadff0ea696fb6e63610feS3VersionKey60957E7E" + "Ref": "AssetParametersc3efdfac6089b6c2ee8dce3aac310085091823af614fce0fb5e42799930f526dS3VersionKeyF8CA384F" } ] } @@ -87,17 +87,17 @@ } }, "Parameters": { - "AssetParameters29cd01a5fe529da311cdec40c163fb1c04b1b3dc8caadff0ea696fb6e63610feS3Bucket38F00249": { + "AssetParametersc3efdfac6089b6c2ee8dce3aac310085091823af614fce0fb5e42799930f526dS3Bucket2D6AE647": { "Type": "String", - "Description": "S3 bucket for asset \"29cd01a5fe529da311cdec40c163fb1c04b1b3dc8caadff0ea696fb6e63610fe\"" + "Description": "S3 bucket for asset \"c3efdfac6089b6c2ee8dce3aac310085091823af614fce0fb5e42799930f526d\"" }, - "AssetParameters29cd01a5fe529da311cdec40c163fb1c04b1b3dc8caadff0ea696fb6e63610feS3VersionKey60957E7E": { + "AssetParametersc3efdfac6089b6c2ee8dce3aac310085091823af614fce0fb5e42799930f526dS3VersionKeyF8CA384F": { "Type": "String", - "Description": "S3 key for asset version \"29cd01a5fe529da311cdec40c163fb1c04b1b3dc8caadff0ea696fb6e63610fe\"" + "Description": "S3 key for asset version \"c3efdfac6089b6c2ee8dce3aac310085091823af614fce0fb5e42799930f526d\"" }, - "AssetParameters29cd01a5fe529da311cdec40c163fb1c04b1b3dc8caadff0ea696fb6e63610feArtifactHash29C18922": { + "AssetParametersc3efdfac6089b6c2ee8dce3aac310085091823af614fce0fb5e42799930f526dArtifactHash8B92B092": { "Type": "String", - "Description": "Artifact hash for asset \"29cd01a5fe529da311cdec40c163fb1c04b1b3dc8caadff0ea696fb6e63610fe\"" + "Description": "Artifact hash for asset \"c3efdfac6089b6c2ee8dce3aac310085091823af614fce0fb5e42799930f526d\"" } }, "Outputs": { diff --git a/packages/@aws-cdk/aws-lambda-python/test/integ.function.requirements.removed.expected.json b/packages/@aws-cdk/aws-lambda-python/test/integ.function.requirements.removed.expected.json index 131ca14b5e5c9..eb7fc23f146c9 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/integ.function.requirements.removed.expected.json +++ b/packages/@aws-cdk/aws-lambda-python/test/integ.function.requirements.removed.expected.json @@ -36,7 +36,7 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParameterse6fadc5eeabdb3ea6ecd571e8ec74e7943cd34cd4ec9d46d0506a200e6163a93S3BucketBA49B914" + "Ref": "AssetParametersdf0fb94d329926d232a09d16076d3eee0200e6a945f32ff69a97ba787087d563S3Bucket1ACC1E9E" }, "S3Key": { "Fn::Join": [ @@ -49,7 +49,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameterse6fadc5eeabdb3ea6ecd571e8ec74e7943cd34cd4ec9d46d0506a200e6163a93S3VersionKey74688352" + "Ref": "AssetParametersdf0fb94d329926d232a09d16076d3eee0200e6a945f32ff69a97ba787087d563S3VersionKeyEA6BC868" } ] } @@ -62,7 +62,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameterse6fadc5eeabdb3ea6ecd571e8ec74e7943cd34cd4ec9d46d0506a200e6163a93S3VersionKey74688352" + "Ref": "AssetParametersdf0fb94d329926d232a09d16076d3eee0200e6a945f32ff69a97ba787087d563S3VersionKeyEA6BC868" } ] } @@ -87,17 +87,17 @@ } }, "Parameters": { - "AssetParameterse6fadc5eeabdb3ea6ecd571e8ec74e7943cd34cd4ec9d46d0506a200e6163a93S3BucketBA49B914": { + "AssetParametersdf0fb94d329926d232a09d16076d3eee0200e6a945f32ff69a97ba787087d563S3Bucket1ACC1E9E": { "Type": "String", - "Description": "S3 bucket for asset \"e6fadc5eeabdb3ea6ecd571e8ec74e7943cd34cd4ec9d46d0506a200e6163a93\"" + "Description": "S3 bucket for asset \"df0fb94d329926d232a09d16076d3eee0200e6a945f32ff69a97ba787087d563\"" }, - "AssetParameterse6fadc5eeabdb3ea6ecd571e8ec74e7943cd34cd4ec9d46d0506a200e6163a93S3VersionKey74688352": { + "AssetParametersdf0fb94d329926d232a09d16076d3eee0200e6a945f32ff69a97ba787087d563S3VersionKeyEA6BC868": { "Type": "String", - "Description": "S3 key for asset version \"e6fadc5eeabdb3ea6ecd571e8ec74e7943cd34cd4ec9d46d0506a200e6163a93\"" + "Description": "S3 key for asset version \"df0fb94d329926d232a09d16076d3eee0200e6a945f32ff69a97ba787087d563\"" }, - "AssetParameterse6fadc5eeabdb3ea6ecd571e8ec74e7943cd34cd4ec9d46d0506a200e6163a93ArtifactHash6870D06D": { + "AssetParametersdf0fb94d329926d232a09d16076d3eee0200e6a945f32ff69a97ba787087d563ArtifactHash887C8025": { "Type": "String", - "Description": "Artifact hash for asset \"e6fadc5eeabdb3ea6ecd571e8ec74e7943cd34cd4ec9d46d0506a200e6163a93\"" + "Description": "Artifact hash for asset \"df0fb94d329926d232a09d16076d3eee0200e6a945f32ff69a97ba787087d563\"" } }, "Outputs": { diff --git a/packages/@aws-cdk/aws-lambda-python/test/integ.function.vpc.expected.json b/packages/@aws-cdk/aws-lambda-python/test/integ.function.vpc.expected.json index 1efa22d57d44f..99705bba839a3 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/integ.function.vpc.expected.json +++ b/packages/@aws-cdk/aws-lambda-python/test/integ.function.vpc.expected.json @@ -296,7 +296,7 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParameters5b8ff93384af5b488025e13b274c2dd894e474a810f1a406af1aeb4edbba6a3cS3Bucket5B146B0B" + "Ref": "AssetParametersfc7bfbf72c74b955f7bc25d2bb123c0eeec9557cda17481146d51672768907b2S3Bucket383ED51E" }, "S3Key": { "Fn::Join": [ @@ -309,7 +309,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters5b8ff93384af5b488025e13b274c2dd894e474a810f1a406af1aeb4edbba6a3cS3VersionKeyC0C8A627" + "Ref": "AssetParametersfc7bfbf72c74b955f7bc25d2bb123c0eeec9557cda17481146d51672768907b2S3VersionKeyA520554C" } ] } @@ -322,7 +322,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters5b8ff93384af5b488025e13b274c2dd894e474a810f1a406af1aeb4edbba6a3cS3VersionKeyC0C8A627" + "Ref": "AssetParametersfc7bfbf72c74b955f7bc25d2bb123c0eeec9557cda17481146d51672768907b2S3VersionKeyA520554C" } ] } @@ -368,17 +368,17 @@ } }, "Parameters": { - "AssetParameters5b8ff93384af5b488025e13b274c2dd894e474a810f1a406af1aeb4edbba6a3cS3Bucket5B146B0B": { + "AssetParametersfc7bfbf72c74b955f7bc25d2bb123c0eeec9557cda17481146d51672768907b2S3Bucket383ED51E": { "Type": "String", - "Description": "S3 bucket for asset \"5b8ff93384af5b488025e13b274c2dd894e474a810f1a406af1aeb4edbba6a3c\"" + "Description": "S3 bucket for asset \"fc7bfbf72c74b955f7bc25d2bb123c0eeec9557cda17481146d51672768907b2\"" }, - "AssetParameters5b8ff93384af5b488025e13b274c2dd894e474a810f1a406af1aeb4edbba6a3cS3VersionKeyC0C8A627": { + "AssetParametersfc7bfbf72c74b955f7bc25d2bb123c0eeec9557cda17481146d51672768907b2S3VersionKeyA520554C": { "Type": "String", - "Description": "S3 key for asset version \"5b8ff93384af5b488025e13b274c2dd894e474a810f1a406af1aeb4edbba6a3c\"" + "Description": "S3 key for asset version \"fc7bfbf72c74b955f7bc25d2bb123c0eeec9557cda17481146d51672768907b2\"" }, - "AssetParameters5b8ff93384af5b488025e13b274c2dd894e474a810f1a406af1aeb4edbba6a3cArtifactHashB6A7723E": { + "AssetParametersfc7bfbf72c74b955f7bc25d2bb123c0eeec9557cda17481146d51672768907b2ArtifactHashB863A6ED": { "Type": "String", - "Description": "Artifact hash for asset \"5b8ff93384af5b488025e13b274c2dd894e474a810f1a406af1aeb4edbba6a3c\"" + "Description": "Artifact hash for asset \"fc7bfbf72c74b955f7bc25d2bb123c0eeec9557cda17481146d51672768907b2\"" } }, "Outputs": { diff --git a/packages/@aws-cdk/aws-lambda/test/code.test.ts b/packages/@aws-cdk/aws-lambda/test/code.test.ts index 958dfe9fc7a56..ec9732baa9ea7 100644 --- a/packages/@aws-cdk/aws-lambda/test/code.test.ts +++ b/packages/@aws-cdk/aws-lambda/test/code.test.ts @@ -298,7 +298,7 @@ describe('code', () => { { Ref: 'AWS::Region' }, '.', { Ref: 'AWS::URLSuffix' }, - '/aws-cdk/assets:e8a944aeb0a08ba4811503d9c138e514b112dadca84daa5b4608e4a0fb80a0c9', + '/aws-cdk/assets:f0fe8a410cb4b860a25f6f3e09237abf69cd38ab59f9ef2441597c75f598c634', ]], }, }, diff --git a/packages/@aws-cdk/aws-lambda/test/integ.lambda.docker.expected.json b/packages/@aws-cdk/aws-lambda/test/integ.lambda.docker.expected.json index bfa1d27910000..6affea556c9d9 100644 --- a/packages/@aws-cdk/aws-lambda/test/integ.lambda.docker.expected.json +++ b/packages/@aws-cdk/aws-lambda/test/integ.lambda.docker.expected.json @@ -50,7 +50,7 @@ { "Ref": "AWS::URLSuffix" }, - "/aws-cdk/assets:e8a944aeb0a08ba4811503d9c138e514b112dadca84daa5b4608e4a0fb80a0c9" + "/aws-cdk/assets:f0fe8a410cb4b860a25f6f3e09237abf69cd38ab59f9ef2441597c75f598c634" ] ] } diff --git a/packages/@aws-cdk/aws-s3-deployment/test/bucket-deployment.test.ts b/packages/@aws-cdk/aws-s3-deployment/test/bucket-deployment.test.ts index 893c5ae03b35f..19af404bbfa7b 100644 --- a/packages/@aws-cdk/aws-s3-deployment/test/bucket-deployment.test.ts +++ b/packages/@aws-cdk/aws-s3-deployment/test/bucket-deployment.test.ts @@ -225,7 +225,7 @@ test('honors passed asset options', () => { ], }, SourceBucketNames: [{ - Ref: 'AssetParameters86f8bca4f28a0bcafef0a98fe4cea25c0071aca27401e35cfaecd06313373bcaS3BucketB41AE64D', + Ref: 'AssetParametersa4d0f1d9c73aa029fd432ca3e640d46745f490023a241d0127f3351773a8938eS3Bucket02009982', }], SourceObjectKeys: [{ 'Fn::Join': [ @@ -238,7 +238,7 @@ test('honors passed asset options', () => { 'Fn::Split': [ '||', { - Ref: 'AssetParameters86f8bca4f28a0bcafef0a98fe4cea25c0071aca27401e35cfaecd06313373bcaS3VersionKeyF3CBA38F', + Ref: 'AssetParametersa4d0f1d9c73aa029fd432ca3e640d46745f490023a241d0127f3351773a8938eS3VersionKey07726F25', }, ], }, @@ -251,7 +251,7 @@ test('honors passed asset options', () => { 'Fn::Split': [ '||', { - Ref: 'AssetParameters86f8bca4f28a0bcafef0a98fe4cea25c0071aca27401e35cfaecd06313373bcaS3VersionKeyF3CBA38F', + Ref: 'AssetParametersa4d0f1d9c73aa029fd432ca3e640d46745f490023a241d0127f3351773a8938eS3VersionKey07726F25', }, ], }, diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/batch/integ.run-batch-job.expected.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/batch/integ.run-batch-job.expected.json index 252eeef05dea4..97eea60b24dcc 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/batch/integ.run-batch-job.expected.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/batch/integ.run-batch-job.expected.json @@ -869,7 +869,7 @@ { "Ref": "AWS::URLSuffix" }, - "/aws-cdk/assets:10112d0d2c68a9d76297acc4623b1af0d5e9fd11b2226eee455e09c6fcf1b776" + "/aws-cdk/assets:3691f011ed75cf0fd05152b8fae3d684323da3da9eaf3be68cba18cb9def2562" ] ] }, diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/batch/integ.submit-job.expected.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/batch/integ.submit-job.expected.json index 6b45fb3889e9b..2026e45ae3c4e 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/batch/integ.submit-job.expected.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/batch/integ.submit-job.expected.json @@ -869,7 +869,7 @@ { "Ref": "AWS::URLSuffix" }, - "/aws-cdk/assets:10112d0d2c68a9d76297acc4623b1af0d5e9fd11b2226eee455e09c6fcf1b776" + "/aws-cdk/assets:3691f011ed75cf0fd05152b8fae3d684323da3da9eaf3be68cba18cb9def2562" ] ] }, diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/integ.ec2-run-task.expected.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/integ.ec2-run-task.expected.json index c67a1adcd7dd7..737459f21b68a 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/integ.ec2-run-task.expected.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/integ.ec2-run-task.expected.json @@ -501,7 +501,7 @@ { "Ref": "AWS::URLSuffix" }, - "/aws-cdk/assets:709fd91ba301f9b460ce1066dbc339f6a29bd4a07609ff98fb0e0faa475b650d" + "/aws-cdk/assets:3fc39b45c4fd074ceef5d0f8528b74fa7fe6e8fa0aa4a6ffe7fb5e016cf8dc04" ] ] }, diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/integ.ec2-task.expected.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/integ.ec2-task.expected.json index 891777171b73c..bfd53444e81b3 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/integ.ec2-task.expected.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/integ.ec2-task.expected.json @@ -501,7 +501,7 @@ { "Ref": "AWS::URLSuffix" }, - "/aws-cdk/assets:709fd91ba301f9b460ce1066dbc339f6a29bd4a07609ff98fb0e0faa475b650d" + "/aws-cdk/assets:3fc39b45c4fd074ceef5d0f8528b74fa7fe6e8fa0aa4a6ffe7fb5e016cf8dc04" ] ] }, diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/integ.fargate-run-task.expected.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/integ.fargate-run-task.expected.json index a2d79417c61df..ab2cb02fd8d0c 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/integ.fargate-run-task.expected.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/integ.fargate-run-task.expected.json @@ -34,7 +34,7 @@ { "Ref": "AWS::URLSuffix" }, - "/aws-cdk/assets:709fd91ba301f9b460ce1066dbc339f6a29bd4a07609ff98fb0e0faa475b650d" + "/aws-cdk/assets:3fc39b45c4fd074ceef5d0f8528b74fa7fe6e8fa0aa4a6ffe7fb5e016cf8dc04" ] ] }, diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/integ.fargate-task.expected.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/integ.fargate-task.expected.json index 00682997b2a31..84c678d4c2806 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/integ.fargate-task.expected.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/integ.fargate-task.expected.json @@ -34,7 +34,7 @@ { "Ref": "AWS::URLSuffix" }, - "/aws-cdk/assets:709fd91ba301f9b460ce1066dbc339f6a29bd4a07609ff98fb0e0faa475b650d" + "/aws-cdk/assets:3fc39b45c4fd074ceef5d0f8528b74fa7fe6e8fa0aa4a6ffe7fb5e016cf8dc04" ] ] }, diff --git a/packages/@aws-cdk/core/lib/fs/fingerprint.ts b/packages/@aws-cdk/core/lib/fs/fingerprint.ts index f7513d89743be..50a81fd53982d 100644 --- a/packages/@aws-cdk/core/lib/fs/fingerprint.ts +++ b/packages/@aws-cdk/core/lib/fs/fingerprint.ts @@ -30,10 +30,6 @@ export function fingerprint(fileOrDirectory: string, options: FingerprintOptions const rootDirectory = fs.statSync(fileOrDirectory).isDirectory() ? fileOrDirectory : path.dirname(fileOrDirectory); - const exclude = options.exclude || []; - if (exclude.length) { - _hashField(hash, 'options.exclude', JSON.stringify(exclude)); - } const ignoreMode = options.ignoreMode || IgnoreMode.GLOB; if (ignoreMode != IgnoreMode.GLOB) { diff --git a/packages/@aws-cdk/core/test/fs/fs-fingerprint.test.ts b/packages/@aws-cdk/core/test/fs/fs-fingerprint.test.ts index ad5bf9cf14160..6a589b3ba159e 100644 --- a/packages/@aws-cdk/core/test/fs/fs-fingerprint.test.ts +++ b/packages/@aws-cdk/core/test/fs/fs-fingerprint.test.ts @@ -155,34 +155,4 @@ nodeunitShim({ test.done(); }, }, - exclude: { - 'encodes exclude patterns'(test: Test) { - // GIVEN - const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'fingerprint-tests')); - const options1 = { path: dir, exclude: ['**', '!file.py'], sourcePath: dir }; - const options2 = { path: dir, exclude: ['**', '!otherfile.py'], sourcePath: dir }; - - // WHEN - const f1 = FileSystem.fingerprint(dir, options1); - const f2 = FileSystem.fingerprint(dir, options2); - - // THEN - test.notDeepEqual(f1, f2); - test.done(); - }, - 'considers negated exclude patterns for fingerprint'(test: Test) { - // GIVEN - const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'fingerprint-tests')); - const options = { path: dir, exclude: ['**', '!file.txt'], sourcePath: dir }; - - // WHEN - const f1 = FileSystem.fingerprint(dir, options); - fs.writeFileSync(path.join(dir, 'file.txt'), 'data'); - const f2 = FileSystem.fingerprint(dir, options); - - // THEN - test.notDeepEqual(f1, f2); - test.done(); - }, - }, }); From 86d0286a54e72959240870bcd00431aaf72344fd Mon Sep 17 00:00:00 2001 From: AWS CDK Team Date: Tue, 17 Aug 2021 18:27:43 +0000 Subject: [PATCH 56/99] chore(release): 1.119.0 --- CHANGELOG.md | 19 +++++++++++++++++++ version.v1.json | 4 ++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 83cca9c58cb2a..9b911ea37c753 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,25 @@ 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.119.0](https://github.com/aws/aws-cdk/compare/v1.118.0...v1.119.0) (2021-08-17) + + +### Features + +* **apigatewayv2:** http api - domain url for a stage ([#15973](https://github.com/aws/aws-cdk/issues/15973)) ([bb5d587](https://github.com/aws/aws-cdk/commit/bb5d5874098b4b1047a29b6697e5e3a65f349ff0)), closes [#15801](https://github.com/aws/aws-cdk/issues/15801) +* **assets:** exclude "cdk.out" from docker assets ([#16034](https://github.com/aws/aws-cdk/issues/16034)) ([84a831a](https://github.com/aws/aws-cdk/commit/84a831ab804244d426321504fc0971d74f6181fd)), closes [#14841](https://github.com/aws/aws-cdk/issues/14841) [#14841](https://github.com/aws/aws-cdk/issues/14841) [#14842](https://github.com/aws/aws-cdk/issues/14842) +* **aws-apigateway:** import existing usage plan ([#15771](https://github.com/aws/aws-cdk/issues/15771)) ([97fc290](https://github.com/aws/aws-cdk/commit/97fc29032c05edb7914c48efee0124be0126a5c4)), closes [#12677](https://github.com/aws/aws-cdk/issues/12677) +* **cfnspec:** cloudformation spec v39.9.0 ([#15987](https://github.com/aws/aws-cdk/issues/15987)) ([e0d6181](https://github.com/aws/aws-cdk/commit/e0d61810ab78f7cab1af53bce82c60790a814f71)) + + +### Bug Fixes + +* **core:** asset bundling fails for non-existent user ([#15313](https://github.com/aws/aws-cdk/issues/15313)) ([bf5882f](https://github.com/aws/aws-cdk/commit/bf5882f8def0676bbfaee7c2ff4fab6bf39df281)), closes [#15415](https://github.com/aws/aws-cdk/issues/15415) [#15415](https://github.com/aws/aws-cdk/issues/15415) +* **ec2:** opaque error when insufficient NAT EIPs are configured ([#16040](https://github.com/aws/aws-cdk/issues/16040)) ([a308cac](https://github.com/aws/aws-cdk/commit/a308cacf1fc48e24311caec246b768ffe6ae9153)), closes [#16039](https://github.com/aws/aws-cdk/issues/16039) +* **events:** cross-account event targets that have a Role are broken ([#15717](https://github.com/aws/aws-cdk/issues/15717)) ([f570c94](https://github.com/aws/aws-cdk/commit/f570c94a7bc99cd5bebc96ee388d152220f9f613)), closes [#15639](https://github.com/aws/aws-cdk/issues/15639) +* **pipelines:** repos with dashes cannot be used as additionalInputs ([#16017](https://github.com/aws/aws-cdk/issues/16017)) ([400a59d](https://github.com/aws/aws-cdk/commit/400a59d19ee63fbd9318da34760b4ed8c9ba99b9)), closes [#15753](https://github.com/aws/aws-cdk/issues/15753) +* **s3-deployment:** BucketDeployment doesn't validate that distribution paths start with "/" ([#15865](https://github.com/aws/aws-cdk/issues/15865)) ([f8d8795](https://github.com/aws/aws-cdk/commit/f8d8795a610c3f49e31967001695caa648730d6d)), closes [#9317](https://github.com/aws/aws-cdk/issues/9317) + ## [1.118.0](https://github.com/aws/aws-cdk/compare/v1.117.0...v1.118.0) (2021-08-10) diff --git a/version.v1.json b/version.v1.json index 5c8ead95001f8..e02425c0f7b3d 100644 --- a/version.v1.json +++ b/version.v1.json @@ -1,3 +1,3 @@ { - "version": "1.118.0" -} + "version": "1.119.0" +} \ No newline at end of file From 8f706d5b151359f6c669265c37a05cc6fdc536be Mon Sep 17 00:00:00 2001 From: Ben Chaimberg Date: Tue, 17 Aug 2021 11:36:39 -0700 Subject: [PATCH 57/99] chore: remove duplicated closed issues in changelog --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b911ea37c753..c207fc6012f7c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,14 +8,14 @@ All notable changes to this project will be documented in this file. See [standa ### Features * **apigatewayv2:** http api - domain url for a stage ([#15973](https://github.com/aws/aws-cdk/issues/15973)) ([bb5d587](https://github.com/aws/aws-cdk/commit/bb5d5874098b4b1047a29b6697e5e3a65f349ff0)), closes [#15801](https://github.com/aws/aws-cdk/issues/15801) -* **assets:** exclude "cdk.out" from docker assets ([#16034](https://github.com/aws/aws-cdk/issues/16034)) ([84a831a](https://github.com/aws/aws-cdk/commit/84a831ab804244d426321504fc0971d74f6181fd)), closes [#14841](https://github.com/aws/aws-cdk/issues/14841) [#14841](https://github.com/aws/aws-cdk/issues/14841) [#14842](https://github.com/aws/aws-cdk/issues/14842) +* **assets:** exclude "cdk.out" from docker assets ([#16034](https://github.com/aws/aws-cdk/issues/16034)) ([84a831a](https://github.com/aws/aws-cdk/commit/84a831ab804244d426321504fc0971d74f6181fd)), closes [#14841](https://github.com/aws/aws-cdk/issues/14841) [#14842](https://github.com/aws/aws-cdk/issues/14842) * **aws-apigateway:** import existing usage plan ([#15771](https://github.com/aws/aws-cdk/issues/15771)) ([97fc290](https://github.com/aws/aws-cdk/commit/97fc29032c05edb7914c48efee0124be0126a5c4)), closes [#12677](https://github.com/aws/aws-cdk/issues/12677) * **cfnspec:** cloudformation spec v39.9.0 ([#15987](https://github.com/aws/aws-cdk/issues/15987)) ([e0d6181](https://github.com/aws/aws-cdk/commit/e0d61810ab78f7cab1af53bce82c60790a814f71)) ### Bug Fixes -* **core:** asset bundling fails for non-existent user ([#15313](https://github.com/aws/aws-cdk/issues/15313)) ([bf5882f](https://github.com/aws/aws-cdk/commit/bf5882f8def0676bbfaee7c2ff4fab6bf39df281)), closes [#15415](https://github.com/aws/aws-cdk/issues/15415) [#15415](https://github.com/aws/aws-cdk/issues/15415) +* **core:** asset bundling fails for non-existent user ([#15313](https://github.com/aws/aws-cdk/issues/15313)) ([bf5882f](https://github.com/aws/aws-cdk/commit/bf5882f8def0676bbfaee7c2ff4fab6bf39df281)), closes [#15415](https://github.com/aws/aws-cdk/issues/15415) * **ec2:** opaque error when insufficient NAT EIPs are configured ([#16040](https://github.com/aws/aws-cdk/issues/16040)) ([a308cac](https://github.com/aws/aws-cdk/commit/a308cacf1fc48e24311caec246b768ffe6ae9153)), closes [#16039](https://github.com/aws/aws-cdk/issues/16039) * **events:** cross-account event targets that have a Role are broken ([#15717](https://github.com/aws/aws-cdk/issues/15717)) ([f570c94](https://github.com/aws/aws-cdk/commit/f570c94a7bc99cd5bebc96ee388d152220f9f613)), closes [#15639](https://github.com/aws/aws-cdk/issues/15639) * **pipelines:** repos with dashes cannot be used as additionalInputs ([#16017](https://github.com/aws/aws-cdk/issues/16017)) ([400a59d](https://github.com/aws/aws-cdk/commit/400a59d19ee63fbd9318da34760b4ed8c9ba99b9)), closes [#15753](https://github.com/aws/aws-cdk/issues/15753) From ceddb5495ad52ff75fbab965fd639216110feb5c Mon Sep 17 00:00:00 2001 From: Calvin Combs Date: Tue, 17 Aug 2021 13:21:48 -0700 Subject: [PATCH 58/99] add comcalvi to mergigy --- .mergify.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mergify.yml b/.mergify.yml index 18f6ee0bb2555..97f3ce42a91be 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)$ + - 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)$ - -label~="contribution/core" - name: automatic merge actions: From 4f62cabe20827573ca5158ef623df47a4b0c334d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Aug 2021 09:30:04 +0300 Subject: [PATCH 59/99] chore(deps): bump tar from 4.4.13 to 4.4.16 (#15991) Bumps [tar](https://github.com/npm/node-tar) from 4.4.13 to 4.4.16. - [Release notes](https://github.com/npm/node-tar/releases) - [Changelog](https://github.com/npm/node-tar/blob/main/CHANGELOG.md) - [Commits](https://github.com/npm/node-tar/compare/v4.4.13...v4.4.16) --- updated-dependencies: - dependency-name: tar dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Ben Chaimberg --- yarn.lock | 121 +++++++++++------------------------------------------- 1 file changed, 24 insertions(+), 97 deletions(-) diff --git a/yarn.lock b/yarn.lock index 66bb214514901..debb10a585377 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2042,11 +2042,6 @@ anymatch@^3.0.3: normalize-path "^3.0.0" picomatch "^2.0.4" -app-root-path@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-2.2.1.tgz#d0df4a682ee408273583d43f6f79e9892624bc9a" - integrity sha512-91IFKeKk7FjfmezPKkwtaRvSpnUc4gDwPAjA1YZ9Gn0q0PPeW+vbeUsZuyDwjI7+QTHhcLen2v25fi/AmhvbJA== - append-transform@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-1.0.0.tgz#046a52ae582a228bd72f58acfbe2967c678759ab" @@ -2268,7 +2263,7 @@ aws-sdk-mock@^5.2.1: sinon "^11.1.1" traverse "^0.6.6" -aws-sdk@^2.596.0, aws-sdk@^2.848.0, aws-sdk@^2.928.0: +aws-sdk@^2.848.0, aws-sdk@^2.928.0: version "2.950.0" resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.950.0.tgz#cffb65590c50de9479c87ed04df57d355d1d8a22" integrity sha512-iFC5fKLuFLEV27xeKmxDHDZzIDj4upm5+Ts3NpYYRbwPlOG0nE0gZzf9fRYkLkLgTr0TQq26CbKorgeo+6ailw== @@ -2693,7 +2688,7 @@ charenc@0.0.2: resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc= -chownr@^1.1.1: +chownr@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== @@ -3600,16 +3595,6 @@ dot-prop@^6.0.1: dependencies: is-obj "^2.0.0" -dotenv-json@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/dotenv-json/-/dotenv-json-1.0.0.tgz#fc7f672aafea04bed33818733b9f94662332815c" - integrity sha512-jAssr+6r4nKhKRudQ0HOzMskOFFi9+ubXWwmrSGJFgTvpjyPXCXsCsYbjif6mXp7uxA7xY3/LGaiTQukZzSbOQ== - -dotenv@^8.0.0: - version "8.6.0" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b" - integrity sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g== - dotgitignore@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/dotgitignore/-/dotgitignore-2.1.0.tgz#a4b15a4e4ef3cf383598aaf1dfa4a04bcc089b7b" @@ -3815,11 +3800,6 @@ escodegen@^2.0.0: optionalDependencies: source-map "~0.6.1" -eslint-config-standard@^14.1.1: - version "14.1.1" - resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-14.1.1.tgz#830a8e44e7aef7de67464979ad06b406026c56ea" - integrity sha512-Z9B+VR+JIXRxz21udPTL9HpFMyoMUEeX1G251EQ6e05WD9aPVtVBn09XUmZ259wCMlCDmYDSZG62Hhm+ZTJcUg== - eslint-import-resolver-node@^0.3.4: version "0.3.4" resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz#85ffa81942c25012d8231096ddf679c03042c717" @@ -3847,14 +3827,6 @@ eslint-module-utils@^2.6.1: debug "^3.2.7" pkg-dir "^2.0.0" -eslint-plugin-es@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz#75a7cdfdccddc0589934aeeb384175f221c57893" - integrity sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ== - dependencies: - eslint-utils "^2.0.0" - regexpp "^3.0.0" - eslint-plugin-import@^2.23.4: version "2.23.4" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.23.4.tgz#8dceb1ed6b73e46e50ec9a5bb2411b645e7d3d97" @@ -3883,33 +3855,11 @@ eslint-plugin-jest@^24.3.7: dependencies: "@typescript-eslint/experimental-utils" "^4.0.1" -eslint-plugin-node@^11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz#c95544416ee4ada26740a30474eefc5402dc671d" - integrity sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g== - dependencies: - eslint-plugin-es "^3.0.0" - eslint-utils "^2.0.0" - ignore "^5.1.1" - minimatch "^3.0.4" - resolve "^1.10.1" - semver "^6.1.0" - -eslint-plugin-promise@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.3.1.tgz#61485df2a359e03149fdafc0a68b0e030ad2ac45" - integrity sha512-bY2sGqyptzFBDLh/GMbAxfdJC+b0f23ME63FOE4+Jao0oZ3E1LEwFtWJX/1pGMJLiTtrSSern2CRM/g+dfc0eQ== - eslint-plugin-rulesdir@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/eslint-plugin-rulesdir/-/eslint-plugin-rulesdir-0.2.0.tgz#0d729e3f11bcb1a18d9b724a29a6d1a082ac2d62" integrity sha512-PPQPCsPkzF3upl1862swPA1bmDAAHKHmJJ4JTHJ11JCVCU4sycB0K5LLA/Rwr6r4VbnpScvUvHV4hqfdjvFmhQ== -eslint-plugin-standard@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-4.1.0.tgz#0c3bf3a67e853f8bbbc580fb4945fbf16f41b7c5" - integrity sha512-ZL7+QRixjTR6/528YNGyDotyffm5OQst/sGxKDwGb9Uqs4In5Egi4+jbobhqJoyoCM6/7v/1A5fhQ7ScMtDjaQ== - eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" @@ -3918,7 +3868,7 @@ eslint-scope@^5.1.1: esrecurse "^4.3.0" estraverse "^4.1.1" -eslint-utils@^2.0.0, eslint-utils@^2.1.0: +eslint-utils@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== @@ -4484,7 +4434,7 @@ fs-extra@^9.1.0: jsonfile "^6.0.1" universalify "^2.0.0" -fs-minipass@^1.2.5: +fs-minipass@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== @@ -4976,7 +4926,7 @@ ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== -ignore@^5.1.1, ignore@^5.1.4, ignore@^5.1.8, ignore@~5.1.8: +ignore@^5.1.4, ignore@^5.1.8, ignore@~5.1.8: version "5.1.8" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== @@ -6209,24 +6159,6 @@ kleur@^3.0.3: resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== -lambda-leak@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lambda-leak/-/lambda-leak-2.0.0.tgz#771985d3628487f6e885afae2b54510dcfb2cd7e" - integrity sha1-dxmF02KEh/boha+uK1RRDc+yzX4= - -lambda-tester@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/lambda-tester/-/lambda-tester-3.6.0.tgz#ceb7d4f4f0da768487a05cff37dcd088508b5247" - integrity sha512-F2ZTGWCLyIR95o/jWK46V/WnOCFAEUG/m/V7/CLhPJ7PCM+pror1rZ6ujP3TkItSGxUfpJi0kqwidw+M/nEqWw== - dependencies: - app-root-path "^2.2.1" - dotenv "^8.0.0" - dotenv-json "^1.0.0" - lambda-leak "^2.0.0" - semver "^6.1.1" - uuid "^3.3.2" - vandium-utils "^1.1.1" - lazystream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4" @@ -6847,7 +6779,7 @@ minipass-sized@^1.0.3: dependencies: minipass "^3.0.0" -minipass@^2.2.0, minipass@^2.3.5, minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0: +minipass@^2.2.0, minipass@^2.3.5, minipass@^2.6.0, minipass@^2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== @@ -6862,7 +6794,7 @@ minipass@^3.0.0, minipass@^3.1.0, minipass@^3.1.1, minipass@^3.1.3: dependencies: yallist "^4.0.0" -minizlib@^1.2.1: +minizlib@^1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== @@ -6899,7 +6831,7 @@ mkdirp@1.x, mkdirp@^1.0.3, mkdirp@^1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== -mkdirp@^0.5.0, mkdirp@^0.5.1: +mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.5: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== @@ -8305,7 +8237,7 @@ regexp.prototype.flags@^1.3.0: call-bind "^1.0.2" define-properties "^1.1.3" -regexpp@^3.0.0, regexpp@^3.1.0: +regexpp@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== @@ -8395,7 +8327,7 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@^1.10.0, resolve@^1.10.1, resolve@^1.11.1, resolve@^1.13.1, resolve@^1.17.0, resolve@^1.18.1, resolve@^1.20.0: +resolve@^1.10.0, resolve@^1.11.1, resolve@^1.13.1, resolve@^1.17.0, resolve@^1.18.1, resolve@^1.20.0: version "1.20.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== @@ -8469,7 +8401,7 @@ rxjs@^6.6.0: dependencies: tslib "^1.9.0" -safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: +safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@^5.2.1, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -8542,7 +8474,7 @@ semver@7.x, semver@^7.1.1, semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^ dependencies: lru-cache "^6.0.0" -semver@^6.0.0, semver@^6.1.0, semver@^6.1.1, semver@^6.3.0: +semver@^6.0.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== @@ -9225,17 +9157,17 @@ tar-stream@^2.2.0: readable-stream "^3.1.1" tar@^4.4.12: - version "4.4.13" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" - integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== - dependencies: - chownr "^1.1.1" - fs-minipass "^1.2.5" - minipass "^2.8.6" - minizlib "^1.2.1" - mkdirp "^0.5.0" - safe-buffer "^5.1.2" - yallist "^3.0.3" + version "4.4.16" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.16.tgz#4a48b3c025e77d9d0c788f038a09b91c594d326d" + integrity sha512-gOVUT/KWPkGFZQmCRDVFNUWBl7niIo/PRR7lzrIqtZpit+st54lGROuVjc6zEQM9FhH+dJfQIl+9F0k8GNXg5g== + dependencies: + chownr "^1.1.4" + fs-minipass "^1.2.7" + minipass "^2.9.0" + minizlib "^1.3.3" + mkdirp "^0.5.5" + safe-buffer "^5.2.1" + yallist "^3.1.1" tar@^6.0.2, tar@^6.1.0: version "6.1.0" @@ -9817,11 +9749,6 @@ validate-npm-package-name@^3.0.0: dependencies: builtins "^1.0.3" -vandium-utils@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/vandium-utils/-/vandium-utils-1.2.0.tgz#44735de4b7641a05de59ebe945f174e582db4f59" - integrity sha1-RHNd5LdkGgXeWevpRfF05YLbT1k= - verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" @@ -10126,7 +10053,7 @@ yallist@^2.1.2: resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= -yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: +yallist@^3.0.0, yallist@^3.0.2, yallist@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== From 1e498570f59b44e1bb0b15068d40f1ceff785b0a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Aug 2021 10:21:31 +0300 Subject: [PATCH 60/99] chore(deps-dev): bump jszip from 3.6.0 to 3.7.0 (#15990) * chore(deps-dev): bump jszip from 3.6.0 to 3.7.0 Bumps [jszip](https://github.com/Stuk/jszip) from 3.6.0 to 3.7.0. - [Release notes](https://github.com/Stuk/jszip/releases) - [Changelog](https://github.com/Stuk/jszip/blob/master/CHANGES.md) - [Commits](https://github.com/Stuk/jszip/compare/v3.6.0...v3.7.0) --- updated-dependencies: - dependency-name: jszip dependency-type: direct:development ... Signed-off-by: dependabot[bot] * updates package.json as well and removes unneeded types dependency Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Ben Chaimberg --- packages/cdk-assets/package.json | 3 +- yarn.lock | 113 ++++++++++++++++++++++++++----- 2 files changed, 98 insertions(+), 18 deletions(-) diff --git a/packages/cdk-assets/package.json b/packages/cdk-assets/package.json index 6faafe1d543e2..3736229b4b2f7 100644 --- a/packages/cdk-assets/package.json +++ b/packages/cdk-assets/package.json @@ -36,14 +36,13 @@ "@types/archiver": "^5.3.0", "@types/glob": "^7.1.4", "@types/jest": "^26.0.24", - "@types/jszip": "^3.4.1", "@types/mime": "^2.0.3", "@types/mock-fs": "^4.13.1", "@types/node": "^10.17.60", "@types/yargs": "^15.0.14", "cdk-build-tools": "0.0.0", "jest": "^26.6.3", - "jszip": "^3.6.0", + "jszip": "^3.7.0", "mock-fs": "^4.14.0", "pkglint": "0.0.0" }, diff --git a/yarn.lock b/yarn.lock index debb10a585377..e23c89293dc2f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1641,13 +1641,6 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.8.tgz#edf1bf1dbf4e04413ca8e5b17b3b7d7d54b59818" integrity sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg== -"@types/jszip@^3.4.1": - version "3.4.1" - resolved "https://registry.yarnpkg.com/@types/jszip/-/jszip-3.4.1.tgz#e7a4059486e494c949ef750933d009684227846f" - integrity sha512-TezXjmf3lj+zQ651r6hPqvSScqBLvyPI9FxdXBqpEwBijNGQ2NXpaFW/7joGzveYkKQUil7iiDHLo6LV71Pc0A== - dependencies: - jszip "*" - "@types/lodash@^4.14.171": version "4.14.171" resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.171.tgz#f01b3a5fe3499e34b622c362a46a609fdb23573b" @@ -2042,6 +2035,11 @@ anymatch@^3.0.3: normalize-path "^3.0.0" picomatch "^2.0.4" +app-root-path@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-2.2.1.tgz#d0df4a682ee408273583d43f6f79e9892624bc9a" + integrity sha512-91IFKeKk7FjfmezPKkwtaRvSpnUc4gDwPAjA1YZ9Gn0q0PPeW+vbeUsZuyDwjI7+QTHhcLen2v25fi/AmhvbJA== + append-transform@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-1.0.0.tgz#046a52ae582a228bd72f58acfbe2967c678759ab" @@ -2263,6 +2261,21 @@ aws-sdk-mock@^5.2.1: sinon "^11.1.1" traverse "^0.6.6" +aws-sdk@^2.596.0: + version "2.970.0" + resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.970.0.tgz#dc258b61b4727dcb5130c494376b598eb19f827b" + integrity sha512-9+ktvE5xgpHr3RsFOcq1SrhXLvU+jUji44jbecFZb5C2lzoEEB29aeN39OLJMW0ZuOrR+3TNum8c3f8YVx6A7w== + dependencies: + buffer "4.9.2" + events "1.1.1" + ieee754 "1.1.13" + jmespath "0.15.0" + querystring "0.2.0" + sax "1.2.1" + url "0.10.3" + uuid "3.3.2" + xml2js "0.4.19" + aws-sdk@^2.848.0, aws-sdk@^2.928.0: version "2.950.0" resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.950.0.tgz#cffb65590c50de9479c87ed04df57d355d1d8a22" @@ -3595,6 +3608,16 @@ dot-prop@^6.0.1: dependencies: is-obj "^2.0.0" +dotenv-json@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/dotenv-json/-/dotenv-json-1.0.0.tgz#fc7f672aafea04bed33818733b9f94662332815c" + integrity sha512-jAssr+6r4nKhKRudQ0HOzMskOFFi9+ubXWwmrSGJFgTvpjyPXCXsCsYbjif6mXp7uxA7xY3/LGaiTQukZzSbOQ== + +dotenv@^8.0.0: + version "8.6.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b" + integrity sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g== + dotgitignore@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/dotgitignore/-/dotgitignore-2.1.0.tgz#a4b15a4e4ef3cf383598aaf1dfa4a04bcc089b7b" @@ -3800,6 +3823,11 @@ escodegen@^2.0.0: optionalDependencies: source-map "~0.6.1" +eslint-config-standard@^14.1.1: + version "14.1.1" + resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-14.1.1.tgz#830a8e44e7aef7de67464979ad06b406026c56ea" + integrity sha512-Z9B+VR+JIXRxz21udPTL9HpFMyoMUEeX1G251EQ6e05WD9aPVtVBn09XUmZ259wCMlCDmYDSZG62Hhm+ZTJcUg== + eslint-import-resolver-node@^0.3.4: version "0.3.4" resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz#85ffa81942c25012d8231096ddf679c03042c717" @@ -3827,6 +3855,14 @@ eslint-module-utils@^2.6.1: debug "^3.2.7" pkg-dir "^2.0.0" +eslint-plugin-es@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz#75a7cdfdccddc0589934aeeb384175f221c57893" + integrity sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ== + dependencies: + eslint-utils "^2.0.0" + regexpp "^3.0.0" + eslint-plugin-import@^2.23.4: version "2.23.4" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.23.4.tgz#8dceb1ed6b73e46e50ec9a5bb2411b645e7d3d97" @@ -3855,11 +3891,33 @@ eslint-plugin-jest@^24.3.7: dependencies: "@typescript-eslint/experimental-utils" "^4.0.1" +eslint-plugin-node@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz#c95544416ee4ada26740a30474eefc5402dc671d" + integrity sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g== + dependencies: + eslint-plugin-es "^3.0.0" + eslint-utils "^2.0.0" + ignore "^5.1.1" + minimatch "^3.0.4" + resolve "^1.10.1" + semver "^6.1.0" + +eslint-plugin-promise@^4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.3.1.tgz#61485df2a359e03149fdafc0a68b0e030ad2ac45" + integrity sha512-bY2sGqyptzFBDLh/GMbAxfdJC+b0f23ME63FOE4+Jao0oZ3E1LEwFtWJX/1pGMJLiTtrSSern2CRM/g+dfc0eQ== + eslint-plugin-rulesdir@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/eslint-plugin-rulesdir/-/eslint-plugin-rulesdir-0.2.0.tgz#0d729e3f11bcb1a18d9b724a29a6d1a082ac2d62" integrity sha512-PPQPCsPkzF3upl1862swPA1bmDAAHKHmJJ4JTHJ11JCVCU4sycB0K5LLA/Rwr6r4VbnpScvUvHV4hqfdjvFmhQ== +eslint-plugin-standard@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-4.1.0.tgz#0c3bf3a67e853f8bbbc580fb4945fbf16f41b7c5" + integrity sha512-ZL7+QRixjTR6/528YNGyDotyffm5OQst/sGxKDwGb9Uqs4In5Egi4+jbobhqJoyoCM6/7v/1A5fhQ7ScMtDjaQ== + eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" @@ -3868,7 +3926,7 @@ eslint-scope@^5.1.1: esrecurse "^4.3.0" estraverse "^4.1.1" -eslint-utils@^2.1.0: +eslint-utils@^2.0.0, eslint-utils@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== @@ -4926,7 +4984,7 @@ ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== -ignore@^5.1.4, ignore@^5.1.8, ignore@~5.1.8: +ignore@^5.1.1, ignore@^5.1.4, ignore@^5.1.8, ignore@~5.1.8: version "5.1.8" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== @@ -6108,10 +6166,10 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" -jszip@*, jszip@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.6.0.tgz#839b72812e3f97819cc13ac4134ffced95dd6af9" - integrity sha512-jgnQoG9LKnWO3mnVNBnfhkh0QknICd1FGSrXcgrl67zioyJ4wgx25o9ZqwNtrROSflGBCGYnJfjrIyRIby1OoQ== +jszip@^3.7.0: + version "3.7.1" + resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.7.1.tgz#bd63401221c15625a1228c556ca8a68da6fda3d9" + integrity sha512-ghL0tz1XG9ZEmRMcEN2vt7xabrDdqHHeykgARpmZ0BiIctWxM47Vt63ZO2dnp4QYt/xJVLLy5Zv1l/xRdh2byg== dependencies: lie "~3.3.0" pako "~1.0.2" @@ -6159,6 +6217,24 @@ kleur@^3.0.3: resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== +lambda-leak@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lambda-leak/-/lambda-leak-2.0.0.tgz#771985d3628487f6e885afae2b54510dcfb2cd7e" + integrity sha1-dxmF02KEh/boha+uK1RRDc+yzX4= + +lambda-tester@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/lambda-tester/-/lambda-tester-3.6.0.tgz#ceb7d4f4f0da768487a05cff37dcd088508b5247" + integrity sha512-F2ZTGWCLyIR95o/jWK46V/WnOCFAEUG/m/V7/CLhPJ7PCM+pror1rZ6ujP3TkItSGxUfpJi0kqwidw+M/nEqWw== + dependencies: + app-root-path "^2.2.1" + dotenv "^8.0.0" + dotenv-json "^1.0.0" + lambda-leak "^2.0.0" + semver "^6.1.1" + uuid "^3.3.2" + vandium-utils "^1.1.1" + lazystream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4" @@ -8237,7 +8313,7 @@ regexp.prototype.flags@^1.3.0: call-bind "^1.0.2" define-properties "^1.1.3" -regexpp@^3.1.0: +regexpp@^3.0.0, regexpp@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== @@ -8327,7 +8403,7 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@^1.10.0, resolve@^1.11.1, resolve@^1.13.1, resolve@^1.17.0, resolve@^1.18.1, resolve@^1.20.0: +resolve@^1.10.0, resolve@^1.10.1, resolve@^1.11.1, resolve@^1.13.1, resolve@^1.17.0, resolve@^1.18.1, resolve@^1.20.0: version "1.20.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== @@ -8474,7 +8550,7 @@ semver@7.x, semver@^7.1.1, semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^ dependencies: lru-cache "^6.0.0" -semver@^6.0.0, semver@^6.3.0: +semver@^6.0.0, semver@^6.1.0, semver@^6.1.1, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== @@ -9749,6 +9825,11 @@ validate-npm-package-name@^3.0.0: dependencies: builtins "^1.0.3" +vandium-utils@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/vandium-utils/-/vandium-utils-1.2.0.tgz#44735de4b7641a05de59ebe945f174e582db4f59" + integrity sha1-RHNd5LdkGgXeWevpRfF05YLbT1k= + verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" From 000d151bec2215aa530819c3cf2c8c432352fec3 Mon Sep 17 00:00:00 2001 From: Bryan Pan Date: Wed, 18 Aug 2021 01:03:29 -0700 Subject: [PATCH 61/99] fix(appsync): addSubscription only allows for field type (#16097) Error in the documentation and type checking. Fixed both the readme and the related PR (integ test used a `Field` type so it still works as intended). Related PR: #10078 Fixes: #16071 ---- *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 | 2 +- packages/@aws-cdk/aws-appsync/lib/schema.ts | 4 +-- .../test/appsync-code-first.test.ts | 25 +++++++++++++++++++ 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk/aws-appsync/README.md b/packages/@aws-cdk/aws-appsync/README.md index 32e0558ccd4f8..3dbf2e27a277b 100644 --- a/packages/@aws-cdk/aws-appsync/README.md +++ b/packages/@aws-cdk/aws-appsync/README.md @@ -960,7 +960,7 @@ To add fields for these subscriptions, we can simply run the `addSubscription` f to the schema's `Subscription` type. ```ts -api.addSubscription('addedFilm', new appsync.ResolvableField({ +api.addSubscription('addedFilm', new appsync.Field({ returnType: film.attribute(), args: { id: appsync.GraphqlType.id({ isRequired: true }) }, directive: [appsync.Directive.subscribe('addFilm')], diff --git a/packages/@aws-cdk/aws-appsync/lib/schema.ts b/packages/@aws-cdk/aws-appsync/lib/schema.ts index fb22204c34440..ad94da1610532 100644 --- a/packages/@aws-cdk/aws-appsync/lib/schema.ts +++ b/packages/@aws-cdk/aws-appsync/lib/schema.ts @@ -4,7 +4,7 @@ import { CfnGraphQLSchema } from './appsync.generated'; import { GraphqlApi } from './graphqlapi'; import { SchemaMode, shapeAddition } from './private'; import { IIntermediateType } from './schema-base'; -import { ResolvableField } from './schema-field'; +import { Field, ResolvableField } from './schema-field'; import { ObjectType } from './schema-intermediate'; /** @@ -164,7 +164,7 @@ export class Schema { * @param fieldName the name of the Subscription * @param field the resolvable field to for this Subscription */ - public addSubscription(fieldName: string, field: ResolvableField): ObjectType { + public addSubscription(fieldName: string, field: Field): ObjectType { if (this.mode !== SchemaMode.CODE) { throw new Error(`Unable to add subscription. Schema definition mode must be ${SchemaMode.CODE}. Received: ${this.mode}`); } diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-code-first.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-code-first.test.ts index d904186f4f07b..f79e92ab67d35 100644 --- a/packages/@aws-cdk/aws-appsync/test/appsync-code-first.test.ts +++ b/packages/@aws-cdk/aws-appsync/test/appsync-code-first.test.ts @@ -141,6 +141,31 @@ describe('code-first implementation through GraphQL Api functions`', () => { Definition: `${out}`, }); }); + + test('addSubscription allows for adding fields but not resolvable fields', () => { + const ds = api.addNoneDataSource('DS'); + + // WHEN + api.addMutation('addId', new appsync.ResolvableField({ + returnType: t.required_id, + args: { id: t.required_id }, + dataSource: ds, + })); + api.addSubscription('addedId', new appsync.Field({ + returnType: t.required_id, + args: { id: t.required_id }, + directives: [appsync.Directive.subscribe('addId')], + })); + + const schemaDef = 'schema {\n mutation: Mutation\n subscription: Subscription\n}\n'; + const mutationDef = 'type Mutation {\n addId(id: ID!): ID!\n}\n'; + const subscriptionDef = 'type Subscription {\n addedId(id: ID!): ID!\n @aws_subscribe(mutations: ["addId"])\n}\n'; + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { + Definition: `${schemaDef}${mutationDef}${subscriptionDef}`, + }); + }); }); describe('code-first implementation through Schema functions`', () => { From 84006c08606bbb3d6371fde2189d0c4cac3c8af2 Mon Sep 17 00:00:00 2001 From: Ben Chaimberg Date: Wed, 18 Aug 2021 01:43:32 -0700 Subject: [PATCH 62/99] chore(deps): bump tar from 6.1.0 to 6.1.8 (#16109) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index e23c89293dc2f..431e3492b2be6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9246,9 +9246,9 @@ tar@^4.4.12: yallist "^3.1.1" tar@^6.0.2, tar@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.0.tgz#d1724e9bcc04b977b18d5c573b333a2207229a83" - integrity sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA== + version "6.1.8" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.8.tgz#4fc50cfe56511c538ce15b71e05eebe66530cbd4" + integrity sha512-sb9b0cp855NbkMJcskdSYA7b11Q8JsX4qe4pyUAfHp+Y6jBjJeek2ZVlwEfWayshEIwlIzXx0Fain3QG9JPm2A== dependencies: chownr "^2.0.0" fs-minipass "^2.0.0" From 7e0ad5d17b30150922d0dfd81f42da11fadb8beb Mon Sep 17 00:00:00 2001 From: AWS CDK Automation <43080478+aws-cdk-automation@users.noreply.github.com> Date: Wed, 18 Aug 2021 12:44:20 +0300 Subject: [PATCH 63/99] feat(cfnspec): cloudformation spec v39.10.0 (#16114) Co-authored-by: AWS CDK Team --- packages/@aws-cdk/cfnspec/CHANGELOG.md | 27 +++ packages/@aws-cdk/cfnspec/cfn.version | 2 +- ...0_CloudFormationResourceSpecification.json | 156 +++++++++++++++++- 3 files changed, 183 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/cfnspec/CHANGELOG.md b/packages/@aws-cdk/cfnspec/CHANGELOG.md index 716c917940793..4f7501decae02 100644 --- a/packages/@aws-cdk/cfnspec/CHANGELOG.md +++ b/packages/@aws-cdk/cfnspec/CHANGELOG.md @@ -1,3 +1,30 @@ +# CloudFormation Resource Specification v39.10.0 + +## New Resource Types + +* AWS::WAFv2::LoggingConfiguration + +## Attribute Changes + +* AWS::EC2::EgressOnlyInternetGateway Id (__added__) +* AWS::S3::AccessPoint Alias (__added__) + +## Property Changes + +* AWS::ApiGateway::DomainName OwnershipVerificationCertificateArn (__added__) +* AWS::CodeBuild::Project ResourceAccessRole (__added__) +* AWS::CodeBuild::Project Visibility (__added__) + +## Property Type Changes + +* AWS::Elasticsearch::Domain.ColdStorageOptions (__added__) +* AWS::IoTAnalytics::Datastore.CustomerManagedS3Storage (__added__) +* AWS::IoTAnalytics::Datastore.IotSiteWiseMultiLayerStorage (__added__) +* AWS::ApiGatewayV2::DomainName.DomainNameConfiguration OwnershipVerificationCertificateArn (__added__) +* AWS::Elasticsearch::Domain.ElasticsearchClusterConfig ColdStorageOptions (__added__) +* AWS::IoTAnalytics::Datastore.DatastoreStorage IotSiteWiseMultiLayerStorage (__added__) + + # CloudFormation Resource Specification v39.9.0 ## New Resource Types diff --git a/packages/@aws-cdk/cfnspec/cfn.version b/packages/@aws-cdk/cfnspec/cfn.version index ff93cfe146d81..3520fac4397ab 100644 --- a/packages/@aws-cdk/cfnspec/cfn.version +++ b/packages/@aws-cdk/cfnspec/cfn.version @@ -1 +1 @@ -39.9.0 +39.10.0 diff --git a/packages/@aws-cdk/cfnspec/spec-source/000_CloudFormationResourceSpecification.json b/packages/@aws-cdk/cfnspec/spec-source/000_CloudFormationResourceSpecification.json index 2d71e22ab1083..ebcff7129953c 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/000_CloudFormationResourceSpecification.json +++ b/packages/@aws-cdk/cfnspec/spec-source/000_CloudFormationResourceSpecification.json @@ -2175,6 +2175,12 @@ "Required": false, "UpdateType": "Mutable" }, + "OwnershipVerificationCertificateArn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-apigatewayv2-domainname-domainnameconfiguration.html#cfn-apigatewayv2-domainname-domainnameconfiguration-ownershipverificationcertificatearn", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, "SecurityPolicy": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-apigatewayv2-domainname-domainnameconfiguration.html#cfn-apigatewayv2-domainname-domainnameconfiguration-securitypolicy", "PrimitiveType": "String", @@ -26500,6 +26506,17 @@ } } }, + "AWS::Elasticsearch::Domain.ColdStorageOptions": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticsearch-domain-coldstorageoptions.html", + "Properties": { + "Enabled": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticsearch-domain-coldstorageoptions.html#cfn-elasticsearch-domain-coldstorageoptions-enabled", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Mutable" + } + } + }, "AWS::Elasticsearch::Domain.DomainEndpointOptions": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticsearch-domain-domainendpointoptions.html", "Properties": { @@ -26567,6 +26584,12 @@ "AWS::Elasticsearch::Domain.ElasticsearchClusterConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticsearch-domain-elasticsearchclusterconfig.html", "Properties": { + "ColdStorageOptions": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticsearch-domain-elasticsearchclusterconfig.html#cfn-elasticsearch-domain-elasticsearchclusterconfig-coldstorageoptions", + "Required": false, + "Type": "ColdStorageOptions", + "UpdateType": "Mutable" + }, "DedicatedMasterCount": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticsearch-domain-elasticsearchclusterconfig.html#cfn-elasticsearch-domain-elasticseachclusterconfig-dedicatedmastercount", "PrimitiveType": "Integer", @@ -34440,6 +34463,23 @@ } } }, + "AWS::IoTAnalytics::Datastore.CustomerManagedS3Storage": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-datastore-customermanageds3storage.html", + "Properties": { + "Bucket": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-datastore-customermanageds3storage.html#cfn-iotanalytics-datastore-customermanageds3storage-bucket", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "KeyPrefix": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-datastore-customermanageds3storage.html#cfn-iotanalytics-datastore-customermanageds3storage-keyprefix", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, "AWS::IoTAnalytics::Datastore.DatastorePartition": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-datastore-datastorepartition.html", "Properties": { @@ -34478,6 +34518,12 @@ "Type": "CustomerManagedS3", "UpdateType": "Mutable" }, + "IotSiteWiseMultiLayerStorage": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-datastore-datastorestorage.html#cfn-iotanalytics-datastore-datastorestorage-iotsitewisemultilayerstorage", + "Required": false, + "Type": "IotSiteWiseMultiLayerStorage", + "UpdateType": "Mutable" + }, "ServiceManagedS3": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-datastore-datastorestorage.html#cfn-iotanalytics-datastore-datastorestorage-servicemanageds3", "Required": false, @@ -34503,6 +34549,17 @@ } } }, + "AWS::IoTAnalytics::Datastore.IotSiteWiseMultiLayerStorage": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-datastore-iotsitewisemultilayerstorage.html", + "Properties": { + "CustomerManagedS3Storage": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-datastore-iotsitewisemultilayerstorage.html#cfn-iotanalytics-datastore-iotsitewisemultilayerstorage-customermanageds3storage", + "Required": true, + "Type": "CustomerManagedS3Storage", + "UpdateType": "Mutable" + } + } + }, "AWS::IoTAnalytics::Datastore.JsonConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-datastore-jsonconfiguration.html", "Properties": {} @@ -59880,6 +59937,41 @@ } } }, + "AWS::WAFv2::LoggingConfiguration.FieldToMatch": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wafv2-loggingconfiguration-fieldtomatch.html", + "Properties": { + "JsonBody": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wafv2-loggingconfiguration-fieldtomatch.html#cfn-wafv2-loggingconfiguration-fieldtomatch-jsonbody", + "PrimitiveType": "Json", + "Required": false, + "UpdateType": "Mutable" + }, + "Method": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wafv2-loggingconfiguration-fieldtomatch.html#cfn-wafv2-loggingconfiguration-fieldtomatch-method", + "PrimitiveType": "Json", + "Required": false, + "UpdateType": "Mutable" + }, + "QueryString": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wafv2-loggingconfiguration-fieldtomatch.html#cfn-wafv2-loggingconfiguration-fieldtomatch-querystring", + "PrimitiveType": "Json", + "Required": false, + "UpdateType": "Mutable" + }, + "SingleHeader": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wafv2-loggingconfiguration-fieldtomatch.html#cfn-wafv2-loggingconfiguration-fieldtomatch-singleheader", + "PrimitiveType": "Json", + "Required": false, + "UpdateType": "Mutable" + }, + "UriPath": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wafv2-loggingconfiguration-fieldtomatch.html#cfn-wafv2-loggingconfiguration-fieldtomatch-uripath", + "PrimitiveType": "Json", + "Required": false, + "UpdateType": "Mutable" + } + } + }, "AWS::WAFv2::RuleGroup.AndStatement": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wafv2-rulegroup-andstatement.html", "Properties": { @@ -61613,7 +61705,7 @@ } } }, - "ResourceSpecificationVersion": "39.9.0", + "ResourceSpecificationVersion": "39.10.0", "ResourceTypes": { "AWS::ACMPCA::Certificate": { "Attributes": { @@ -62617,6 +62709,12 @@ "Type": "MutualTlsAuthentication", "UpdateType": "Mutable" }, + "OwnershipVerificationCertificateArn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-domainname.html#cfn-apigateway-domainname-ownershipverificationcertificatearn", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, "RegionalCertificateArn": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-domainname.html#cfn-apigateway-domainname-regionalcertificatearn", "PrimitiveType": "String", @@ -68710,6 +68808,12 @@ "Required": false, "UpdateType": "Mutable" }, + "ResourceAccessRole": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-codebuild-project.html#cfn-codebuild-project-resourceaccessrole", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, "SecondaryArtifacts": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-codebuild-project.html#cfn-codebuild-project-secondaryartifacts", "ItemType": "Artifacts", @@ -68768,6 +68872,12 @@ "Type": "ProjectTriggers", "UpdateType": "Mutable" }, + "Visibility": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-codebuild-project.html#cfn-codebuild-project-visibility", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, "VpcConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-codebuild-project.html#cfn-codebuild-project-vpcconfig", "Required": false, @@ -73395,6 +73505,11 @@ } }, "AWS::EC2::EgressOnlyInternetGateway": { + "Attributes": { + "Id": { + "PrimitiveType": "String" + } + }, "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-egressonlyinternetgateway.html", "Properties": { "VpcId": { @@ -94431,6 +94546,9 @@ }, "AWS::S3::AccessPoint": { "Attributes": { + "Alias": { + "PrimitiveType": "String" + }, "Arn": { "PrimitiveType": "String" }, @@ -99359,6 +99477,42 @@ } } }, + "AWS::WAFv2::LoggingConfiguration": { + "Attributes": { + "ManagedByFirewallManager": { + "PrimitiveType": "Boolean" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-wafv2-loggingconfiguration.html", + "Properties": { + "LogDestinationConfigs": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-wafv2-loggingconfiguration.html#cfn-wafv2-loggingconfiguration-logdestinationconfigs", + "PrimitiveItemType": "String", + "Required": true, + "Type": "List", + "UpdateType": "Mutable" + }, + "LoggingFilter": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-wafv2-loggingconfiguration.html#cfn-wafv2-loggingconfiguration-loggingfilter", + "PrimitiveType": "Json", + "Required": false, + "UpdateType": "Mutable" + }, + "RedactedFields": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-wafv2-loggingconfiguration.html#cfn-wafv2-loggingconfiguration-redactedfields", + "ItemType": "FieldToMatch", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "ResourceArn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-wafv2-loggingconfiguration.html#cfn-wafv2-loggingconfiguration-resourcearn", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + } + } + }, "AWS::WAFv2::RegexPatternSet": { "Attributes": { "Arn": { From f35b032cea4354992d3320e78c1ed0e2878a3fe7 Mon Sep 17 00:00:00 2001 From: kaizen3031593 <36202692+kaizen3031593@users.noreply.github.com> Date: Wed, 18 Aug 2021 16:09:32 -0400 Subject: [PATCH 64/99] fix(cli): 'deploy' and 'diff' silently does nothing when given unknown stack name (#16073) Currently, `cdk deploy` and `cdk diff` on stacks that do not exist return no output on the command line. This PR introduces a descriptive error message for those cases so it is easier to understand what happened. Leaving the idea of fuzzy matching for stack name suggestions to a (potential) future PR, I can open a new issue for that if this one goes through. For the linter, I'm not sure if anything of value can be added to the readme so I'm wondering if this would be a candidate for exemption. closes #15866 while adding the same idea to `diff` as well as `deploy`. ---- *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/cdk-toolkit.ts | 10 +++++++--- packages/aws-cdk/test/cdk-toolkit.test.ts | 8 ++++++++ packages/aws-cdk/test/diff.test.ts | 10 ++++++++++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/packages/aws-cdk/lib/cdk-toolkit.ts b/packages/aws-cdk/lib/cdk-toolkit.ts index 55ca1c6e24903..8edefe66fc333 100644 --- a/packages/aws-cdk/lib/cdk-toolkit.ts +++ b/packages/aws-cdk/lib/cdk-toolkit.ts @@ -397,7 +397,7 @@ export class CdkToolkit { defaultBehavior: DefaultSelection.OnlySingle, }); - await this.validateStacks(stacks); + await this.validateStacks(stacks, selector.patterns); return stacks; } @@ -415,7 +415,7 @@ export class CdkToolkit { ? allStacks.filter(art => art.validateOnSynth ?? false) : new StackCollection(assembly, []); - await this.validateStacks(selectedForDiff.concat(autoValidateStacks)); + await this.validateStacks(selectedForDiff.concat(autoValidateStacks), stackNames); return selectedForDiff; } @@ -435,7 +435,11 @@ export class CdkToolkit { /** * Validate the stacks for errors and warnings according to the CLI's current settings */ - private async validateStacks(stacks: StackCollection) { + private async validateStacks(stacks: StackCollection, stackNames: string[]) { + if (stacks.stackCount == 0) { + throw new Error(`No stacks match the name(s) ${stackNames}`); + } + stacks.processMetadataMessages({ ignoreErrors: this.props.ignoreErrors, strict: this.props.strict, diff --git a/packages/aws-cdk/test/cdk-toolkit.test.ts b/packages/aws-cdk/test/cdk-toolkit.test.ts index 8f53405b749e4..f4573637ee5f4 100644 --- a/packages/aws-cdk/test/cdk-toolkit.test.ts +++ b/packages/aws-cdk/test/cdk-toolkit.test.ts @@ -39,6 +39,14 @@ function defaultToolkitSetup() { } describe('deploy', () => { + test('fails when no valid stack names are given', async () => { + // GIVEN + const toolkit = defaultToolkitSetup(); + + // WHEN + await expect(() => toolkit.deploy({ selector: { patterns: ['Test-Stack-D'] } })).rejects.toThrow('No stacks match the name(s) Test-Stack-D'); + }); + describe('makes correct CloudFormation calls', () => { test('without options', async () => { // GIVEN diff --git a/packages/aws-cdk/test/diff.test.ts b/packages/aws-cdk/test/diff.test.ts index c1bcd11c78caa..e14ebe9bd9779 100644 --- a/packages/aws-cdk/test/diff.test.ts +++ b/packages/aws-cdk/test/diff.test.ts @@ -121,6 +121,16 @@ test('throws an error during diffs on stack with error metadata', async () => { })).rejects.toThrow(/Found errors/); }); +test('throws an error if no valid stack names given', async () => { + const buffer = new StringWritable(); + + // WHEN + await expect(() => toolkit.diff({ + stackNames: ['X', 'Y', 'Z'], + stream: buffer, + })).rejects.toThrow('No stacks match the name(s) X,Y,Z'); +}); + class StringWritable extends Writable { public data: string; private readonly _decoder: NodeStringDecoder; From 2372b3c360d13fb0224fc981a7bb1ae318581265 Mon Sep 17 00:00:00 2001 From: diegotry <33488603+diegotry@users.noreply.github.com> Date: Wed, 18 Aug 2021 15:13:46 -0700 Subject: [PATCH 65/99] feat(aws-stepfunctions): add support to heartbeat error inside catch block (#16078) Step Functions recently added a feature to catch States.HeartbeatTimeout. This change adds support to that. https://docs.aws.amazon.com/step-functions/latest/dg/concepts-error-handling.html closes #16084 ---- *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 | 16 ++++++++++++++++ packages/@aws-cdk/aws-stepfunctions/lib/types.ts | 5 +++++ packages/@aws-cdk/aws-stepfunctions/package.json | 1 + 3 files changed, 22 insertions(+) diff --git a/packages/@aws-cdk/aws-stepfunctions/README.md b/packages/@aws-cdk/aws-stepfunctions/README.md index f22d45f9f475d..4faf512ad0509 100644 --- a/packages/@aws-cdk/aws-stepfunctions/README.md +++ b/packages/@aws-cdk/aws-stepfunctions/README.md @@ -555,6 +555,22 @@ new cloudwatch.Alarm(this, 'ThrottledAlarm', { }); ``` +## Error names + +Step Functions identifies errors in the Amazon States Language using case-sensitive strings, known as error names. +The Amazon States Language defines a set of built-in strings that name well-known errors, all beginning with the `States.` prefix. + +* `States.ALL` - A wildcard that matches any known error name. +* `States.Runtime` - An execution failed due to some exception that could not be processed. Often these are caused by errors at runtime, such as attempting to apply InputPath or OutputPath on a null JSON payload. A `States.Runtime` error is not retriable, and will always cause the execution to fail. A retry or catch on `States.ALL` will NOT catch States.Runtime errors. +* `States.DataLimitExceeded` - A States.DataLimitExceeded exception will be thrown for the following: + * When the output of a connector is larger than payload size quota. + * When the output of a state is larger than payload size quota. + * When, after Parameters processing, the input of a state is larger than the payload size quota. + * See [the AWS documentation](https://docs.aws.amazon.com/step-functions/latest/dg/limits-overview.html) to learn more about AWS Step Functions Quotas. +* `States.HeartbeatTimeout` - A Task state failed to send a heartbeat for a period longer than the HeartbeatSeconds value. +* `States.Timeout` - A Task state either ran longer than the TimeoutSeconds value, or failed to send a heartbeat for a period longer than the HeartbeatSeconds value. +* `States.TaskFailed`- A Task state failed during the execution. When used in a retry or catch, `States.TaskFailed` acts as a wildcard that matches any known error name except for `States.Timeout`. + ## Logging Enable logging to CloudWatch by passing a logging configuration with a diff --git a/packages/@aws-cdk/aws-stepfunctions/lib/types.ts b/packages/@aws-cdk/aws-stepfunctions/lib/types.ts index a376ace3b24ea..d3eee929f09b8 100644 --- a/packages/@aws-cdk/aws-stepfunctions/lib/types.ts +++ b/packages/@aws-cdk/aws-stepfunctions/lib/types.ts @@ -45,6 +45,11 @@ export class Errors { */ public static readonly ALL = 'States.ALL'; + /** + * A Task State failed to heartbeat for a time longer than the “HeartbeatSeconds” value. + */ + public static readonly HEARTBEAT_TIMEOUT = 'States.HeartbeatTimeout'; + /** * A Task State either ran longer than the “TimeoutSeconds” value, or * failed to heartbeat for a time longer than the “HeartbeatSeconds” value. diff --git a/packages/@aws-cdk/aws-stepfunctions/package.json b/packages/@aws-cdk/aws-stepfunctions/package.json index 485a879fee653..a5141b16bf045 100644 --- a/packages/@aws-cdk/aws-stepfunctions/package.json +++ b/packages/@aws-cdk/aws-stepfunctions/package.json @@ -105,6 +105,7 @@ "awslint": { "exclude": [ "duration-prop-type:@aws-cdk/aws-stepfunctions.Errors.TIMEOUT", + "duration-prop-type:@aws-cdk/aws-stepfunctions.Errors.HEARTBEAT_TIMEOUT", "no-unused-type:@aws-cdk/aws-stepfunctions.ServiceIntegrationPattern" ] }, From 2ce274f43e0d8e93707e5e67dcd789e6fde87d9e Mon Sep 17 00:00:00 2001 From: Calvin Combs <66279577+comcalvi@users.noreply.github.com> Date: Wed, 18 Aug 2021 16:35:35 -0700 Subject: [PATCH 66/99] transfered ownership of autoscaling to @comcalvi (#16119) --- .github/workflows/issue-label-assign.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/issue-label-assign.yml b/.github/workflows/issue-label-assign.yml index bcf12f04a1ec6..618de4693571f 100644 --- a/.github/workflows/issue-label-assign.yml +++ b/.github/workflows/issue-label-assign.yml @@ -35,18 +35,18 @@ jobs: {"keywords":["(@aws-cdk/aws-appconfig)","(aws-appconfig)","(appconfig)","(app config)","(app-config)"],"labels":["@aws-cdk/aws-appconfig"],"assignees":["rix0rrr"]}, {"keywords":["(@aws-cdk/aws-appflow)","(aws-appflow)","(appflow)","(app flow)","(app-flow)"],"labels":["@aws-cdk/aws-appflow"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/aws-appintegrations)","(aws-appintegrations)","(appintegrations)"],"labels":["@aws-cdk/aws-appintegrations"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-applicationautoscaling)","(aws-applicationautoscaling)","(applicationautoscaling)","(application autoscaling)","(application-autoscaling)"],"labels":["@aws-cdk/aws-applicationautoscaling"],"assignees":["rix0rrr"]}, + {"keywords":["(@aws-cdk/aws-applicationautoscaling)","(aws-applicationautoscaling)","(applicationautoscaling)","(application autoscaling)","(application-autoscaling)"],"labels":["@aws-cdk/aws-applicationautoscaling"],"assignees":["comcalvi"]}, {"keywords":["(@aws-cdk/aws-applicationinsights)","(aws-applicationinsights)","(applicationinsights)","(application insights)","(application-insights)"],"labels":["@aws-cdk/aws-applicationinsights"],"assignees":["njlynch"]}, {"keywords":["(@aws-cdk/aws-appmesh)","(aws-appmesh)","(appmesh)","(app mesh)","(app-mesh)"],"labels":["@aws-cdk/aws-appmesh"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/aws-appstream)","(aws-appstream)","(appstream)","(app stream)","(app-stream)"],"labels":["@aws-cdk/aws-appstream"],"assignees":["madeline-k"]}, {"keywords":["(@aws-cdk/aws-appsync)","(aws-appsync)","(appsync)","(app sync)","(app-sync)"],"labels":["@aws-cdk/aws-appsync"],"assignees":["otaviomacedo"]}, {"keywords":["(@aws-cdk/aws-athena)","(aws-athena)","(athena)"],"labels":["@aws-cdk/aws-athena"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/aws-auditmanager)","(aws-auditmanager)","(auditmanager)"],"labels":["@aws-cdk/aws-auditmanager"],"assignees":["njlynch"]}, - {"keywords":["(@aws-cdk/aws-autoscaling)","(aws-autoscaling)","(autoscaling)","(auto scaling)","(auto-scaling)"],"labels":["@aws-cdk/aws-autoscaling"],"assignees":["rix0rrr"]}, - {"keywords":["(@aws-cdk/aws-autoscaling-api)","(aws-autoscaling-api)","(autoscaling-api)","(autoscaling api)","(autoscaling-api)"],"labels":["@aws-cdk/aws-autoscaling-api"],"assignees":["rix0rrr"]}, - {"keywords":["(@aws-cdk/aws-autoscaling-common)","(aws-autoscaling-common)","(autoscaling-common)","(autoscaling common)","(autoscaling-common)"],"labels":["@aws-cdk/aws-autoscaling-common"],"assignees":["rix0rrr"]}, - {"keywords":["(@aws-cdk/aws-autoscaling-hooktargets)","(aws-autoscaling-hooktargets)","(autoscaling-hooktargets)","(autoscaling hooktargets)"],"labels":["@aws-cdk/aws-autoscaling-hooktargets"],"assignees":["rix0rrr"]}, - {"keywords":["(@aws-cdk/aws-autoscalingplans)","(aws-autoscalingplans)","(autoscalingplans)","(autoscaling plans)", "(autoscaling-plans)"],"labels":["@aws-cdk/aws-autoscalingplans"],"assignees":["rix0rrr"]}, + {"keywords":["(@aws-cdk/aws-autoscaling)","(aws-autoscaling)","(autoscaling)","(auto scaling)","(auto-scaling)"],"labels":["@aws-cdk/aws-autoscaling"],"assignees":["comcalvi"]}, + {"keywords":["(@aws-cdk/aws-autoscaling-api)","(aws-autoscaling-api)","(autoscaling-api)","(autoscaling api)","(autoscaling-api)"],"labels":["@aws-cdk/aws-autoscaling-api"],"assignees":["comcalvi"]}, + {"keywords":["(@aws-cdk/aws-autoscaling-common)","(aws-autoscaling-common)","(autoscaling-common)","(autoscaling common)","(autoscaling-common)"],"labels":["@aws-cdk/aws-autoscaling-common"],"assignees":["comcalvi"]}, + {"keywords":["(@aws-cdk/aws-autoscaling-hooktargets)","(aws-autoscaling-hooktargets)","(autoscaling-hooktargets)","(autoscaling hooktargets)"],"labels":["@aws-cdk/aws-autoscaling-hooktargets"],"assignees":["comcalvi"]}, + {"keywords":["(@aws-cdk/aws-autoscalingplans)","(aws-autoscalingplans)","(autoscalingplans)","(autoscaling plans)", "(autoscaling-plans)"],"labels":["@aws-cdk/aws-autoscalingplans"],"assignees":["comcalvi"]}, {"keywords":["(@aws-cdk/aws-backup)","(aws-backup)","(backup)"],"labels":["@aws-cdk/aws-backup"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/aws-batch)","(aws-batch)","(batch)"],"labels":["@aws-cdk/aws-batch"],"assignees":["madeline-k"]}, {"keywords":["(@aws-cdk/aws-budgets)","(aws-budgets)","(budgets)"],"labels":["@aws-cdk/aws-budgets"],"assignees":["njlynch"]}, From f2d77d336d535ef718813b4ed6b88b5d2af05cb9 Mon Sep 17 00:00:00 2001 From: kaizen3031593 <36202692+kaizen3031593@users.noreply.github.com> Date: Wed, 18 Aug 2021 20:17:08 -0400 Subject: [PATCH 67/99] revert(cli): 'deploy' and 'diff' silently does nothing when given unknown stack name (#16125) Broke integration tests when `synth`ing without providing a stack name reverts aws/aws-cdk#16073 --- packages/aws-cdk/lib/cdk-toolkit.ts | 10 +++------- packages/aws-cdk/test/cdk-toolkit.test.ts | 8 -------- packages/aws-cdk/test/diff.test.ts | 10 ---------- 3 files changed, 3 insertions(+), 25 deletions(-) diff --git a/packages/aws-cdk/lib/cdk-toolkit.ts b/packages/aws-cdk/lib/cdk-toolkit.ts index 8edefe66fc333..55ca1c6e24903 100644 --- a/packages/aws-cdk/lib/cdk-toolkit.ts +++ b/packages/aws-cdk/lib/cdk-toolkit.ts @@ -397,7 +397,7 @@ export class CdkToolkit { defaultBehavior: DefaultSelection.OnlySingle, }); - await this.validateStacks(stacks, selector.patterns); + await this.validateStacks(stacks); return stacks; } @@ -415,7 +415,7 @@ export class CdkToolkit { ? allStacks.filter(art => art.validateOnSynth ?? false) : new StackCollection(assembly, []); - await this.validateStacks(selectedForDiff.concat(autoValidateStacks), stackNames); + await this.validateStacks(selectedForDiff.concat(autoValidateStacks)); return selectedForDiff; } @@ -435,11 +435,7 @@ export class CdkToolkit { /** * Validate the stacks for errors and warnings according to the CLI's current settings */ - private async validateStacks(stacks: StackCollection, stackNames: string[]) { - if (stacks.stackCount == 0) { - throw new Error(`No stacks match the name(s) ${stackNames}`); - } - + private async validateStacks(stacks: StackCollection) { stacks.processMetadataMessages({ ignoreErrors: this.props.ignoreErrors, strict: this.props.strict, diff --git a/packages/aws-cdk/test/cdk-toolkit.test.ts b/packages/aws-cdk/test/cdk-toolkit.test.ts index f4573637ee5f4..8f53405b749e4 100644 --- a/packages/aws-cdk/test/cdk-toolkit.test.ts +++ b/packages/aws-cdk/test/cdk-toolkit.test.ts @@ -39,14 +39,6 @@ function defaultToolkitSetup() { } describe('deploy', () => { - test('fails when no valid stack names are given', async () => { - // GIVEN - const toolkit = defaultToolkitSetup(); - - // WHEN - await expect(() => toolkit.deploy({ selector: { patterns: ['Test-Stack-D'] } })).rejects.toThrow('No stacks match the name(s) Test-Stack-D'); - }); - describe('makes correct CloudFormation calls', () => { test('without options', async () => { // GIVEN diff --git a/packages/aws-cdk/test/diff.test.ts b/packages/aws-cdk/test/diff.test.ts index e14ebe9bd9779..c1bcd11c78caa 100644 --- a/packages/aws-cdk/test/diff.test.ts +++ b/packages/aws-cdk/test/diff.test.ts @@ -121,16 +121,6 @@ test('throws an error during diffs on stack with error metadata', async () => { })).rejects.toThrow(/Found errors/); }); -test('throws an error if no valid stack names given', async () => { - const buffer = new StringWritable(); - - // WHEN - await expect(() => toolkit.diff({ - stackNames: ['X', 'Y', 'Z'], - stream: buffer, - })).rejects.toThrow('No stacks match the name(s) X,Y,Z'); -}); - class StringWritable extends Writable { public data: string; private readonly _decoder: NodeStringDecoder; From 3b2c790c2b7d210868576540feab4e088376ab6c Mon Sep 17 00:00:00 2001 From: Pearcekieser <5055971+Pearcekieser@users.noreply.github.com> Date: Thu, 19 Aug 2021 02:19:49 -0700 Subject: [PATCH 68/99] fix(cli): Python init template does not work in directory with '-' (#15939) fixes #15938 Pytest error after init sample-app on directory "aws-data-pipeline" ``` E File "C:\Users\<...>\aws-data-pipeline\tests\unit\test_aws_data_pipe E from aws-data-pipeline.aws_data_pipeline_stack import AwsDataPipelineStack E ^ E SyntaxError: invalid syntax ``` See https://github.com/aws/aws-cdk/issues/15938 for detials I was having trouble getting the aws-cdk build and tests running in my dev env. I think its some issues trying to build the code on windows. Do you have any recommendations on how to best add a test for this change? ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../tests/unit/test_%name.PythonModule%_stack.template.py | 2 +- .../tests/unit/test_%name.PythonModule%_stack.template.py | 2 +- packages/aws-cdk/test/integ/init/test-python.sh | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/aws-cdk/lib/init-templates/v1/sample-app/python/tests/unit/test_%name.PythonModule%_stack.template.py b/packages/aws-cdk/lib/init-templates/v1/sample-app/python/tests/unit/test_%name.PythonModule%_stack.template.py index fab17d075ac44..182d07fe09855 100644 --- a/packages/aws-cdk/lib/init-templates/v1/sample-app/python/tests/unit/test_%name.PythonModule%_stack.template.py +++ b/packages/aws-cdk/lib/init-templates/v1/sample-app/python/tests/unit/test_%name.PythonModule%_stack.template.py @@ -2,7 +2,7 @@ import pytest from aws_cdk import core -from %name%.%name.PythonModule%_stack import %name.PascalCased%Stack +from %name.PythonModule%.%name.PythonModule%_stack import %name.PascalCased%Stack def get_template(): diff --git a/packages/aws-cdk/lib/init-templates/v2/sample-app/python/tests/unit/test_%name.PythonModule%_stack.template.py b/packages/aws-cdk/lib/init-templates/v2/sample-app/python/tests/unit/test_%name.PythonModule%_stack.template.py index 2b7e876b75742..b51a164ff8c5e 100644 --- a/packages/aws-cdk/lib/init-templates/v2/sample-app/python/tests/unit/test_%name.PythonModule%_stack.template.py +++ b/packages/aws-cdk/lib/init-templates/v2/sample-app/python/tests/unit/test_%name.PythonModule%_stack.template.py @@ -2,7 +2,7 @@ import pytest import aws_cdk_lib as core -from %name%.%name.PythonModule%_stack import %name.PascalCased%Stack +from %name.PythonModule%.%name.PythonModule%_stack import %name.PascalCased%Stack def get_template(): diff --git a/packages/aws-cdk/test/integ/init/test-python.sh b/packages/aws-cdk/test/integ/init/test-python.sh index 1f5163df5ae48..dd944e8369342 100755 --- a/packages/aws-cdk/test/integ/init/test-python.sh +++ b/packages/aws-cdk/test/integ/init/test-python.sh @@ -28,4 +28,5 @@ for template in $templates; do pip install -r requirements.txt cdk synth + pytest done From d42e89e01034dcba08c8f8ac0390a743143c4531 Mon Sep 17 00:00:00 2001 From: David Tucker Date: Thu, 19 Aug 2021 11:06:41 -0400 Subject: [PATCH 69/99] feat(s3-deployment): exclude and include filters (#16054) This construct only enables integration with the two existing CLI options (`--exclude` and `--include`) that are supported for the `s3 sync` command. There are a few situations where this can prove valuable: 1. Situations where you want to deploy a subset of files from an archive - This can be handled by leveraging the bundling option for a source, although in some situations the `exclude` filter would be significantly easier. 2. Situations where you want to leverage `prune` but have specific files excluded - This is the situation that cannot be solved with current tools. The most common scenario (and one I detailed in #14362 ) is where you manage a web app config file with a custom CloudFormation resource (to pass in API endpoint, user pool, etc...) and then manage a web application using this construct. Closes #14362 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../ec2/integ.environment-file.expected.json | 32 ++--- packages/@aws-cdk/aws-s3-deployment/README.md | 23 ++++ .../lib/bucket-deployment.ts | 25 ++++ .../aws-s3-deployment/lib/lambda/index.py | 14 +- .../test/bucket-deployment.test.ts | 76 +++++++++++ ...bucket-deployment-cloudfront.expected.json | 20 +-- .../integ.bucket-deployment.expected.json | 125 ++++++++++++++++-- .../test/integ.bucket-deployment.ts | 7 + .../aws-s3-deployment/test/lambda/aws | 9 +- .../aws-s3-deployment/test/lambda/test.py | 116 ++++++++++++++++ 10 files changed, 408 insertions(+), 39 deletions(-) diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/integ.environment-file.expected.json b/packages/@aws-cdk/aws-ecs/test/ec2/integ.environment-file.expected.json index c309c8a70f249..dc3aad690d805 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/integ.environment-file.expected.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/integ.environment-file.expected.json @@ -108,15 +108,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "Tags": [ { "Key": "Name", @@ -205,15 +205,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "Tags": [ { "Key": "Name", @@ -1219,7 +1219,7 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParametersc24b999656e4fe6c609c31bae56a1cf4717a405619c3aa6ba1bc686b8c2c86cfS3Bucket55EFA30C" + "Ref": "AssetParameters1f6de40da10b415b255c07df709f791e772ffb9f7bdd14ad81fb75643aad24eaS3BucketD8D20B9A" }, "S3Key": { "Fn::Join": [ @@ -1232,7 +1232,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParametersc24b999656e4fe6c609c31bae56a1cf4717a405619c3aa6ba1bc686b8c2c86cfS3VersionKey60329B70" + "Ref": "AssetParameters1f6de40da10b415b255c07df709f791e772ffb9f7bdd14ad81fb75643aad24eaS3VersionKeyCD2774D3" } ] } @@ -1245,7 +1245,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParametersc24b999656e4fe6c609c31bae56a1cf4717a405619c3aa6ba1bc686b8c2c86cfS3VersionKey60329B70" + "Ref": "AssetParameters1f6de40da10b415b255c07df709f791e772ffb9f7bdd14ad81fb75643aad24eaS3VersionKeyCD2774D3" } ] } @@ -1348,17 +1348,17 @@ "Type": "String", "Description": "Artifact hash for asset \"e9882ab123687399f934da0d45effe675ecc8ce13b40cb946f3e1d6141fe8d68\"" }, - "AssetParametersc24b999656e4fe6c609c31bae56a1cf4717a405619c3aa6ba1bc686b8c2c86cfS3Bucket55EFA30C": { + "AssetParameters1f6de40da10b415b255c07df709f791e772ffb9f7bdd14ad81fb75643aad24eaS3BucketD8D20B9A": { "Type": "String", - "Description": "S3 bucket for asset \"c24b999656e4fe6c609c31bae56a1cf4717a405619c3aa6ba1bc686b8c2c86cf\"" + "Description": "S3 bucket for asset \"1f6de40da10b415b255c07df709f791e772ffb9f7bdd14ad81fb75643aad24ea\"" }, - "AssetParametersc24b999656e4fe6c609c31bae56a1cf4717a405619c3aa6ba1bc686b8c2c86cfS3VersionKey60329B70": { + "AssetParameters1f6de40da10b415b255c07df709f791e772ffb9f7bdd14ad81fb75643aad24eaS3VersionKeyCD2774D3": { "Type": "String", - "Description": "S3 key for asset version \"c24b999656e4fe6c609c31bae56a1cf4717a405619c3aa6ba1bc686b8c2c86cf\"" + "Description": "S3 key for asset version \"1f6de40da10b415b255c07df709f791e772ffb9f7bdd14ad81fb75643aad24ea\"" }, - "AssetParametersc24b999656e4fe6c609c31bae56a1cf4717a405619c3aa6ba1bc686b8c2c86cfArtifactHash85F58E48": { + "AssetParameters1f6de40da10b415b255c07df709f791e772ffb9f7bdd14ad81fb75643aad24eaArtifactHash3943F7F3": { "Type": "String", - "Description": "Artifact hash for asset \"c24b999656e4fe6c609c31bae56a1cf4717a405619c3aa6ba1bc686b8c2c86cf\"" + "Description": "Artifact hash for asset \"1f6de40da10b415b255c07df709f791e772ffb9f7bdd14ad81fb75643aad24ea\"" }, "AssetParameters972240f9dd6e036a93d5f081af9a24315b2053828ac049b3b19b2fa12d7ae64aS3Bucket1F1A8472": { "Type": "String", @@ -1385,4 +1385,4 @@ "Description": "Artifact hash for asset \"872561bf078edd1685d50c9ff821cdd60d2b2ddfb0013c4087e79bf2bb50724d\"" } } -} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3-deployment/README.md b/packages/@aws-cdk/aws-s3-deployment/README.md index a896d55cfc575..74b31d98c41fd 100644 --- a/packages/@aws-cdk/aws-s3-deployment/README.md +++ b/packages/@aws-cdk/aws-s3-deployment/README.md @@ -138,6 +138,29 @@ new BucketDeployment(this, 'HTMLBucketDeployment', { }); ``` +## Exclude and Include Filters + +There are two points at which filters are evaluated in a deployment: asset bundling and the actual deployment. If you simply want to exclude files in the asset bundling process, you should leverage the `exclude` property of `AssetOptions` when defining your source: + +```ts +new BucketDeployment(this, 'HTMLBucketDeployment', { + sources: [Source.asset('./website', { exclude: ['*', '!index.html'] })], + destinationBucket: bucket, +}); +``` + +If you want to specify filters to be used in the deployment process, you can use the `exclude` and `include` filters on `BucketDeployment`. If excluded, these files will not be deployed to the destination bucket. In addition, if the file already exists in the destination bucket, it will not be deleted if you are using the `prune` option: + +```ts +new s3deploy.BucketDeployment(this, 'DeployButExcludeSpecificFiles', { + sources: [s3deploy.Source.asset(path.join(__dirname, 'my-website'))], + destinationBucket, + exclude: ['*.txt'] +}); +``` + +These filters follow the same format that is used for the AWS CLI. See the CLI documentation for information on [Using Include and Exclude Filters](https://docs.aws.amazon.com/cli/latest/reference/s3/index.html#use-of-exclude-and-include-filters). + ## Objects metadata You can specify metadata to be set on all the objects in your deployment. diff --git a/packages/@aws-cdk/aws-s3-deployment/lib/bucket-deployment.ts b/packages/@aws-cdk/aws-s3-deployment/lib/bucket-deployment.ts index 990a1ec359d0b..4281a82b74140 100644 --- a/packages/@aws-cdk/aws-s3-deployment/lib/bucket-deployment.ts +++ b/packages/@aws-cdk/aws-s3-deployment/lib/bucket-deployment.ts @@ -35,6 +35,29 @@ export interface BucketDeploymentProps { */ readonly destinationKeyPrefix?: string; + /** + * If this is set, matching files or objects will be excluded from the deployment's sync + * command. This can be used to exclude a file from being pruned in the destination bucket. + * + * If you want to just exclude files from the deployment package (which excludes these files + * evaluated when invalidating the asset), you should leverage the `exclude` property of + * `AssetOptions` when defining your source. + * + * @default - No exclude filters are used + * @see https://docs.aws.amazon.com/cli/latest/reference/s3/index.html#use-of-exclude-and-include-filters + */ + readonly exclude?: string[] + + /** + * If this is set, matching files or objects will be included with the deployment's sync + * command. Since all files from the deployment package are included by default, this property + * is usually leveraged alongside an `exclude` filter. + * + * @default - No include filters are used and all files are included with the sync command + * @see https://docs.aws.amazon.com/cli/latest/reference/s3/index.html#use-of-exclude-and-include-filters + */ + readonly include?: string[] + /** * If this is set to false, files in the destination bucket that * do not exist in the asset, will NOT be deleted during deployment (create/update). @@ -245,6 +268,8 @@ export class BucketDeployment extends CoreConstruct { DestinationBucketKeyPrefix: props.destinationKeyPrefix, RetainOnDelete: props.retainOnDelete, Prune: props.prune ?? true, + Exclude: props.exclude, + Include: props.include, UserMetadata: props.metadata ? mapUserMetadata(props.metadata) : undefined, SystemMetadata: mapSystemMetadata(props), DistributionId: props.distribution?.distributionId, diff --git a/packages/@aws-cdk/aws-s3-deployment/lib/lambda/index.py b/packages/@aws-cdk/aws-s3-deployment/lib/lambda/index.py index 3935e3122529d..ed7e1d9c5d7e9 100644 --- a/packages/@aws-cdk/aws-s3-deployment/lib/lambda/index.py +++ b/packages/@aws-cdk/aws-s3-deployment/lib/lambda/index.py @@ -49,6 +49,8 @@ def cfn_error(message=None): user_metadata = props.get('UserMetadata', {}) system_metadata = props.get('SystemMetadata', {}) prune = props.get('Prune', 'true').lower() == 'true' + exclude = props.get('Exclude', []) + include = props.get('Include', []) default_distribution_path = dest_bucket_prefix if not default_distribution_path.endswith("/"): @@ -100,7 +102,7 @@ def cfn_error(message=None): aws_command("s3", "rm", old_s3_dest, "--recursive") if request_type == "Update" or request_type == "Create": - s3_deploy(s3_source_zips, s3_dest, user_metadata, system_metadata, prune) + s3_deploy(s3_source_zips, s3_dest, user_metadata, system_metadata, prune, exclude, include) if distribution_id: cloudfront_invalidate(distribution_id, distribution_paths) @@ -114,7 +116,7 @@ def cfn_error(message=None): #--------------------------------------------------------------------------------------------------- # populate all files from s3_source_zips to a destination bucket -def s3_deploy(s3_source_zips, s3_dest, user_metadata, system_metadata, prune): +def s3_deploy(s3_source_zips, s3_dest, user_metadata, system_metadata, prune, exclude, include): # create a temporary working directory workdir=tempfile.mkdtemp() logger.info("| workdir: %s" % workdir) @@ -139,6 +141,14 @@ def s3_deploy(s3_source_zips, s3_dest, user_metadata, system_metadata, prune): if prune: s3_command.append("--delete") + if exclude: + for filter in exclude: + s3_command.extend(["--exclude", filter]) + + if include: + for filter in include: + s3_command.extend(["--include", filter]) + s3_command.extend([contents_dir, s3_dest]) s3_command.extend(create_metadata_args(user_metadata, system_metadata)) aws_command(*s3_command) diff --git a/packages/@aws-cdk/aws-s3-deployment/test/bucket-deployment.test.ts b/packages/@aws-cdk/aws-s3-deployment/test/bucket-deployment.test.ts index 19af404bbfa7b..cd40925261668 100644 --- a/packages/@aws-cdk/aws-s3-deployment/test/bucket-deployment.test.ts +++ b/packages/@aws-cdk/aws-s3-deployment/test/bucket-deployment.test.ts @@ -689,6 +689,82 @@ test('deploy without deleting missing files from destination', () => { }); }); +test('deploy with excluded files from destination', () => { + + // GIVEN + const stack = new cdk.Stack(); + const bucket = new s3.Bucket(stack, 'Dest'); + + // WHEN + new s3deploy.BucketDeployment(stack, 'Deploy', { + sources: [s3deploy.Source.asset(path.join(__dirname, 'my-website'))], + destinationBucket: bucket, + exclude: ['sample.js'], + }); + + expect(stack).toHaveResourceLike('Custom::CDKBucketDeployment', { + Exclude: ['sample.js'], + }); +}); + +test('deploy with included files from destination', () => { + + // GIVEN + const stack = new cdk.Stack(); + const bucket = new s3.Bucket(stack, 'Dest'); + + // WHEN + new s3deploy.BucketDeployment(stack, 'Deploy', { + sources: [s3deploy.Source.asset(path.join(__dirname, 'my-website'))], + destinationBucket: bucket, + include: ['sample.js'], + }); + + expect(stack).toHaveResourceLike('Custom::CDKBucketDeployment', { + Include: ['sample.js'], + }); +}); + +test('deploy with excluded and included files from destination', () => { + + // GIVEN + const stack = new cdk.Stack(); + const bucket = new s3.Bucket(stack, 'Dest'); + + // WHEN + new s3deploy.BucketDeployment(stack, 'Deploy', { + sources: [s3deploy.Source.asset(path.join(__dirname, 'my-website'))], + destinationBucket: bucket, + exclude: ['sample/*'], + include: ['sample/include.json'], + }); + + expect(stack).toHaveResourceLike('Custom::CDKBucketDeployment', { + Exclude: ['sample/*'], + Include: ['sample/include.json'], + }); +}); + +test('deploy with multiple exclude and include filters', () => { + + // GIVEN + const stack = new cdk.Stack(); + const bucket = new s3.Bucket(stack, 'Dest'); + + // WHEN + new s3deploy.BucketDeployment(stack, 'Deploy', { + sources: [s3deploy.Source.asset(path.join(__dirname, 'my-website'))], + destinationBucket: bucket, + exclude: ['sample/*', 'another/*'], + include: ['sample/include.json', 'another/include.json'], + }); + + expect(stack).toHaveResourceLike('Custom::CDKBucketDeployment', { + Exclude: ['sample/*', 'another/*'], + Include: ['sample/include.json', 'another/include.json'], + }); +}); + test('deployment allows vpc to be implicitly supplied to lambda', () => { // GIVEN diff --git a/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment-cloudfront.expected.json b/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment-cloudfront.expected.json index 76f906941f2bd..a0d375ee6e3a1 100644 --- a/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment-cloudfront.expected.json +++ b/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment-cloudfront.expected.json @@ -295,7 +295,7 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParametersc24b999656e4fe6c609c31bae56a1cf4717a405619c3aa6ba1bc686b8c2c86cfS3Bucket55EFA30C" + "Ref": "AssetParameters1f6de40da10b415b255c07df709f791e772ffb9f7bdd14ad81fb75643aad24eaS3BucketD8D20B9A" }, "S3Key": { "Fn::Join": [ @@ -308,7 +308,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParametersc24b999656e4fe6c609c31bae56a1cf4717a405619c3aa6ba1bc686b8c2c86cfS3VersionKey60329B70" + "Ref": "AssetParameters1f6de40da10b415b255c07df709f791e772ffb9f7bdd14ad81fb75643aad24eaS3VersionKeyCD2774D3" } ] } @@ -321,7 +321,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParametersc24b999656e4fe6c609c31bae56a1cf4717a405619c3aa6ba1bc686b8c2c86cfS3VersionKey60329B70" + "Ref": "AssetParameters1f6de40da10b415b255c07df709f791e772ffb9f7bdd14ad81fb75643aad24eaS3VersionKeyCD2774D3" } ] } @@ -365,17 +365,17 @@ "Type": "String", "Description": "Artifact hash for asset \"e9882ab123687399f934da0d45effe675ecc8ce13b40cb946f3e1d6141fe8d68\"" }, - "AssetParametersc24b999656e4fe6c609c31bae56a1cf4717a405619c3aa6ba1bc686b8c2c86cfS3Bucket55EFA30C": { + "AssetParameters1f6de40da10b415b255c07df709f791e772ffb9f7bdd14ad81fb75643aad24eaS3BucketD8D20B9A": { "Type": "String", - "Description": "S3 bucket for asset \"c24b999656e4fe6c609c31bae56a1cf4717a405619c3aa6ba1bc686b8c2c86cf\"" + "Description": "S3 bucket for asset \"1f6de40da10b415b255c07df709f791e772ffb9f7bdd14ad81fb75643aad24ea\"" }, - "AssetParametersc24b999656e4fe6c609c31bae56a1cf4717a405619c3aa6ba1bc686b8c2c86cfS3VersionKey60329B70": { + "AssetParameters1f6de40da10b415b255c07df709f791e772ffb9f7bdd14ad81fb75643aad24eaS3VersionKeyCD2774D3": { "Type": "String", - "Description": "S3 key for asset version \"c24b999656e4fe6c609c31bae56a1cf4717a405619c3aa6ba1bc686b8c2c86cf\"" + "Description": "S3 key for asset version \"1f6de40da10b415b255c07df709f791e772ffb9f7bdd14ad81fb75643aad24ea\"" }, - "AssetParametersc24b999656e4fe6c609c31bae56a1cf4717a405619c3aa6ba1bc686b8c2c86cfArtifactHash85F58E48": { + "AssetParameters1f6de40da10b415b255c07df709f791e772ffb9f7bdd14ad81fb75643aad24eaArtifactHash3943F7F3": { "Type": "String", - "Description": "Artifact hash for asset \"c24b999656e4fe6c609c31bae56a1cf4717a405619c3aa6ba1bc686b8c2c86cf\"" + "Description": "Artifact hash for asset \"1f6de40da10b415b255c07df709f791e772ffb9f7bdd14ad81fb75643aad24ea\"" }, "AssetParametersfc4481abf279255619ff7418faa5d24456fef3432ea0da59c95542578ff0222eS3Bucket9CD8B20A": { "Type": "String", @@ -390,4 +390,4 @@ "Description": "Artifact hash for asset \"fc4481abf279255619ff7418faa5d24456fef3432ea0da59c95542578ff0222e\"" } } -} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.expected.json b/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.expected.json index 877298773816b..320bf196acb7b 100644 --- a/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.expected.json +++ b/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.expected.json @@ -304,7 +304,7 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParametersc24b999656e4fe6c609c31bae56a1cf4717a405619c3aa6ba1bc686b8c2c86cfS3Bucket55EFA30C" + "Ref": "AssetParameters1f6de40da10b415b255c07df709f791e772ffb9f7bdd14ad81fb75643aad24eaS3BucketD8D20B9A" }, "S3Key": { "Fn::Join": [ @@ -317,7 +317,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParametersc24b999656e4fe6c609c31bae56a1cf4717a405619c3aa6ba1bc686b8c2c86cfS3VersionKey60329B70" + "Ref": "AssetParameters1f6de40da10b415b255c07df709f791e772ffb9f7bdd14ad81fb75643aad24eaS3VersionKeyCD2774D3" } ] } @@ -330,7 +330,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParametersc24b999656e4fe6c609c31bae56a1cf4717a405619c3aa6ba1bc686b8c2c86cfS3VersionKey60329B70" + "Ref": "AssetParameters1f6de40da10b415b255c07df709f791e772ffb9f7bdd14ad81fb75643aad24eaS3VersionKeyCD2774D3" } ] } @@ -685,6 +685,111 @@ }, "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" + }, + "DeployMeWithExcludedFilesOnDestinationAwsCliLayer68F5E11D": { + "Type": "AWS::Lambda::LayerVersion", + "Properties": { + "Content": { + "S3Bucket": { + "Ref": "AssetParameterse9882ab123687399f934da0d45effe675ecc8ce13b40cb946f3e1d6141fe8d68S3BucketAEADE8C7" + }, + "S3Key": { + "Fn::Join": [ + "", + [ + { + "Fn::Select": [ + 0, + { + "Fn::Split": [ + "||", + { + "Ref": "AssetParameterse9882ab123687399f934da0d45effe675ecc8ce13b40cb946f3e1d6141fe8d68S3VersionKeyE415415F" + } + ] + } + ] + }, + { + "Fn::Select": [ + 1, + { + "Fn::Split": [ + "||", + { + "Ref": "AssetParameterse9882ab123687399f934da0d45effe675ecc8ce13b40cb946f3e1d6141fe8d68S3VersionKeyE415415F" + } + ] + } + ] + } + ] + ] + } + }, + "Description": "/opt/awscli/aws" + } + }, + "DeployMeWithExcludedFilesOnDestinationCustomResource48D69581": { + "Type": "Custom::CDKBucketDeployment", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C81C01536", + "Arn" + ] + }, + "SourceBucketNames": [ + { + "Ref": "AssetParametersfc4481abf279255619ff7418faa5d24456fef3432ea0da59c95542578ff0222eS3Bucket9CD8B20A" + } + ], + "SourceObjectKeys": [ + { + "Fn::Join": [ + "", + [ + { + "Fn::Select": [ + 0, + { + "Fn::Split": [ + "||", + { + "Ref": "AssetParametersfc4481abf279255619ff7418faa5d24456fef3432ea0da59c95542578ff0222eS3VersionKeyA58D380C" + } + ] + } + ] + }, + { + "Fn::Select": [ + 1, + { + "Fn::Split": [ + "||", + { + "Ref": "AssetParametersfc4481abf279255619ff7418faa5d24456fef3432ea0da59c95542578ff0222eS3VersionKeyA58D380C" + } + ] + } + ] + } + ] + ] + } + ], + "DestinationBucketName": { + "Ref": "Destination920A3C57" + }, + "RetainOnDelete": false, + "Prune": true, + "Exclude": [ + "*.gif" + ] + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" } }, "Parameters": { @@ -700,17 +805,17 @@ "Type": "String", "Description": "Artifact hash for asset \"e9882ab123687399f934da0d45effe675ecc8ce13b40cb946f3e1d6141fe8d68\"" }, - "AssetParametersc24b999656e4fe6c609c31bae56a1cf4717a405619c3aa6ba1bc686b8c2c86cfS3Bucket55EFA30C": { + "AssetParameters1f6de40da10b415b255c07df709f791e772ffb9f7bdd14ad81fb75643aad24eaS3BucketD8D20B9A": { "Type": "String", - "Description": "S3 bucket for asset \"c24b999656e4fe6c609c31bae56a1cf4717a405619c3aa6ba1bc686b8c2c86cf\"" + "Description": "S3 bucket for asset \"1f6de40da10b415b255c07df709f791e772ffb9f7bdd14ad81fb75643aad24ea\"" }, - "AssetParametersc24b999656e4fe6c609c31bae56a1cf4717a405619c3aa6ba1bc686b8c2c86cfS3VersionKey60329B70": { + "AssetParameters1f6de40da10b415b255c07df709f791e772ffb9f7bdd14ad81fb75643aad24eaS3VersionKeyCD2774D3": { "Type": "String", - "Description": "S3 key for asset version \"c24b999656e4fe6c609c31bae56a1cf4717a405619c3aa6ba1bc686b8c2c86cf\"" + "Description": "S3 key for asset version \"1f6de40da10b415b255c07df709f791e772ffb9f7bdd14ad81fb75643aad24ea\"" }, - "AssetParametersc24b999656e4fe6c609c31bae56a1cf4717a405619c3aa6ba1bc686b8c2c86cfArtifactHash85F58E48": { + "AssetParameters1f6de40da10b415b255c07df709f791e772ffb9f7bdd14ad81fb75643aad24eaArtifactHash3943F7F3": { "Type": "String", - "Description": "Artifact hash for asset \"c24b999656e4fe6c609c31bae56a1cf4717a405619c3aa6ba1bc686b8c2c86cf\"" + "Description": "Artifact hash for asset \"1f6de40da10b415b255c07df709f791e772ffb9f7bdd14ad81fb75643aad24ea\"" }, "AssetParametersfc4481abf279255619ff7418faa5d24456fef3432ea0da59c95542578ff0222eS3Bucket9CD8B20A": { "Type": "String", @@ -725,4 +830,4 @@ "Description": "Artifact hash for asset \"fc4481abf279255619ff7418faa5d24456fef3432ea0da59c95542578ff0222e\"" } } -} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.ts b/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.ts index b2b1754083bd7..b6f20f62e6024 100644 --- a/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.ts +++ b/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.ts @@ -46,6 +46,13 @@ class TestBucketDeployment extends cdk.Stack { retainOnDelete: false, }); + new s3deploy.BucketDeployment(this, 'DeployMeWithExcludedFilesOnDestination', { + sources: [s3deploy.Source.asset(path.join(__dirname, 'my-website'))], + destinationBucket, + exclude: ['*.gif'], + retainOnDelete: false, + }); + } } diff --git a/packages/@aws-cdk/aws-s3-deployment/test/lambda/aws b/packages/@aws-cdk/aws-s3-deployment/test/lambda/aws index 969bb982cd08c..5cfd9275eeb71 100755 --- a/packages/@aws-cdk/aws-s3-deployment/test/lambda/aws +++ b/packages/@aws-cdk/aws-s3-deployment/test/lambda/aws @@ -21,7 +21,14 @@ if sys.argv[2] == "cp" and not sys.argv[4].startswith("s3://"): sys.argv[4] = "archive.zip" if sys.argv[2] == "sync": - sys.argv[4 if '--delete' in sys.argv else 3] = "contents.zip" + contentsIdx = 3 + if '--include' in sys.argv: + contentsIdx += sys.argv.count("--include") * 2 + if '--exclude' in sys.argv: + contentsIdx += sys.argv.count("--exclude") * 2 + if '--delete' in sys.argv: + contentsIdx += 1 + sys.argv[contentsIdx] = "contents.zip" with open("./aws.out", "a") as myfile: myfile.write(json.dumps(sys.argv[1:]) + "\n") diff --git a/packages/@aws-cdk/aws-s3-deployment/test/lambda/test.py b/packages/@aws-cdk/aws-s3-deployment/test/lambda/test.py index 7813a13db3859..c7a371fafa01e 100644 --- a/packages/@aws-cdk/aws-s3-deployment/test/lambda/test.py +++ b/packages/@aws-cdk/aws-s3-deployment/test/lambda/test.py @@ -68,6 +68,122 @@ def test_update_no_delete(self): ["s3", "sync", "contents.zip", "s3:///"] ) + def test_create_exclude(self): + invoke_handler("Create", { + "SourceBucketNames": [""], + "SourceObjectKeys": [""], + "DestinationBucketName": "", + "Exclude": ["sample.json"] + }) + + self.assertAwsCommands( + ["s3", "cp", "s3:///", "archive.zip"], + ["s3", "sync", "--delete", "--exclude", "sample.json", "contents.zip", "s3:///"] + ) + + def test_update_exclude(self): + invoke_handler("Update", { + "SourceBucketNames": [""], + "SourceObjectKeys": [""], + "DestinationBucketName": "", + "Exclude": ["sample.json"] + }, old_resource_props={ + "DestinationBucketName": "", + }, physical_id="") + + self.assertAwsCommands( + ["s3", "cp", "s3:///", "archive.zip"], + ["s3", "sync", "--delete", "--exclude", "sample.json", "contents.zip", "s3:///"] + ) + + def test_create_include(self): + invoke_handler("Create", { + "SourceBucketNames": [""], + "SourceObjectKeys": [""], + "DestinationBucketName": "", + "Include": ["/sample/*.json"] + }) + + self.assertAwsCommands( + ["s3", "cp", "s3:///", "archive.zip"], + ["s3", "sync", "--delete", "--include", "/sample/*.json", "contents.zip", "s3:///"] + ) + + def test_update_include(self): + invoke_handler("Update", { + "SourceBucketNames": [""], + "SourceObjectKeys": [""], + "DestinationBucketName": "", + "Include": ["/sample/*.json"] + }, old_resource_props={ + "DestinationBucketName": "", + }, physical_id="") + + self.assertAwsCommands( + ["s3", "cp", "s3:///", "archive.zip"], + ["s3", "sync", "--delete", "--include", "/sample/*.json", "contents.zip", "s3:///"] + ) + + def test_create_include_exclude(self): + invoke_handler("Create", { + "SourceBucketNames": [""], + "SourceObjectKeys": [""], + "DestinationBucketName": "", + "Exclude": ["/sample/*"], + "Include": ["/sample/*.json"] + }) + + self.assertAwsCommands( + ["s3", "cp", "s3:///", "archive.zip"], + ["s3", "sync", "--delete", "--exclude", "/sample/*", "--include", "/sample/*.json", "contents.zip", "s3:///"] + ) + + def test_update_include_exclude(self): + invoke_handler("Update", { + "SourceBucketNames": [""], + "SourceObjectKeys": [""], + "DestinationBucketName": "", + "Exclude": ["/sample/*"], + "Include": ["/sample/*.json"] + }, old_resource_props={ + "DestinationBucketName": "", + }, physical_id="") + + self.assertAwsCommands( + ["s3", "cp", "s3:///", "archive.zip"], + ["s3", "sync", "--delete", "--exclude", "/sample/*", "--include", "/sample/*.json", "contents.zip", "s3:///"] + ) + + def test_create_multiple_include_exclude(self): + invoke_handler("Create", { + "SourceBucketNames": [""], + "SourceObjectKeys": [""], + "DestinationBucketName": "", + "Exclude": ["/sample/*", "/another/*"], + "Include": ["/sample/*.json", "/another/*.json"] + }) + + self.assertAwsCommands( + ["s3", "cp", "s3:///", "archive.zip"], + ["s3", "sync", "--delete", "--exclude", "/sample/*", "--exclude", "/another/*", "--include", "/sample/*.json", "--include", "/another/*.json", "contents.zip", "s3:///"] + ) + + def test_update_multiple_include_exclude(self): + invoke_handler("Update", { + "SourceBucketNames": [""], + "SourceObjectKeys": [""], + "DestinationBucketName": "", + "Exclude": ["/sample/*", "/another/*"], + "Include": ["/sample/*.json", "/another/*.json"] + }, old_resource_props={ + "DestinationBucketName": "", + }, physical_id="") + + self.assertAwsCommands( + ["s3", "cp", "s3:///", "archive.zip"], + ["s3", "sync", "--delete", "--exclude", "/sample/*", "--exclude", "/another/*", "--include", "/sample/*.json", "--include", "/another/*.json", "contents.zip", "s3:///"] + ) + def test_create_update_multiple_sources(self): invoke_handler("Create", { "SourceBucketNames": ["", ""], From 0f7c0b421327f1ffed28de79692191af187f23ca Mon Sep 17 00:00:00 2001 From: Ben Chaimberg Date: Thu, 19 Aug 2021 09:36:34 -0700 Subject: [PATCH 70/99] fix(cli): unknown command pytest in build container fails integration tests (#16134) Erroneously added in #15939 ---- *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/init/test-python.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/aws-cdk/test/integ/init/test-python.sh b/packages/aws-cdk/test/integ/init/test-python.sh index dd944e8369342..1f5163df5ae48 100755 --- a/packages/aws-cdk/test/integ/init/test-python.sh +++ b/packages/aws-cdk/test/integ/init/test-python.sh @@ -28,5 +28,4 @@ for template in $templates; do pip install -r requirements.txt cdk synth - pytest done From 436540f85aedfdcea78b67a0aded9505a93cd8f3 Mon Sep 17 00:00:00 2001 From: Massimo Prencipe Date: Thu, 19 Aug 2021 21:30:22 +0300 Subject: [PATCH 71/99] docs(apigateway): @see tag doesn't work with the @deprecated tag in docs (#16136) fix: Remove @see tag that doesn't work with the @deprecated tag. Fixes: #16100 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/@aws-cdk/aws-apigateway/lib/model.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/aws-apigateway/lib/model.ts b/packages/@aws-cdk/aws-apigateway/lib/model.ts index 277c0e4fa20b7..9e4f4cb12c1a4 100644 --- a/packages/@aws-cdk/aws-apigateway/lib/model.ts +++ b/packages/@aws-cdk/aws-apigateway/lib/model.ts @@ -30,7 +30,7 @@ export interface IModel { * } * * @see https://docs.amazonaws.cn/en_us/apigateway/latest/developerguide/models-mappings.html#models-mappings-models - * @deprecated You should use @see Model.EMPTY_MODEL + * @deprecated You should use Model.EMPTY_MODEL */ export class EmptyModel implements IModel { public readonly modelId = 'Empty'; @@ -51,7 +51,7 @@ export class EmptyModel implements IModel { * "message" : { "type" : "string" } * } * } - * @deprecated You should use @see Model.ERROR_MODEL + * @deprecated You should use Model.ERROR_MODEL */ export class ErrorModel implements IModel { public readonly modelId = 'Error'; From bf13891c59e6804a150471542af601ae4ccee803 Mon Sep 17 00:00:00 2001 From: Clarence Date: Fri, 20 Aug 2021 05:23:32 +0800 Subject: [PATCH 72/99] docs(ecs): Fix ecs readme sample (#16058) Sample code missing parentheses ---- *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/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-ecs/README.md b/packages/@aws-cdk/aws-ecs/README.md index 180710a7e2cb3..e3c7f900b58a2 100644 --- a/packages/@aws-cdk/aws-ecs/README.md +++ b/packages/@aws-cdk/aws-ecs/README.md @@ -854,7 +854,7 @@ cluster.addAsgCapacityProvider(capacityProvider); const taskDefinition = new ecs.Ec2TaskDefinition(stack, 'TaskDef'); taskDefinition.addContainer('web', { - image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample', + image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), memoryReservationMiB: 256, }); From 8b9e5163e2844726e1656a9c13bdf03b7f1a89d2 Mon Sep 17 00:00:00 2001 From: Juan Lulkin Date: Fri, 20 Aug 2021 00:04:46 +0200 Subject: [PATCH 73/99] docs(eks): change serviceAccount variable name (#16090) ---- *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-eks/README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/@aws-cdk/aws-eks/README.md b/packages/@aws-cdk/aws-eks/README.md index 7e1d7ebb8ad04..1437446e6640a 100644 --- a/packages/@aws-cdk/aws-eks/README.md +++ b/packages/@aws-cdk/aws-eks/README.md @@ -740,7 +740,7 @@ With services account you can provide Kubernetes Pods access to AWS resources. ```ts // add service account -const sa = cluster.addServiceAccount('MyServiceAccount'); +const serviceAccount = cluster.addServiceAccount('MyServiceAccount'); const bucket = new Bucket(this, 'Bucket'); bucket.grantReadWrite(serviceAccount); @@ -750,7 +750,7 @@ const mypod = cluster.addManifest('mypod', { kind: 'Pod', metadata: { name: 'mypod' }, spec: { - serviceAccountName: sa.serviceAccountName + serviceAccountName: serviceAccount.serviceAccountName containers: [ { name: 'hello', @@ -763,13 +763,13 @@ const mypod = cluster.addManifest('mypod', { }); // create the resource after the service account. -mypod.node.addDependency(sa); +mypod.node.addDependency(serviceAccount); // print the IAM role arn for this service account -new cdk.CfnOutput(this, 'ServiceAccountIamRole', { value: sa.role.roleArn }) +new cdk.CfnOutput(this, 'ServiceAccountIamRole', { value: serviceAccount.role.roleArn }) ``` -Note that using `sa.serviceAccountName` above **does not** translate into a resource dependency. +Note that using `serviceAccount.serviceAccountName` above **does not** translate into a resource dependency. This is why an explicit dependency is needed. See for more details. You can also add service accounts to existing clusters. @@ -788,7 +788,7 @@ const cluster = eks.Cluster.fromClusterAttributes({ kubectlRoleArn: 'arn:aws:iam::123456:role/service-role/k8sservicerole', }); -const sa = cluster.addServiceAccount('MyServiceAccount'); +const serviceAccount = cluster.addServiceAccount('MyServiceAccount'); const bucket = new Bucket(this, 'Bucket'); bucket.grantReadWrite(serviceAccount); From 5de41faebd9322ac76e8f90fa249304b0bf83050 Mon Sep 17 00:00:00 2001 From: Damien Gallagher Date: Thu, 19 Aug 2021 23:45:58 +0100 Subject: [PATCH 74/99] chore: added links to the relevant aws cdk workshop tutorials in sample-app readme for the various languages (#16042) When getting started with the AWS CDK, it is useful to have links to a good tutorial to help learn the tool. This pr adds links to the generated README.md files in order to access the CDK Workshops. This is a trivial addition but may help folks who are unaware that the CDK Workshops exist --- .../init-templates/v1/sample-app/csharp/README.template.md | 3 +++ .../lib/init-templates/v1/sample-app/java/README.template.md | 4 ++++ .../v1/sample-app/javascript/README.template.md | 3 +++ .../init-templates/v1/sample-app/python/README.template.md | 3 +++ .../v1/sample-app/typescript/README.template.md | 4 ++++ 5 files changed, 17 insertions(+) diff --git a/packages/aws-cdk/lib/init-templates/v1/sample-app/csharp/README.template.md b/packages/aws-cdk/lib/init-templates/v1/sample-app/csharp/README.template.md index 411d4e653994e..a9915823b7a48 100644 --- a/packages/aws-cdk/lib/init-templates/v1/sample-app/csharp/README.template.md +++ b/packages/aws-cdk/lib/init-templates/v1/sample-app/csharp/README.template.md @@ -7,6 +7,9 @@ The `cdk.json` file tells the CDK Toolkit how to execute your app. It uses the [.NET Core CLI](https://docs.microsoft.com/dotnet/articles/core/) to compile and execute your project. +## Tutorial +See [this useful workshop](https://cdkworkshop.com/40-dotnet.html) on working with the AWS CDK for C# projects. + ## Useful commands * `dotnet build src` compile this app diff --git a/packages/aws-cdk/lib/init-templates/v1/sample-app/java/README.template.md b/packages/aws-cdk/lib/init-templates/v1/sample-app/java/README.template.md index ecbdec164e29e..d73d043e81c0e 100644 --- a/packages/aws-cdk/lib/init-templates/v1/sample-app/java/README.template.md +++ b/packages/aws-cdk/lib/init-templates/v1/sample-app/java/README.template.md @@ -7,6 +7,10 @@ The `cdk.json` file tells the CDK Toolkit how to execute your app. It is a [Maven](https://maven.apache.org/) based project, so you can open this project with any Maven compatible Java IDE to build and run tests. +## Tutorial +See [this useful workshop](https://cdkworkshop.com/50-java.html) on working with the AWS CDK for Java projects. + + ## Useful commands * `mvn package` compile and run tests diff --git a/packages/aws-cdk/lib/init-templates/v1/sample-app/javascript/README.template.md b/packages/aws-cdk/lib/init-templates/v1/sample-app/javascript/README.template.md index 4963f41f7463e..6460007f8e51c 100644 --- a/packages/aws-cdk/lib/init-templates/v1/sample-app/javascript/README.template.md +++ b/packages/aws-cdk/lib/init-templates/v1/sample-app/javascript/README.template.md @@ -5,6 +5,9 @@ which contains an Amazon SQS queue that is subscribed to an Amazon SNS topic. The `cdk.json` file tells the CDK Toolkit how to execute your app. The build step is not required when using JavaScript. +## Tutorial +See [this useful workshop](https://cdkworkshop.com/20-typescript.html) on working with the AWS CDK for Typescript projects. + ## Useful commands * `npm run test` perform the jest unit tests diff --git a/packages/aws-cdk/lib/init-templates/v1/sample-app/python/README.template.md b/packages/aws-cdk/lib/init-templates/v1/sample-app/python/README.template.md index 1775b25f602ae..0b737ad6a5651 100644 --- a/packages/aws-cdk/lib/init-templates/v1/sample-app/python/README.template.md +++ b/packages/aws-cdk/lib/init-templates/v1/sample-app/python/README.template.md @@ -54,6 +54,9 @@ To add additional dependencies, for example other CDK libraries, just add to your requirements.txt file and rerun the `pip install -r requirements.txt` command. +## Tutorial +See [this useful workshop](https://cdkworkshop.com/30-python.html) on working with the AWS CDK for Python projects. + ## Useful commands * `cdk ls` list all stacks in the app diff --git a/packages/aws-cdk/lib/init-templates/v1/sample-app/typescript/README.template.md b/packages/aws-cdk/lib/init-templates/v1/sample-app/typescript/README.template.md index 56b7b636bd523..90cd6c08373e2 100644 --- a/packages/aws-cdk/lib/init-templates/v1/sample-app/typescript/README.template.md +++ b/packages/aws-cdk/lib/init-templates/v1/sample-app/typescript/README.template.md @@ -5,6 +5,10 @@ which contains an Amazon SQS queue that is subscribed to an Amazon SNS topic. The `cdk.json` file tells the CDK Toolkit how to execute your app. +## Tutorial +See [this useful workshop](https://cdkworkshop.com/20-typescript.html) on working with the AWS CDK for Typescript projects. + + ## Useful commands * `npm run build` compile typescript to js From cb3b7ea1644dad98fcf9e3543ed347e9e53ba09d Mon Sep 17 00:00:00 2001 From: Chauncey Garrett Date: Fri, 20 Aug 2021 05:38:58 -0500 Subject: [PATCH 75/99] chore(eks): bad indent in kubectl apply handler (#16106) ---- *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/kubectl-handler/apply/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/aws-eks/lib/kubectl-handler/apply/__init__.py b/packages/@aws-cdk/aws-eks/lib/kubectl-handler/apply/__init__.py index 80e9a7891481e..8498ccaaa6cc2 100644 --- a/packages/@aws-cdk/aws-eks/lib/kubectl-handler/apply/__init__.py +++ b/packages/@aws-cdk/aws-eks/lib/kubectl-handler/apply/__init__.py @@ -81,8 +81,8 @@ def kubectl(verb, file, *opts): except subprocess.CalledProcessError as exc: output = exc.output if b'i/o timeout' in output and retry > 0: - retry = retry - 1 - logger.info("kubectl timed out, retries left: %s" % retry) + retry = retry - 1 + logger.info("kubectl timed out, retries left: %s" % retry) else: raise Exception(output) else: From 683ed7ebd3a212054ec5b9178b9583bb1e3e2332 Mon Sep 17 00:00:00 2001 From: Doggy Date: Fri, 20 Aug 2021 06:38:49 -0500 Subject: [PATCH 76/99] chore(appsync): Correct VTL for aurora Serverless (#15874) docs: correct spelling of CHANGELOGThe old vtl will result in "unable to convert to object" ---- *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 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/aws-appsync/README.md b/packages/@aws-cdk/aws-appsync/README.md index 3dbf2e27a277b..0145beae621f6 100644 --- a/packages/@aws-cdk/aws-appsync/README.md +++ b/packages/@aws-cdk/aws-appsync/README.md @@ -135,7 +135,7 @@ rdsDS.createResolver({ } `), responseMappingTemplate: MappingTemplate.fromString(` - $util.rds.toJsonObject($ctx.result) + $utils.toJson($utils.rds.toJsonObject($ctx.result)[0]) `), }); @@ -157,7 +157,7 @@ rdsDS.createResolver({ } `), responseMappingTemplate: MappingTemplate.fromString(` - $util.rds.toJsonObject($ctx.result) + $utils.toJson($utils.rds.toJsonObject($ctx.result)[1][0]) `), }); ``` From 82dd2822a86431d0aa0be896550d421810b80c67 Mon Sep 17 00:00:00 2001 From: Blazej Siejek <40015521+mrsiejas@users.noreply.github.com> Date: Fri, 20 Aug 2021 15:30:09 +0200 Subject: [PATCH 77/99] fix: KubectlHandler - insecure kubeconfig warning (#16063) KubectlHandler started to return insecure kubeconfig file warning starting Kubernetes 1.20 ``` 2:08:24 PM | CREATE_FAILED | Custom::AWSCDK-EKS-HelmChart | NginxIngressController/Resource/Default Received response status [FAILED] from custom resource. Message returned: Error: b'WARNING: Kubernetes configuration file is group-readable. This is insecure. Location: /tmp/kubeconfig\nWARNING: Kubernetes configuration file is world-readable. This is insecure. Location: /tmp/kubeconfig\nError: UPGRADE FAILED: an other operation (install/upgrade/rollback) is in progress\n' ``` Fix changes permissions of the file to read and write for the User and removes permissions for Group and Others. Fixes #14560 ---- *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/kubectl-handler/apply/__init__.py | 4 ++++ packages/@aws-cdk/aws-eks/lib/kubectl-handler/get/__init__.py | 4 ++++ .../@aws-cdk/aws-eks/lib/kubectl-handler/helm/__init__.py | 4 ++++ .../@aws-cdk/aws-eks/lib/kubectl-handler/patch/__init__.py | 4 ++++ 4 files changed, 16 insertions(+) diff --git a/packages/@aws-cdk/aws-eks/lib/kubectl-handler/apply/__init__.py b/packages/@aws-cdk/aws-eks/lib/kubectl-handler/apply/__init__.py index 8498ccaaa6cc2..038d379f8478a 100644 --- a/packages/@aws-cdk/aws-eks/lib/kubectl-handler/apply/__init__.py +++ b/packages/@aws-cdk/aws-eks/lib/kubectl-handler/apply/__init__.py @@ -12,6 +12,7 @@ outdir = os.environ.get('TEST_OUTDIR', '/tmp') kubeconfig = os.path.join(outdir, 'kubeconfig') + def apply_handler(event, context): logger.info(json.dumps(event)) @@ -35,6 +36,9 @@ def apply_handler(event, context): logger.info(f'Running command: {cmd}') subprocess.check_call(cmd) + if os.path.isfile(kubeconfig): + os.chmod(kubeconfig, 0o600) + # write resource manifests in sequence: { r1 }{ r2 }{ r3 } (this is how # a stream of JSON objects can be included in a k8s manifest). manifest_list = json.loads(manifest_text) diff --git a/packages/@aws-cdk/aws-eks/lib/kubectl-handler/get/__init__.py b/packages/@aws-cdk/aws-eks/lib/kubectl-handler/get/__init__.py index 6058c8371e5bd..4fb3b162765ca 100644 --- a/packages/@aws-cdk/aws-eks/lib/kubectl-handler/get/__init__.py +++ b/packages/@aws-cdk/aws-eks/lib/kubectl-handler/get/__init__.py @@ -13,6 +13,7 @@ outdir = os.environ.get('TEST_OUTDIR', '/tmp') kubeconfig = os.path.join(outdir, 'kubeconfig') + def get_handler(event, context): logger.info(json.dumps(event)) @@ -30,6 +31,9 @@ def get_handler(event, context): '--kubeconfig', kubeconfig ]) + if os.path.isfile(kubeconfig): + os.chmod(kubeconfig, 0o600) + object_type = props['ObjectType'] object_name = props['ObjectName'] object_namespace = props['ObjectNamespace'] diff --git a/packages/@aws-cdk/aws-eks/lib/kubectl-handler/helm/__init__.py b/packages/@aws-cdk/aws-eks/lib/kubectl-handler/helm/__init__.py index 67171b11aeede..17208a075d01f 100644 --- a/packages/@aws-cdk/aws-eks/lib/kubectl-handler/helm/__init__.py +++ b/packages/@aws-cdk/aws-eks/lib/kubectl-handler/helm/__init__.py @@ -12,6 +12,7 @@ outdir = os.environ.get('TEST_OUTDIR', '/tmp') kubeconfig = os.path.join(outdir, 'kubeconfig') + def helm_handler(event, context): logger.info(json.dumps(event)) @@ -38,6 +39,9 @@ def helm_handler(event, context): '--kubeconfig', kubeconfig ]) + if os.path.isfile(kubeconfig): + os.chmod(kubeconfig, 0o600) + # Write out the values to a file and include them with the install and upgrade values_file = None if not request_type == "Delete" and not values_text is None: diff --git a/packages/@aws-cdk/aws-eks/lib/kubectl-handler/patch/__init__.py b/packages/@aws-cdk/aws-eks/lib/kubectl-handler/patch/__init__.py index 6597341a4806d..a18455663b7f3 100644 --- a/packages/@aws-cdk/aws-eks/lib/kubectl-handler/patch/__init__.py +++ b/packages/@aws-cdk/aws-eks/lib/kubectl-handler/patch/__init__.py @@ -12,6 +12,7 @@ outdir = os.environ.get('TEST_OUTDIR', '/tmp') kubeconfig = os.path.join(outdir, 'kubeconfig') + def patch_handler(event, context): logger.info(json.dumps(event)) @@ -29,6 +30,9 @@ def patch_handler(event, context): '--kubeconfig', kubeconfig ]) + if os.path.isfile(kubeconfig): + os.chmod(kubeconfig, 0o600) + resource_name = props['ResourceName'] resource_namespace = props['ResourceNamespace'] apply_patch_json = props['ApplyPatchJson'] From 82e4b4f07be202e2d6c6afa4f9ed0d9d6146f0a8 Mon Sep 17 00:00:00 2001 From: Ben Chaimberg Date: Mon, 23 Aug 2021 06:26:05 -0700 Subject: [PATCH 78/99] fix(cfnspec): changes to resource-level documentation not supported (#16170) Internal reference: V417958316 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/@aws-cdk/cfnspec/build-tools/spec-diff.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/@aws-cdk/cfnspec/build-tools/spec-diff.ts b/packages/@aws-cdk/cfnspec/build-tools/spec-diff.ts index f4aa0ee7daab3..6b5a0d6d466f9 100644 --- a/packages/@aws-cdk/cfnspec/build-tools/spec-diff.ts +++ b/packages/@aws-cdk/cfnspec/build-tools/spec-diff.ts @@ -106,6 +106,11 @@ async function main() { }); } break; + case 'Documentation': + describeChanges(resourceType, key, update.Documentation).forEach(change => { + attributeChanges.push(change); + }); + break; default: throw new Error(`Unexpected update to ${resourceType}: ${key}`); } From 677fedcc5351b8b5346970fac03e5e342f36265b Mon Sep 17 00:00:00 2001 From: Otavio Macedo Date: Mon, 23 Aug 2021 15:09:12 +0100 Subject: [PATCH 79/99] fix(ses): drop spam rule appears in the incorrect order (#16146) The auto-generated drop spam rule should come before all user-defined rules. If an email is classified as spam, it should stop the processing of all other rules. Fixes #16091 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../@aws-cdk/aws-ses/lib/receipt-rule-set.ts | 6 ++-- .../aws-ses/test/test.receipt-rule-set.ts | 35 +++++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk/aws-ses/lib/receipt-rule-set.ts b/packages/@aws-cdk/aws-ses/lib/receipt-rule-set.ts index dcb3d011d4251..d8590216f2460 100644 --- a/packages/@aws-cdk/aws-ses/lib/receipt-rule-set.ts +++ b/packages/@aws-cdk/aws-ses/lib/receipt-rule-set.ts @@ -109,12 +109,12 @@ export class ReceiptRuleSet extends ReceiptRuleSetBase { this.receiptRuleSetName = resource.ref; if (props) { - const rules = props.rules || []; - rules.forEach((ruleOption, idx) => this.addRule(`Rule${idx}`, ruleOption)); - if (props.dropSpam) { this.addDropSpamRule(); } + + const rules = props.rules || []; + rules.forEach((ruleOption, idx) => this.addRule(`Rule${idx}`, ruleOption)); } } } diff --git a/packages/@aws-cdk/aws-ses/test/test.receipt-rule-set.ts b/packages/@aws-cdk/aws-ses/test/test.receipt-rule-set.ts index cf4b44f422371..458dacfcf311f 100644 --- a/packages/@aws-cdk/aws-ses/test/test.receipt-rule-set.ts +++ b/packages/@aws-cdk/aws-ses/test/test.receipt-rule-set.ts @@ -58,6 +58,41 @@ export = { test.done(); }, + 'drop spam rule should always appear first'(test: Test) { + // GIVEN + const stack = new Stack(); + + // WHEN + new ReceiptRuleSet(stack, 'RuleSet', { + dropSpam: true, + rules: [ + { + scanEnabled: true, + recipients: ['foo@example.com'], + }, + ], + }); + + // THEN + expect(stack).to(haveResource('AWS::SES::ReceiptRule', { + Rule: { + Enabled: true, + Recipients: [ + 'foo@example.com', + ], + ScanEnabled: true, + }, + // All "regular" rules should come after the drop spam rule + After: { + Ref: 'RuleSetDropSpamRule5809F51B', + }, + })); + + expect(stack).to(haveResource('AWS::Lambda::Function')); + + test.done(); + }, + 'import receipt rule set'(test: Test) { // GIVEN const stack = new Stack(); From 52f0576a072ac76bd751d766a0879edb1da87633 Mon Sep 17 00:00:00 2001 From: Nick Lynch Date: Mon, 23 Aug 2021 15:49:22 +0100 Subject: [PATCH 80/99] docs(cloudfront): fix CacheHeaderBehavior.behavior docstring (#16067) related #16002 ---- *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 | 2 +- 1 file changed, 1 insertion(+), 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 0d851e8a886ef..d0dad353a8727 100644 --- a/packages/@aws-cdk/aws-cloudfront/lib/cache-policy.ts +++ b/packages/@aws-cdk/aws-cloudfront/lib/cache-policy.ts @@ -234,7 +234,7 @@ export class CacheHeaderBehavior { return new CacheHeaderBehavior('whitelist', headers); } - /** If the no headers will be passed, or an allow list of headers. */ + /** If no headers will be passed, or an allow list of headers. */ public readonly behavior: string; /** The headers for the allow/deny list, if applicable. */ public readonly headers?: string[]; From b059124b238e27751217cbdaaa01c38b00e80fc9 Mon Sep 17 00:00:00 2001 From: AWS CDK Automation <43080478+aws-cdk-automation@users.noreply.github.com> Date: Mon, 23 Aug 2021 19:19:54 +0300 Subject: [PATCH 81/99] feat(cfnspec): cloudformation spec v40.0.0 (#16183) Co-authored-by: AWS CDK Team --- packages/@aws-cdk/cfnspec/CHANGELOG.md | 83 +++++ packages/@aws-cdk/cfnspec/cfn.version | 2 +- ...0_CloudFormationResourceSpecification.json | 348 +++++++++++++++++- 3 files changed, 419 insertions(+), 14 deletions(-) diff --git a/packages/@aws-cdk/cfnspec/CHANGELOG.md b/packages/@aws-cdk/cfnspec/CHANGELOG.md index 4f7501decae02..85274a4543fbf 100644 --- a/packages/@aws-cdk/cfnspec/CHANGELOG.md +++ b/packages/@aws-cdk/cfnspec/CHANGELOG.md @@ -1,3 +1,86 @@ +# CloudFormation Resource Specification v40.0.0 + +## New Resource Types + + +## Attribute Changes + +* AWS::EC2::DHCPOptions Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-dhcp-options.html + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-dhcpoptions.html +* AWS::EC2::DHCPOptions DhcpOptionsId (__added__) + +## Property Changes + +* AWS::AutoScaling::ScalingPolicy PredictiveScalingConfiguration (__added__) +* AWS::EC2::DHCPOptions DomainName.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-dhcp-options.html#cfn-ec2-dhcpoptions-domainname + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-dhcpoptions.html#cfn-ec2-dhcpoptions-domainname +* AWS::EC2::DHCPOptions DomainNameServers.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-dhcp-options.html#cfn-ec2-dhcpoptions-domainnameservers + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-dhcpoptions.html#cfn-ec2-dhcpoptions-domainnameservers +* AWS::EC2::DHCPOptions NetbiosNameServers.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-dhcp-options.html#cfn-ec2-dhcpoptions-netbiosnameservers + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-dhcpoptions.html#cfn-ec2-dhcpoptions-netbiosnameservers +* AWS::EC2::DHCPOptions NetbiosNodeType.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-dhcp-options.html#cfn-ec2-dhcpoptions-netbiosnodetype + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-dhcpoptions.html#cfn-ec2-dhcpoptions-netbiosnodetype +* AWS::EC2::DHCPOptions NtpServers.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-dhcp-options.html#cfn-ec2-dhcpoptions-ntpservers + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-dhcpoptions.html#cfn-ec2-dhcpoptions-ntpservers +* AWS::EC2::DHCPOptions Tags.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-dhcp-options.html#cfn-ec2-dhcpoptions-tags + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-dhcpoptions.html#cfn-ec2-dhcpoptions-tags +* AWS::Redshift::Cluster AquaConfigurationStatus (__added__) +* AWS::Redshift::Cluster AvailabilityZoneRelocation (__added__) +* AWS::Redshift::Cluster AvailabilityZoneRelocationStatus (__added__) +* AWS::Redshift::Cluster Classic (__added__) +* AWS::Redshift::Cluster DeferMaintenance (__added__) +* AWS::Redshift::Cluster DeferMaintenanceDuration (__added__) +* AWS::Redshift::Cluster DeferMaintenanceEndTime (__added__) +* AWS::Redshift::Cluster DeferMaintenanceIdentifier (__added__) +* AWS::Redshift::Cluster DeferMaintenanceStartTime (__added__) +* AWS::Redshift::Cluster DestinationRegion (__added__) +* AWS::Redshift::Cluster EnhancedVpcRouting (__added__) +* AWS::Redshift::Cluster MaintenanceTrackName (__added__) +* AWS::Redshift::Cluster ManualSnapshotRetentionPeriod (__added__) +* AWS::Redshift::Cluster ResourceAction (__added__) +* AWS::Redshift::Cluster RevisionTarget (__added__) +* AWS::Redshift::Cluster RotateEncryptionKey (__added__) +* AWS::Redshift::Cluster SnapshotCopyGrantName (__added__) +* AWS::Redshift::Cluster SnapshotCopyManual (__added__) +* AWS::Redshift::Cluster SnapshotCopyRetentionPeriod (__added__) +* AWS::Redshift::Cluster AvailabilityZone.UpdateType (__changed__) + * Old: Immutable + * New: Mutable +* AWS::Redshift::Cluster ElasticIp.UpdateType (__changed__) + * Old: Immutable + * New: Mutable +* AWS::Redshift::Cluster Encrypted.UpdateType (__changed__) + * Old: Immutable + * New: Mutable +* AWS::Redshift::Cluster KmsKeyId.UpdateType (__changed__) + * Old: Immutable + * New: Mutable +* AWS::Redshift::Cluster Port.UpdateType (__changed__) + * Old: Immutable + * New: Mutable +* AWS::SageMaker::EndpointConfig AsyncInferenceConfig (__added__) + +## Property Type Changes + +* AWS::AutoScaling::ScalingPolicy.PredictiveScalingConfiguration (__added__) +* AWS::AutoScaling::ScalingPolicy.PredictiveScalingMetricSpecification (__added__) +* AWS::AutoScaling::ScalingPolicy.PredictiveScalingPredefinedLoadMetric (__added__) +* AWS::AutoScaling::ScalingPolicy.PredictiveScalingPredefinedMetricPair (__added__) +* AWS::AutoScaling::ScalingPolicy.PredictiveScalingPredefinedScalingMetric (__added__) +* AWS::SageMaker::EndpointConfig.AsyncInferenceClientConfig (__added__) +* AWS::SageMaker::EndpointConfig.AsyncInferenceConfig (__added__) +* AWS::SageMaker::EndpointConfig.AsyncInferenceNotificationConfig (__added__) +* AWS::SageMaker::EndpointConfig.AsyncInferenceOutputConfig (__added__) +* AWS::WAFv2::WebACL.ManagedRuleGroupStatement Version (__added__) + + # CloudFormation Resource Specification v39.10.0 ## New Resource Types diff --git a/packages/@aws-cdk/cfnspec/cfn.version b/packages/@aws-cdk/cfnspec/cfn.version index 3520fac4397ab..e9340fd6f7115 100644 --- a/packages/@aws-cdk/cfnspec/cfn.version +++ b/packages/@aws-cdk/cfnspec/cfn.version @@ -1 +1 @@ -39.10.0 +40.0.0 diff --git a/packages/@aws-cdk/cfnspec/spec-source/000_CloudFormationResourceSpecification.json b/packages/@aws-cdk/cfnspec/spec-source/000_CloudFormationResourceSpecification.json index ebcff7129953c..1bb4dde7c70f4 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/000_CloudFormationResourceSpecification.json +++ b/packages/@aws-cdk/cfnspec/spec-source/000_CloudFormationResourceSpecification.json @@ -8641,6 +8641,123 @@ } } }, + "AWS::AutoScaling::ScalingPolicy.PredictiveScalingConfiguration": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-autoscaling-scalingpolicy-predictivescalingconfiguration.html", + "Properties": { + "MaxCapacityBreachBehavior": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-autoscaling-scalingpolicy-predictivescalingconfiguration.html#cfn-autoscaling-scalingpolicy-predictivescalingconfiguration-maxcapacitybreachbehavior", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "MaxCapacityBuffer": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-autoscaling-scalingpolicy-predictivescalingconfiguration.html#cfn-autoscaling-scalingpolicy-predictivescalingconfiguration-maxcapacitybuffer", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + }, + "MetricSpecifications": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-autoscaling-scalingpolicy-predictivescalingconfiguration.html#cfn-autoscaling-scalingpolicy-predictivescalingconfiguration-metricspecifications", + "DuplicatesAllowed": false, + "ItemType": "PredictiveScalingMetricSpecification", + "Required": true, + "Type": "List", + "UpdateType": "Mutable" + }, + "Mode": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-autoscaling-scalingpolicy-predictivescalingconfiguration.html#cfn-autoscaling-scalingpolicy-predictivescalingconfiguration-mode", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "SchedulingBufferTime": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-autoscaling-scalingpolicy-predictivescalingconfiguration.html#cfn-autoscaling-scalingpolicy-predictivescalingconfiguration-schedulingbuffertime", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + } + } + }, + "AWS::AutoScaling::ScalingPolicy.PredictiveScalingMetricSpecification": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-autoscaling-scalingpolicy-predictivescalingmetricspecification.html", + "Properties": { + "PredefinedLoadMetricSpecification": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-autoscaling-scalingpolicy-predictivescalingmetricspecification.html#cfn-autoscaling-scalingpolicy-predictivescalingmetricspecification-predefinedloadmetricspecification", + "Required": false, + "Type": "PredictiveScalingPredefinedLoadMetric", + "UpdateType": "Mutable" + }, + "PredefinedMetricPairSpecification": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-autoscaling-scalingpolicy-predictivescalingmetricspecification.html#cfn-autoscaling-scalingpolicy-predictivescalingmetricspecification-predefinedmetricpairspecification", + "Required": false, + "Type": "PredictiveScalingPredefinedMetricPair", + "UpdateType": "Mutable" + }, + "PredefinedScalingMetricSpecification": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-autoscaling-scalingpolicy-predictivescalingmetricspecification.html#cfn-autoscaling-scalingpolicy-predictivescalingmetricspecification-predefinedscalingmetricspecification", + "Required": false, + "Type": "PredictiveScalingPredefinedScalingMetric", + "UpdateType": "Mutable" + }, + "TargetValue": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-autoscaling-scalingpolicy-predictivescalingmetricspecification.html#cfn-autoscaling-scalingpolicy-predictivescalingmetricspecification-targetvalue", + "PrimitiveType": "Double", + "Required": true, + "UpdateType": "Mutable" + } + } + }, + "AWS::AutoScaling::ScalingPolicy.PredictiveScalingPredefinedLoadMetric": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-autoscaling-scalingpolicy-predictivescalingpredefinedloadmetric.html", + "Properties": { + "PredefinedMetricType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-autoscaling-scalingpolicy-predictivescalingpredefinedloadmetric.html#cfn-autoscaling-scalingpolicy-predictivescalingpredefinedloadmetric-predefinedmetrictype", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "ResourceLabel": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-autoscaling-scalingpolicy-predictivescalingpredefinedloadmetric.html#cfn-autoscaling-scalingpolicy-predictivescalingpredefinedloadmetric-resourcelabel", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, + "AWS::AutoScaling::ScalingPolicy.PredictiveScalingPredefinedMetricPair": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-autoscaling-scalingpolicy-predictivescalingpredefinedmetricpair.html", + "Properties": { + "PredefinedMetricType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-autoscaling-scalingpolicy-predictivescalingpredefinedmetricpair.html#cfn-autoscaling-scalingpolicy-predictivescalingpredefinedmetricpair-predefinedmetrictype", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "ResourceLabel": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-autoscaling-scalingpolicy-predictivescalingpredefinedmetricpair.html#cfn-autoscaling-scalingpolicy-predictivescalingpredefinedmetricpair-resourcelabel", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, + "AWS::AutoScaling::ScalingPolicy.PredictiveScalingPredefinedScalingMetric": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-autoscaling-scalingpolicy-predictivescalingpredefinedscalingmetric.html", + "Properties": { + "PredefinedMetricType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-autoscaling-scalingpolicy-predictivescalingpredefinedscalingmetric.html#cfn-autoscaling-scalingpolicy-predictivescalingpredefinedscalingmetric-predefinedmetrictype", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "ResourceLabel": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-autoscaling-scalingpolicy-predictivescalingpredefinedscalingmetric.html#cfn-autoscaling-scalingpolicy-predictivescalingpredefinedscalingmetric-resourcelabel", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, "AWS::AutoScaling::ScalingPolicy.StepAdjustment": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-autoscaling-scalingpolicy-stepadjustments.html", "Properties": { @@ -56904,6 +57021,74 @@ } } }, + "AWS::SageMaker::EndpointConfig.AsyncInferenceClientConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-asyncinferenceclientconfig.html", + "Properties": { + "MaxConcurrentInvocationsPerInstance": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-asyncinferenceclientconfig.html#cfn-sagemaker-endpointconfig-asyncinferenceclientconfig-maxconcurrentinvocationsperinstance", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Immutable" + } + } + }, + "AWS::SageMaker::EndpointConfig.AsyncInferenceConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-asyncinferenceconfig.html", + "Properties": { + "ClientConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-asyncinferenceconfig.html#cfn-sagemaker-endpointconfig-asyncinferenceconfig-clientconfig", + "Required": false, + "Type": "AsyncInferenceClientConfig", + "UpdateType": "Immutable" + }, + "OutputConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-asyncinferenceconfig.html#cfn-sagemaker-endpointconfig-asyncinferenceconfig-outputconfig", + "Required": true, + "Type": "AsyncInferenceOutputConfig", + "UpdateType": "Immutable" + } + } + }, + "AWS::SageMaker::EndpointConfig.AsyncInferenceNotificationConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-asyncinferencenotificationconfig.html", + "Properties": { + "ErrorTopic": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-asyncinferencenotificationconfig.html#cfn-sagemaker-endpointconfig-asyncinferencenotificationconfig-errortopic", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "SuccessTopic": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-asyncinferencenotificationconfig.html#cfn-sagemaker-endpointconfig-asyncinferencenotificationconfig-successtopic", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + } + } + }, + "AWS::SageMaker::EndpointConfig.AsyncInferenceOutputConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-asyncinferenceoutputconfig.html", + "Properties": { + "KmsKeyId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-asyncinferenceoutputconfig.html#cfn-sagemaker-endpointconfig-asyncinferenceoutputconfig-kmskeyid", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "NotificationConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-asyncinferenceoutputconfig.html#cfn-sagemaker-endpointconfig-asyncinferenceoutputconfig-notificationconfig", + "Required": false, + "Type": "AsyncInferenceNotificationConfig", + "UpdateType": "Immutable" + }, + "S3OutputPath": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-asyncinferenceoutputconfig.html#cfn-sagemaker-endpointconfig-asyncinferenceoutputconfig-s3outputpath", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + } + } + }, "AWS::SageMaker::EndpointConfig.CaptureContentTypeHeader": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-endpointconfig-datacaptureconfig-capturecontenttypeheader.html", "Properties": { @@ -60972,6 +61157,12 @@ "PrimitiveType": "String", "Required": true, "UpdateType": "Mutable" + }, + "Version": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wafv2-webacl-managedrulegroupstatement.html#cfn-wafv2-webacl-managedrulegroupstatement-version", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" } } }, @@ -61705,7 +61896,7 @@ } } }, - "ResourceSpecificationVersion": "39.10.0", + "ResourceSpecificationVersion": "40.0.0", "ResourceTypes": { "AWS::ACMPCA::Certificate": { "Attributes": { @@ -66484,6 +66675,12 @@ "Required": false, "UpdateType": "Mutable" }, + "PredictiveScalingConfiguration": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-as-policy.html#cfn-autoscaling-scalingpolicy-predictivescalingconfiguration", + "Required": false, + "Type": "PredictiveScalingConfiguration", + "UpdateType": "Mutable" + }, "ScalingAdjustment": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-as-policy.html#cfn-as-scalingpolicy-scalingadjustment", "PrimitiveType": "Integer", @@ -73299,16 +73496,21 @@ } }, "AWS::EC2::DHCPOptions": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-dhcp-options.html", + "Attributes": { + "DhcpOptionsId": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-dhcpoptions.html", "Properties": { "DomainName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-dhcp-options.html#cfn-ec2-dhcpoptions-domainname", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-dhcpoptions.html#cfn-ec2-dhcpoptions-domainname", "PrimitiveType": "String", "Required": false, "UpdateType": "Immutable" }, "DomainNameServers": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-dhcp-options.html#cfn-ec2-dhcpoptions-domainnameservers", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-dhcpoptions.html#cfn-ec2-dhcpoptions-domainnameservers", "DuplicatesAllowed": false, "PrimitiveItemType": "String", "Required": false, @@ -73316,7 +73518,7 @@ "UpdateType": "Immutable" }, "NetbiosNameServers": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-dhcp-options.html#cfn-ec2-dhcpoptions-netbiosnameservers", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-dhcpoptions.html#cfn-ec2-dhcpoptions-netbiosnameservers", "DuplicatesAllowed": false, "PrimitiveItemType": "String", "Required": false, @@ -73324,13 +73526,13 @@ "UpdateType": "Immutable" }, "NetbiosNodeType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-dhcp-options.html#cfn-ec2-dhcpoptions-netbiosnodetype", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-dhcpoptions.html#cfn-ec2-dhcpoptions-netbiosnodetype", "PrimitiveType": "Integer", "Required": false, "UpdateType": "Immutable" }, "NtpServers": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-dhcp-options.html#cfn-ec2-dhcpoptions-ntpservers", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-dhcpoptions.html#cfn-ec2-dhcpoptions-ntpservers", "DuplicatesAllowed": true, "PrimitiveItemType": "String", "Required": false, @@ -73338,7 +73540,7 @@ "UpdateType": "Immutable" }, "Tags": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-dhcp-options.html#cfn-ec2-dhcpoptions-tags", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-dhcpoptions.html#cfn-ec2-dhcpoptions-tags", "DuplicatesAllowed": true, "ItemType": "Tag", "Required": false, @@ -93067,6 +93269,12 @@ "Required": false, "UpdateType": "Mutable" }, + "AquaConfigurationStatus": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-aquaconfigurationstatus", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, "AutomatedSnapshotRetentionPeriod": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-automatedsnapshotretentionperiod", "PrimitiveType": "Integer", @@ -93077,7 +93285,25 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-availabilityzone", "PrimitiveType": "String", "Required": false, - "UpdateType": "Immutable" + "UpdateType": "Mutable" + }, + "AvailabilityZoneRelocation": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-availabilityzonerelocation", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Mutable" + }, + "AvailabilityZoneRelocationStatus": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-availabilityzonerelocationstatus", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "Classic": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-classic", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Mutable" }, "ClusterIdentifier": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-clusteridentifier", @@ -93123,17 +93349,53 @@ "Required": true, "UpdateType": "Immutable" }, + "DeferMaintenance": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-defermaintenance", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Mutable" + }, + "DeferMaintenanceDuration": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-defermaintenanceduration", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + }, + "DeferMaintenanceEndTime": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-defermaintenanceendtime", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "DeferMaintenanceIdentifier": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-defermaintenanceidentifier", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "DeferMaintenanceStartTime": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-defermaintenancestarttime", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "DestinationRegion": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-destinationregion", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, "ElasticIp": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-elasticip", "PrimitiveType": "String", "Required": false, - "UpdateType": "Immutable" + "UpdateType": "Mutable" }, "Encrypted": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-encrypted", "PrimitiveType": "Boolean", "Required": false, - "UpdateType": "Immutable" + "UpdateType": "Mutable" }, "Endpoint": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-endpoint", @@ -93141,6 +93403,12 @@ "Type": "Endpoint", "UpdateType": "Mutable" }, + "EnhancedVpcRouting": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-enhancedvpcrouting", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Mutable" + }, "HsmClientCertificateIdentifier": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-hsmclientcertificateidentifier", "PrimitiveType": "String", @@ -93165,7 +93433,7 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-kmskeyid", "PrimitiveType": "String", "Required": false, - "UpdateType": "Immutable" + "UpdateType": "Mutable" }, "LoggingProperties": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-loggingproperties", @@ -93173,6 +93441,18 @@ "Type": "LoggingProperties", "UpdateType": "Mutable" }, + "MaintenanceTrackName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-maintenancetrackname", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "ManualSnapshotRetentionPeriod": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-manualsnapshotretentionperiod", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + }, "MasterUserPassword": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-masteruserpassword", "PrimitiveType": "String", @@ -93207,7 +93487,7 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-port", "PrimitiveType": "Integer", "Required": false, - "UpdateType": "Immutable" + "UpdateType": "Mutable" }, "PreferredMaintenanceWindow": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-preferredmaintenancewindow", @@ -93221,12 +93501,48 @@ "Required": false, "UpdateType": "Mutable" }, + "ResourceAction": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-resourceaction", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "RevisionTarget": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-revisiontarget", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "RotateEncryptionKey": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-rotateencryptionkey", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Mutable" + }, "SnapshotClusterIdentifier": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-snapshotclusteridentifier", "PrimitiveType": "String", "Required": false, "UpdateType": "Immutable" }, + "SnapshotCopyGrantName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-snapshotcopygrantname", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "SnapshotCopyManual": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-snapshotcopymanual", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Mutable" + }, + "SnapshotCopyRetentionPeriod": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-snapshotcopyretentionperiod", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + }, "SnapshotIdentifier": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-snapshotidentifier", "PrimitiveType": "String", @@ -96592,6 +96908,12 @@ }, "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-endpointconfig.html", "Properties": { + "AsyncInferenceConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-endpointconfig.html#cfn-sagemaker-endpointconfig-asyncinferenceconfig", + "Required": false, + "Type": "AsyncInferenceConfig", + "UpdateType": "Immutable" + }, "DataCaptureConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-endpointconfig.html#cfn-sagemaker-endpointconfig-datacaptureconfig", "Required": false, From cd280a8f4f46eb50be3a25d80c00a807881832c4 Mon Sep 17 00:00:00 2001 From: "Michael S. Fischer" Date: Mon, 23 Aug 2021 10:42:53 -0700 Subject: [PATCH 82/99] feat(ecs): add support for Bottlerocket on ARM64 (#15454) Add support for Bottlerocket AMIs on ARM64 architecture, including AWS Graviton2 instances. Closes #14466 ---- *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/README.md | 11 +- packages/@aws-cdk/aws-ecs/lib/cluster.ts | 19 +- .../@aws-cdk/aws-ecs/test/cluster.test.ts | 31 +- .../integ.graviton-bottlerocket.expected.json | 874 ++++++++++++++++++ .../test/ec2/integ.graviton-bottlerocket.ts | 16 + .../test/ec2/integ.graviton.expected.json | 12 +- 6 files changed, 952 insertions(+), 11 deletions(-) create mode 100644 packages/@aws-cdk/aws-ecs/test/ec2/integ.graviton-bottlerocket.expected.json create mode 100644 packages/@aws-cdk/aws-ecs/test/ec2/integ.graviton-bottlerocket.ts diff --git a/packages/@aws-cdk/aws-ecs/README.md b/packages/@aws-cdk/aws-ecs/README.md index e3c7f900b58a2..1d8a10f4deb8c 100644 --- a/packages/@aws-cdk/aws-ecs/README.md +++ b/packages/@aws-cdk/aws-ecs/README.md @@ -137,8 +137,6 @@ If you omit the property `vpc`, the construct will create a new VPC with two AZs [Bottlerocket](https://aws.amazon.com/bottlerocket/) is a Linux-based open source operating system that is purpose-built by AWS for running containers. You can launch Amazon ECS container instances with the Bottlerocket AMI. -> **NOTICE**: The Bottlerocket AMI is in developer preview release for Amazon ECS and is subject to change. - The following example will create a capacity with self-managed Amazon EC2 capacity of 2 `c5.large` Linux instances running with `Bottlerocket` AMI. The following example adds Bottlerocket capacity to the cluster: @@ -164,7 +162,16 @@ cluster.addCapacity('graviton-cluster', { instanceType: new ec2.InstanceType('c6g.large'), machineImage: ecs.EcsOptimizedImage.amazonLinux2(ecs.AmiHardwareType.ARM), }); +``` +Bottlerocket is also supported: + +```ts +cluster.addCapacity('graviton-cluster', { + minCapacity: 2, + instanceType: new ec2.InstanceType('c6g.large'), + machineImage: ecs.MachineImageType.BOTTLEROCKET, +}); ``` ### Spot Instances diff --git a/packages/@aws-cdk/aws-ecs/lib/cluster.ts b/packages/@aws-cdk/aws-ecs/lib/cluster.ts index 1fce9b00d4500..4ea5e24b7529c 100644 --- a/packages/@aws-cdk/aws-ecs/lib/cluster.ts +++ b/packages/@aws-cdk/aws-ecs/lib/cluster.ts @@ -297,7 +297,9 @@ export class Cluster extends Resource implements ICluster { // Do 2-way defaulting here: if the machineImageType is BOTTLEROCKET, pick the right AMI. // Otherwise, determine the machineImageType from the given AMI. const machineImage = options.machineImage ?? - (options.machineImageType === MachineImageType.BOTTLEROCKET ? new BottleRocketImage() : new EcsOptimizedAmi()); + (options.machineImageType === MachineImageType.BOTTLEROCKET ? new BottleRocketImage({ + architecture: options.instanceType.architecture, + }) : new EcsOptimizedAmi()); const machineImageType = options.machineImageType ?? (isBottleRocketImage(machineImage) ? MachineImageType.BOTTLEROCKET : MachineImageType.AMAZON_LINUX_2); @@ -767,6 +769,13 @@ export interface BottleRocketImageProps { * @default - BottlerocketEcsVariant.AWS_ECS_1 */ readonly variant?: BottlerocketEcsVariant; + + /** + * The CPU architecture + * + * @default - x86_64 + */ + readonly architecture?: ec2.InstanceArchitecture; } /** @@ -779,14 +788,20 @@ export class BottleRocketImage implements ec2.IMachineImage { */ private readonly variant: string; + /** + * Instance architecture + */ + private readonly architecture: ec2.InstanceArchitecture; + /** * Constructs a new instance of the BottleRocketImage class. */ public constructor(props: BottleRocketImageProps = {}) { this.variant = props.variant ?? BottlerocketEcsVariant.AWS_ECS_1; + this.architecture = props.architecture ?? ec2.InstanceArchitecture.X86_64; // set the SSM parameter name - this.amiParameterName = `/aws/service/bottlerocket/${this.variant}/x86_64/latest/image_id`; + this.amiParameterName = `/aws/service/bottlerocket/${this.variant}/${this.architecture}/latest/image_id`; } /** diff --git a/packages/@aws-cdk/aws-ecs/test/cluster.test.ts b/packages/@aws-cdk/aws-ecs/test/cluster.test.ts index 8b6dd4626ddb6..40c74a08257f2 100644 --- a/packages/@aws-cdk/aws-ecs/test/cluster.test.ts +++ b/packages/@aws-cdk/aws-ecs/test/cluster.test.ts @@ -1682,7 +1682,36 @@ nodeunitShim({ test.done(); }, - 'cluster capacity with bottlerocket AMI, by setting the machineImage'(test: Test) { + 'correct bottlerocket AMI for ARM64 architecture'(test: Test) { + // GIVEN + const app = new cdk.App(); + const stack = new cdk.Stack(app, 'test'); + + const cluster = new ecs.Cluster(stack, 'EcsCluster'); + cluster.addCapacity('bottlerocket-asg', { + instanceType: new ec2.InstanceType('m6g.large'), + machineImageType: ecs.MachineImageType.BOTTLEROCKET, + }); + + // THEN + expect(stack).to(haveResource('AWS::AutoScaling::LaunchConfiguration', { + ImageId: { + Ref: 'SsmParameterValueawsservicebottlerocketawsecs1arm64latestimageidC96584B6F00A464EAD1953AFF4B05118Parameter', + }, + })); + + const assembly = app.synth(); + const template = assembly.getStackByName(stack.stackName).template; + test.deepEqual(template.Parameters, { + SsmParameterValueawsservicebottlerocketawsecs1arm64latestimageidC96584B6F00A464EAD1953AFF4B05118Parameter: { + Type: 'AWS::SSM::Parameter::Value', + Default: '/aws/service/bottlerocket/aws-ecs-1/arm64/latest/image_id', + }, + }); + test.done(); + }, + + 'throws when machineImage and machineImageType both specified'(test: Test) { // GIVEN const app = new cdk.App(); const stack = new cdk.Stack(app, 'test'); diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/integ.graviton-bottlerocket.expected.json b/packages/@aws-cdk/aws-ecs/test/ec2/integ.graviton-bottlerocket.expected.json new file mode 100644 index 0000000000000..fb6c80ff66b00 --- /dev/null +++ b/packages/@aws-cdk/aws-ecs/test/ec2/integ.graviton-bottlerocket.expected.json @@ -0,0 +1,874 @@ +{ + "Resources": { + "Vpc8378EB38": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default", + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-integ/Vpc" + } + ] + } + }, + "VpcPublicSubnet1Subnet5C2D37C4": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "CidrBlock": "10.0.0.0/18", + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "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-ecs-integ/Vpc/PublicSubnet1" + } + ] + } + }, + "VpcPublicSubnet1RouteTable6C95E38E": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-integ/Vpc/PublicSubnet1" + } + ] + } + }, + "VpcPublicSubnet1RouteTableAssociation97140677": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" + }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + } + } + }, + "VpcPublicSubnet1DefaultRoute3DA9E72A": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VpcIGWD7BA715C" + } + }, + "DependsOn": [ + "VpcVPCGWBF912B6E" + ] + }, + "VpcPublicSubnet1EIPD7E02669": { + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-integ/Vpc/PublicSubnet1" + } + ] + } + }, + "VpcPublicSubnet1NATGateway4D7517AA": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, + "AllocationId": { + "Fn::GetAtt": [ + "VpcPublicSubnet1EIPD7E02669", + "AllocationId" + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-integ/Vpc/PublicSubnet1" + } + ] + } + }, + "VpcPublicSubnet2Subnet691E08A3": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "CidrBlock": "10.0.64.0/18", + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "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-ecs-integ/Vpc/PublicSubnet2" + } + ] + } + }, + "VpcPublicSubnet2RouteTable94F7E489": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-integ/Vpc/PublicSubnet2" + } + ] + } + }, + "VpcPublicSubnet2RouteTableAssociationDD5762D8": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" + }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + } + } + }, + "VpcPublicSubnet2DefaultRoute97F91067": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VpcIGWD7BA715C" + } + }, + "DependsOn": [ + "VpcVPCGWBF912B6E" + ] + }, + "VpcPublicSubnet2EIP3C605A87": { + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-integ/Vpc/PublicSubnet2" + } + ] + } + }, + "VpcPublicSubnet2NATGateway9182C01D": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, + "AllocationId": { + "Fn::GetAtt": [ + "VpcPublicSubnet2EIP3C605A87", + "AllocationId" + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-integ/Vpc/PublicSubnet2" + } + ] + } + }, + "VpcPrivateSubnet1Subnet536B997A": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "CidrBlock": "10.0.128.0/18", + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "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-ecs-integ/Vpc/PrivateSubnet1" + } + ] + } + }, + "VpcPrivateSubnet1RouteTableB2C5B500": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-integ/Vpc/PrivateSubnet1" + } + ] + } + }, + "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" + }, + "SubnetId": { + "Ref": "VpcPrivateSubnet1Subnet536B997A" + } + } + }, + "VpcPrivateSubnet1DefaultRouteBE02A9ED": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + } + } + }, + "VpcPrivateSubnet2Subnet3788AAA1": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "CidrBlock": "10.0.192.0/18", + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "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-ecs-integ/Vpc/PrivateSubnet2" + } + ] + } + }, + "VpcPrivateSubnet2RouteTableA678073B": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-integ/Vpc/PrivateSubnet2" + } + ] + } + }, + "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" + }, + "SubnetId": { + "Ref": "VpcPrivateSubnet2Subnet3788AAA1" + } + } + }, + "VpcPrivateSubnet2DefaultRoute060D2087": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "VpcPublicSubnet2NATGateway9182C01D" + } + } + }, + "VpcIGWD7BA715C": { + "Type": "AWS::EC2::InternetGateway", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-integ/Vpc" + } + ] + } + }, + "VpcVPCGWBF912B6E": { + "Type": "AWS::EC2::VPCGatewayAttachment", + "Properties": { + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "InternetGatewayId": { + "Ref": "VpcIGWD7BA715C" + } + } + }, + "EcsCluster97242B84": { + "Type": "AWS::ECS::Cluster" + }, + "EcsClustergravitonclusterInstanceSecurityGroup0187E9BB": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "aws-ecs-integ/EcsCluster/graviton-cluster/InstanceSecurityGroup", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-integ/EcsCluster/graviton-cluster" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "EcsClustergravitonclusterInstanceRole0D0E0F94": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": { + "Fn::Join": [ + "", + [ + "ec2.", + { + "Ref": "AWS::URLSuffix" + } + ] + ] + } + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonSSMManagedInstanceCore" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role" + ] + ] + } + ], + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-integ/EcsCluster/graviton-cluster" + } + ] + } + }, + "EcsClustergravitonclusterInstanceRoleDefaultPolicyB89DB33F": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "ecs:DeregisterContainerInstance", + "ecs:RegisterContainerInstance", + "ecs:Submit*" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "EcsCluster97242B84", + "Arn" + ] + } + }, + { + "Action": [ + "ecs:Poll", + "ecs:StartTelemetrySession" + ], + "Condition": { + "ArnEquals": { + "ecs:cluster": { + "Fn::GetAtt": [ + "EcsCluster97242B84", + "Arn" + ] + } + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ecs:DiscoverPollEndpoint", + "ecr:GetAuthorizationToken", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "EcsClustergravitonclusterInstanceRoleDefaultPolicyB89DB33F", + "Roles": [ + { + "Ref": "EcsClustergravitonclusterInstanceRole0D0E0F94" + } + ] + } + }, + "EcsClustergravitonclusterInstanceProfileD1BBFAAE": { + "Type": "AWS::IAM::InstanceProfile", + "Properties": { + "Roles": [ + { + "Ref": "EcsClustergravitonclusterInstanceRole0D0E0F94" + } + ] + } + }, + "EcsClustergravitonclusterLaunchConfig64183B57": { + "Type": "AWS::AutoScaling::LaunchConfiguration", + "Properties": { + "ImageId": { + "Ref": "SsmParameterValueawsservicebottlerocketawsecs1arm64latestimageidC96584B6F00A464EAD1953AFF4B05118Parameter" + }, + "InstanceType": "c6g.large", + "IamInstanceProfile": { + "Ref": "EcsClustergravitonclusterInstanceProfileD1BBFAAE" + }, + "SecurityGroups": [ + { + "Fn::GetAtt": [ + "EcsClustergravitonclusterInstanceSecurityGroup0187E9BB", + "GroupId" + ] + } + ], + "UserData": { + "Fn::Base64": { + "Fn::Join": [ + "", + [ + "\n[settings.ecs]\ncluster = \"", + { + "Ref": "EcsCluster97242B84" + }, + "\"" + ] + ] + } + } + }, + "DependsOn": [ + "EcsClustergravitonclusterInstanceRoleDefaultPolicyB89DB33F", + "EcsClustergravitonclusterInstanceRole0D0E0F94" + ] + }, + "EcsClustergravitonclusterASG869F3168": { + "Type": "AWS::AutoScaling::AutoScalingGroup", + "Properties": { + "MaxSize": "2", + "MinSize": "2", + "LaunchConfigurationName": { + "Ref": "EcsClustergravitonclusterLaunchConfig64183B57" + }, + "Tags": [ + { + "Key": "Name", + "PropagateAtLaunch": true, + "Value": "aws-ecs-integ/EcsCluster/graviton-cluster" + } + ], + "VPCZoneIdentifier": [ + { + "Ref": "VpcPrivateSubnet1Subnet536B997A" + }, + { + "Ref": "VpcPrivateSubnet2Subnet3788AAA1" + } + ] + }, + "UpdatePolicy": { + "AutoScalingReplacingUpdate": { + "WillReplace": true + }, + "AutoScalingScheduledAction": { + "IgnoreUnmodifiedGroupSizeProperties": true + } + } + }, + "EcsClustergravitonclusterDrainECSHookFunctionServiceRole26D97764": { + "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" + ] + ] + } + ], + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-integ/EcsCluster/graviton-cluster" + } + ] + } + }, + "EcsClustergravitonclusterDrainECSHookFunctionServiceRoleDefaultPolicy1563DC6B": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "ec2:DescribeInstances", + "ec2:DescribeInstanceAttribute", + "ec2:DescribeInstanceStatus", + "ec2:DescribeHosts" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "autoscaling:CompleteLifecycleAction", + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":autoscaling:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":autoScalingGroup:*:autoScalingGroupName/", + { + "Ref": "EcsClustergravitonclusterASG869F3168" + } + ] + ] + } + }, + { + "Action": [ + "ecs:DescribeContainerInstances", + "ecs:DescribeTasks" + ], + "Condition": { + "ArnEquals": { + "ecs:cluster": { + "Fn::GetAtt": [ + "EcsCluster97242B84", + "Arn" + ] + } + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ecs:ListContainerInstances", + "ecs:SubmitContainerStateChange", + "ecs:SubmitTaskStateChange" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "EcsCluster97242B84", + "Arn" + ] + } + }, + { + "Action": [ + "ecs:UpdateContainerInstancesState", + "ecs:ListTasks" + ], + "Condition": { + "ArnEquals": { + "ecs:cluster": { + "Fn::GetAtt": [ + "EcsCluster97242B84", + "Arn" + ] + } + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "EcsClustergravitonclusterDrainECSHookFunctionServiceRoleDefaultPolicy1563DC6B", + "Roles": [ + { + "Ref": "EcsClustergravitonclusterDrainECSHookFunctionServiceRole26D97764" + } + ] + } + }, + "EcsClustergravitonclusterDrainECSHookFunctionB606E681": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + }, + "Role": { + "Fn::GetAtt": [ + "EcsClustergravitonclusterDrainECSHookFunctionServiceRole26D97764", + "Arn" + ] + }, + "Environment": { + "Variables": { + "CLUSTER": { + "Ref": "EcsCluster97242B84" + } + } + }, + "Handler": "index.lambda_handler", + "Runtime": "python3.6", + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-integ/EcsCluster/graviton-cluster" + } + ], + "Timeout": 310 + }, + "DependsOn": [ + "EcsClustergravitonclusterDrainECSHookFunctionServiceRoleDefaultPolicy1563DC6B", + "EcsClustergravitonclusterDrainECSHookFunctionServiceRole26D97764" + ] + }, + "EcsClustergravitonclusterDrainECSHookFunctionAllowInvokeawsecsintegEcsClustergravitonclusterLifecycleHookDrainHookTopicF44E68AA50D91BA3": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::GetAtt": [ + "EcsClustergravitonclusterDrainECSHookFunctionB606E681", + "Arn" + ] + }, + "Principal": "sns.amazonaws.com", + "SourceArn": { + "Ref": "EcsClustergravitonclusterLifecycleHookDrainHookTopic0A778AAC" + } + } + }, + "EcsClustergravitonclusterDrainECSHookFunctionTopic65B3FD43": { + "Type": "AWS::SNS::Subscription", + "Properties": { + "Protocol": "lambda", + "TopicArn": { + "Ref": "EcsClustergravitonclusterLifecycleHookDrainHookTopic0A778AAC" + }, + "Endpoint": { + "Fn::GetAtt": [ + "EcsClustergravitonclusterDrainECSHookFunctionB606E681", + "Arn" + ] + } + } + }, + "EcsClustergravitonclusterLifecycleHookDrainHookRoleA16C85AD": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "autoscaling.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-integ/EcsCluster/graviton-cluster" + } + ] + } + }, + "EcsClustergravitonclusterLifecycleHookDrainHookRoleDefaultPolicy516A6DA7": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "sns:Publish", + "Effect": "Allow", + "Resource": { + "Ref": "EcsClustergravitonclusterLifecycleHookDrainHookTopic0A778AAC" + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "EcsClustergravitonclusterLifecycleHookDrainHookRoleDefaultPolicy516A6DA7", + "Roles": [ + { + "Ref": "EcsClustergravitonclusterLifecycleHookDrainHookRoleA16C85AD" + } + ] + } + }, + "EcsClustergravitonclusterLifecycleHookDrainHookTopic0A778AAC": { + "Type": "AWS::SNS::Topic", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-integ/EcsCluster/graviton-cluster" + } + ] + } + }, + "EcsClustergravitonclusterLifecycleHookDrainHookA1F91B1B": { + "Type": "AWS::AutoScaling::LifecycleHook", + "Properties": { + "AutoScalingGroupName": { + "Ref": "EcsClustergravitonclusterASG869F3168" + }, + "LifecycleTransition": "autoscaling:EC2_INSTANCE_TERMINATING", + "DefaultResult": "CONTINUE", + "HeartbeatTimeout": 300, + "NotificationTargetARN": { + "Ref": "EcsClustergravitonclusterLifecycleHookDrainHookTopic0A778AAC" + }, + "RoleARN": { + "Fn::GetAtt": [ + "EcsClustergravitonclusterLifecycleHookDrainHookRoleA16C85AD", + "Arn" + ] + } + }, + "DependsOn": [ + "EcsClustergravitonclusterLifecycleHookDrainHookRoleDefaultPolicy516A6DA7", + "EcsClustergravitonclusterLifecycleHookDrainHookRoleA16C85AD" + ] + } + }, + "Parameters": { + "SsmParameterValueawsservicebottlerocketawsecs1arm64latestimageidC96584B6F00A464EAD1953AFF4B05118Parameter": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/aws/service/bottlerocket/aws-ecs-1/arm64/latest/image_id" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/integ.graviton-bottlerocket.ts b/packages/@aws-cdk/aws-ecs/test/ec2/integ.graviton-bottlerocket.ts new file mode 100644 index 0000000000000..5b8ecdca4fd0b --- /dev/null +++ b/packages/@aws-cdk/aws-ecs/test/ec2/integ.graviton-bottlerocket.ts @@ -0,0 +1,16 @@ +import * as ec2 from '@aws-cdk/aws-ec2'; +import * as cdk from '@aws-cdk/core'; +import * as ecs from '../../lib'; + +const app = new cdk.App(); +const stack = new cdk.Stack(app, 'aws-ecs-integ'); + +const vpc = new ec2.Vpc(stack, 'Vpc', { maxAzs: 2 }); +const cluster = new ecs.Cluster(stack, 'EcsCluster', { vpc }); + +cluster.addCapacity('graviton-cluster', { + minCapacity: 2, + instanceType: new ec2.InstanceType('c6g.large'), + machineImageType: ecs.MachineImageType.BOTTLEROCKET, +}); +app.synth(); diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/integ.graviton.expected.json b/packages/@aws-cdk/aws-ecs/test/ec2/integ.graviton.expected.json index 8529dea9b1171..c2b3eeecc8ddf 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/integ.graviton.expected.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/integ.graviton.expected.json @@ -95,15 +95,15 @@ "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, - "SubnetId": { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, "Tags": [ { "Key": "Name", @@ -192,15 +192,15 @@ "VpcPublicSubnet2NATGateway9182C01D": { "Type": "AWS::EC2::NatGateway", "Properties": { + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, "AllocationId": { "Fn::GetAtt": [ "VpcPublicSubnet2EIP3C605A87", "AllocationId" ] }, - "SubnetId": { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - }, "Tags": [ { "Key": "Name", From fdf612a45b3d3c0f8c972bd2736cb9f93e2e7057 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Tue, 24 Aug 2021 11:26:24 +0200 Subject: [PATCH 83/99] docs(pipelines): should use 'lookup' tag instead of 'deploy' tag (#15984) The code example was using the wrong condition. ---- *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 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/pipelines/README.md b/packages/@aws-cdk/pipelines/README.md index f17a35e3a9990..bab41842c2316 100644 --- a/packages/@aws-cdk/pipelines/README.md +++ b/packages/@aws-cdk/pipelines/README.md @@ -955,7 +955,7 @@ new CodePipeline(this, 'Pipeline', { resources: ['*'], conditions: { StringEquals: { - 'iam:ResourceTag/aws-cdk:bootstrap-role': 'deploy', + 'iam:ResourceTag/aws-cdk:bootstrap-role': 'lookup', }, }, }), From 0d0db38e3cdb557b4a641c5993068400847cc7df Mon Sep 17 00:00:00 2001 From: Yihui Han <53243835+readybuilderone@users.noreply.github.com> Date: Tue, 24 Aug 2021 18:09:03 +0800 Subject: [PATCH 84/99] fix: (aws-ec2): fix vpc endpoint incorrect issue in China region (#16139) fix:(aws-ec2): fix vpc endpoint incorrect issue in China region This PR fix the issue that can't create interface vpc endpoint for 40+ services like ecr, ec2, athena etc Closes: #9864 ---- # Considerations 1. In cn-north-1 region, there are: - 2 services whose endpoint service begin with "aws.sagemaker" prefix; - 41 services whose endpoint service begin with "cn.com.amazonaws" prefix; - 21 services whose endpoint service begin with "com.amazonaws" prefix; Details: https://gist.github.com/readybuilderone/d355f9f8f0f2b66379a10742b3c67cc7 2. in cn-northwest-1 region, there are: - 2 services whose endpoint service begin with "aws.sagemaker" prefix; - 44 services whose endpoint service begin with "cn.com.amazonaws" prefix; - 21 services whose endpoint service begin with "com.amazonaws" prefix; Details: https://gist.github.com/readybuilderone/a79f2c5e6fa02aae1699bf674b08be7c So, In cn-north-1 and cn-northwest-1, the vpc endpoint prefix is both region and service related. At first, I found the vpc endpoint prefix could be fetched via [AWS API](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeVpcEndpoints.html) , however the javascript sdk supports only asynchronous call, currently I didn't find any pattern in CDK to make live calls in object construction. Since the exception rules won't ever change ( only be added to), and the rate of change should be small in the grand scheme, I just kept the exception prefix lists in a map as fact data. # Known Issues Since the interface vpc endpoints prefixs are not region agnostic, it requires to set the {region} in the environment to create stacks in cn-north-1, and cn-northwest-1. The methods could be found in the [offical guide](https://docs.aws.amazon.com/cdk/latest/guide/environments.html). *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/@aws-cdk/aws-ec2/lib/vpc-endpoint.ts | 63 +++++++++- .../aws-ec2/test/vpc-endpoint.test.ts | 119 ++++++++++++++++++ 2 files changed, 181 insertions(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-ec2/lib/vpc-endpoint.ts b/packages/@aws-cdk/aws-ec2/lib/vpc-endpoint.ts index dd28d74e84ea1..69ad4aab88404 100644 --- a/packages/@aws-cdk/aws-ec2/lib/vpc-endpoint.ts +++ b/packages/@aws-cdk/aws-ec2/lib/vpc-endpoint.ts @@ -326,9 +326,70 @@ export class InterfaceVpcEndpointAwsService implements IInterfaceVpcEndpointServ const region = Lazy.uncachedString({ produce: (context) => Stack.of(context.scope).region, }); - this.name = `${prefix || 'com.amazonaws'}.${region}.${name}`; + const defaultEndpointPrefix = Lazy.uncachedString({ + produce: (context) => { + const regionName = Stack.of(context.scope).region; + return this.getDefaultEndpointPrefix(name, regionName); + }, + }); + const defaultEndpointSuffix = Lazy.uncachedString({ + produce: (context) => { + const regionName = Stack.of(context.scope).region; + return this.getDefaultEndpointSuffix(name, regionName); + }, + }); + + this.name = `${prefix || defaultEndpointPrefix}.${region}.${name}${defaultEndpointSuffix}`; this.port = port || 443; } + + /** + * Get the endpoint prefix for the service in the specified region + * because the prefix for some of the services in cn-north-1 and cn-northwest-1 are different + * + * For future maintenance, the vpc endpoint services could be fetched using AWS CLI Commmand: + * aws ec2 describe-vpc-endpoint-services + */ + private getDefaultEndpointPrefix(name: string, region: string) { + const VPC_ENDPOINT_SERVICE_EXCEPTIONS: { [region: string]: string[] } = { + 'cn-north-1': ['application-autoscaling', 'athena', 'autoscaling', 'awsconnector', 'cassandra', + 'cloudformation', 'codedeploy-commands-secure', 'databrew', 'dms', 'ebs', 'ec2', 'ecr.api', 'ecr.dkr', + 'elasticbeanstalk', 'elasticfilesystem', 'elasticfilesystem-fips', 'execute-api', 'imagebuilder', + 'iotsitewise.api', 'iotsitewise.data', 'kinesis-streams', 'lambda', 'license-manager', 'monitoring', + 'rds', 'redshift', 'redshift-data', 's3', 'sagemaker.api', 'sagemaker.featurestore-runtime', + 'sagemaker.runtime', 'servicecatalog', 'sms', 'sqs', 'states', 'sts', 'synthetics', 'transcribe', + 'transcribestreaming', 'transfer', 'xray'], + 'cn-northwest-1': ['application-autoscaling', 'athena', 'autoscaling', 'awsconnector', 'cassandra', + 'cloudformation', 'codedeploy-commands-secure', 'databrew', 'dms', 'ebs', 'ec2', 'ecr.api', 'ecr.dkr', + 'elasticbeanstalk', 'elasticfilesystem', 'elasticfilesystem-fips', 'execute-api', 'imagebuilder', + 'kinesis-streams', 'lambda', 'license-manager', 'monitoring', 'rds', 'redshift', 'redshift-data', 's3', + 'sagemaker.api', 'sagemaker.featurestore-runtime', 'sagemaker.runtime', 'servicecatalog', 'sms', 'sqs', + 'states', 'sts', 'synthetics', 'transcribe', 'transcribestreaming', 'transfer', 'workspaces', 'xray'], + }; + if (VPC_ENDPOINT_SERVICE_EXCEPTIONS[region]?.includes(name)) { + return 'cn.com.amazonaws'; + } else { + return 'com.amazonaws'; + } + } + + /** + * Get the endpoint suffix for the service in the specified region. + * In cn-north-1 and cn-northwest-1, the vpc endpoint of transcribe is: + * cn.com.amazonaws.cn-north-1.transcribe.cn + * cn.com.amazonaws.cn-northwest-1.transcribe.cn + * so suffix '.cn' should be return in these scenarios. + * + * For future maintenance, the vpc endpoint services could be fetched using AWS CLI Commmand: + * aws ec2 describe-vpc-endpoint-services + */ + private getDefaultEndpointSuffix(name: string, region: string) { + const VPC_ENDPOINT_SERVICE_EXCEPTIONS: { [region: string]: string[] } = { + 'cn-north-1': ['transcribe'], + 'cn-northwest-1': ['transcribe'], + }; + return VPC_ENDPOINT_SERVICE_EXCEPTIONS[region]?.includes(name) ? '.cn' : ''; + } } /** diff --git a/packages/@aws-cdk/aws-ec2/test/vpc-endpoint.test.ts b/packages/@aws-cdk/aws-ec2/test/vpc-endpoint.test.ts index a59dfbbca07eb..267c48a9e4145 100644 --- a/packages/@aws-cdk/aws-ec2/test/vpc-endpoint.test.ts +++ b/packages/@aws-cdk/aws-ec2/test/vpc-endpoint.test.ts @@ -607,5 +607,124 @@ nodeunitShim({ })); test.done(); }, + 'test vpc interface endpoint with cn.com.amazonaws prefix can be created correctly in cn-north-1'(test: Test) { + //GIVEN + const stack = new Stack(undefined, 'TestStack', { env: { account: '123456789012', region: 'cn-north-1' } }); + const vpc = new Vpc(stack, 'VPC'); + + //WHEN + vpc.addInterfaceEndpoint('ECR Endpoint', { + service: InterfaceVpcEndpointAwsService.ECR, + }); + + //THEN + expect(stack).to(haveResource('AWS::EC2::VPCEndpoint', { + ServiceName: 'cn.com.amazonaws.cn-north-1.ecr.api', + })); + + test.done(); + }, + 'test vpc interface endpoint with cn.com.amazonaws prefix can be created correctly in cn-northwest-1'(test: Test) { + //GIVEN + const stack = new Stack(undefined, 'TestStack', { env: { account: '123456789012', region: 'cn-northwest-1' } }); + const vpc = new Vpc(stack, 'VPC'); + + //WHEN + vpc.addInterfaceEndpoint('Lambda Endpoint', { + service: InterfaceVpcEndpointAwsService.LAMBDA, + }); + + //THEN + expect(stack).to(haveResource('AWS::EC2::VPCEndpoint', { + ServiceName: 'cn.com.amazonaws.cn-northwest-1.lambda', + })); + + test.done(); + }, + 'test vpc interface endpoint without cn.com.amazonaws prefix can be created correctly in cn-north-1'(test: Test) { + //GIVEN + const stack = new Stack(undefined, 'TestStack', { env: { account: '123456789012', region: 'cn-north-1' } }); + const vpc = new Vpc(stack, 'VPC'); + + //WHEN + vpc.addInterfaceEndpoint('ECS Endpoint', { + service: InterfaceVpcEndpointAwsService.ECS, + }); + + //THEN + expect(stack).to(haveResource('AWS::EC2::VPCEndpoint', { + ServiceName: 'com.amazonaws.cn-north-1.ecs', + })); + + test.done(); + }, + 'test vpc interface endpoint without cn.com.amazonaws prefix can be created correctly in cn-northwest-1'(test: Test) { + //GIVEN + const stack = new Stack(undefined, 'TestStack', { env: { account: '123456789012', region: 'cn-northwest-1' } }); + const vpc = new Vpc(stack, 'VPC'); + + //WHEN + vpc.addInterfaceEndpoint('Glue Endpoint', { + service: InterfaceVpcEndpointAwsService.GLUE, + }); + + //THEN + expect(stack).to(haveResource('AWS::EC2::VPCEndpoint', { + ServiceName: 'com.amazonaws.cn-northwest-1.glue', + })); + + test.done(); + }, + 'test vpc interface endpoint for transcribe can be created correctly in non-china regions'(test: Test) { + //GIVEN + const stack = new Stack(undefined, 'TestStack', { env: { account: '123456789012', region: 'us-east-1' } }); + const vpc = new Vpc(stack, 'VPC'); + + //WHEN + vpc.addInterfaceEndpoint('Transcribe Endpoint', { + service: InterfaceVpcEndpointAwsService.TRANSCRIBE, + }); + + //THEN + expect(stack).to(haveResource('AWS::EC2::VPCEndpoint', { + ServiceName: 'com.amazonaws.us-east-1.transcribe', + })); + + test.done(); + }, + 'test vpc interface endpoint for transcribe can be created correctly in cn-north-1'(test: Test) { + //GIVEN + const stack = new Stack(undefined, 'TestStack', { env: { account: '123456789012', region: 'cn-north-1' } }); + const vpc = new Vpc(stack, 'VPC'); + + //WHEN + vpc.addInterfaceEndpoint('Transcribe Endpoint', { + service: InterfaceVpcEndpointAwsService.TRANSCRIBE, + }); + + //THEN + expect(stack).to(haveResource('AWS::EC2::VPCEndpoint', { + ServiceName: 'cn.com.amazonaws.cn-north-1.transcribe.cn', + })); + + test.done(); + }, + 'test vpc interface endpoint for transcribe can be created correctly in cn-northwest-1'(test: Test) { + //GIVEN + const stack = new Stack(undefined, 'TestStack', { env: { account: '123456789012', region: 'cn-northwest-1' } }); + const vpc = new Vpc(stack, 'VPC'); + + //WHEN + vpc.addInterfaceEndpoint('Transcribe Endpoint', { + service: InterfaceVpcEndpointAwsService.TRANSCRIBE, + }); + + //THEN + expect(stack).to(haveResource('AWS::EC2::VPCEndpoint', { + ServiceName: 'cn.com.amazonaws.cn-northwest-1.transcribe.cn', + })); + + test.done(); + }, }, }); From 1be373c14350e2fade0874579f6196384dc8d3d2 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Tue, 24 Aug 2021 12:54:25 +0200 Subject: [PATCH 85/99] =?UTF-8?q?chore:=20`publishInParallel=3Dfalse`=20wi?= =?UTF-8?q?th=20tokens=20produces=20useless=20error=20m=E2=80=A6=20(#16196?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …essage When a buildspec is written to disk at synth time and the BuildSpec contains CFN references, the error produced is: ``` The "data" argument must be of type string or an instance of Buffer, TypedArray, or DataView. Received an instance of Object ``` Because it's trying to write the `{ Fn::Join }` instead of a plain string. This error message is pretty useless. Supporting the feature correctly is a lot more complicated, but at least we can detect this situation and give a more readable error message. Relates to #16164. ---- *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 | 10 +++++++- .../pipelines/test/docker-credentials.test.ts | 24 +++++++++++++++++-- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk/pipelines/lib/codepipeline/_codebuild-factory.ts b/packages/@aws-cdk/pipelines/lib/codepipeline/_codebuild-factory.ts index ac125aee29f0d..59abcbe8e287d 100644 --- a/packages/@aws-cdk/pipelines/lib/codepipeline/_codebuild-factory.ts +++ b/packages/@aws-cdk/pipelines/lib/codepipeline/_codebuild-factory.ts @@ -241,7 +241,15 @@ export class CodeBuildFactory implements ICodePipelineActionFactory { // Write to disk and replace with a reference const relativeSpecFile = `buildspec-${Node.of(scope).addr}-${this.constructId}.yaml`; const absSpecFile = path.join(cloudAssemblyBuildSpecDir(scope), relativeSpecFile); - fs.writeFileSync(absSpecFile, Stack.of(scope).resolve(actualBuildSpec.toBuildSpec()), { encoding: 'utf-8' }); + + // This should resolve to a pure JSON string. If it resolves to an object, it's a CFN + // expression, and we can't support that yet. Maybe someday if we think really hard about it. + const fileContents = Stack.of(scope).resolve(actualBuildSpec.toBuildSpec()); + + if (typeof fileContents !== 'string') { + throw new Error(`This BuildSpec contains CloudFormation references and is supported by publishInParallel=false: ${JSON.stringify(fileContents, undefined, 2)}`); + } + fs.writeFileSync(absSpecFile, fileContents, { encoding: 'utf-8' }); projectBuildSpec = codebuild.BuildSpec.fromSourceFilename(relativeSpecFile); } else { projectBuildSpec = actualBuildSpec; diff --git a/packages/@aws-cdk/pipelines/test/docker-credentials.test.ts b/packages/@aws-cdk/pipelines/test/docker-credentials.test.ts index de9d7efa54852..9e3559242e04c 100644 --- a/packages/@aws-cdk/pipelines/test/docker-credentials.test.ts +++ b/packages/@aws-cdk/pipelines/test/docker-credentials.test.ts @@ -6,12 +6,14 @@ import * as iam from '@aws-cdk/aws-iam'; import * as secretsmanager from '@aws-cdk/aws-secretsmanager'; import * as cdk from '@aws-cdk/core'; import * as cdkp from '../lib'; +import { ShellStep } from '../lib'; +import { DockerAssetApp, TestApp } from './testhelpers'; let app: cdk.App; let stack: cdk.Stack; beforeEach(() => { - app = new cdk.App(); + app = new TestApp(); stack = new cdk.Stack(app, 'Stack', { env: { account: '0123456789012', region: 'eu-west-1' }, }); @@ -299,9 +301,27 @@ describe('EcrDockerCredential', () => { expect(stack).not.toHaveResource('AWS::IAM::Policy'); }); - }); + // This test doesn't actually work yet. See https://github.com/aws/aws-cdk/issues/16164 + // eslint-disable-next-line jest/no-disabled-tests + test.skip('with non-parallel publishing', () => { + const pipelines = new cdkp.CodePipeline(stack, 'Pipeline', { + synth: new ShellStep('Build', { + input: cdkp.CodePipelineSource.gitHub('test/test', 'test'), + commands: ['cdk synth'], + }), + + publishAssetsInParallel: false, + dockerCredentials: [ + cdkp.DockerCredential.ecr([repo]), + ], + }); + pipelines.addStage(new DockerAssetApp(stack, 'AssetApp')); + + // Should not throw + app.synth(); + }); }); describe('dockerCredentialsInstallCommands', () => { From 9c39bcb970fc791e94d199b962cc006fca1a3320 Mon Sep 17 00:00:00 2001 From: Sam Wilson Date: Tue, 24 Aug 2021 06:56:44 -0500 Subject: [PATCH 86/99] fix(apigatewayv2): http api - disallow empty string as domain name (#16044) Currently, empty strings are allowed for custom domain name values despite other tools such as the AWS CLI not allowing empty string values. This effort brings the `DomainName` construct up to date with other tooling. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../aws-apigatewayv2/lib/common/domain-name.ts | 4 ++++ .../test/http/domain-name.test.ts | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/packages/@aws-cdk/aws-apigatewayv2/lib/common/domain-name.ts b/packages/@aws-cdk/aws-apigatewayv2/lib/common/domain-name.ts index 94d284c7f16c6..dca1a60bd4548 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/lib/common/domain-name.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/lib/common/domain-name.ts @@ -84,6 +84,10 @@ export class DomainName extends Resource implements IDomainName { constructor(scope: Construct, id: string, props: DomainNameProps) { super(scope, id); + if (props.domainName === '') { + throw new Error('empty string for domainName not allowed'); + } + const domainNameProps: CfnDomainNameProps = { domainName: props.domainName, domainNameConfigurations: [ diff --git a/packages/@aws-cdk/aws-apigatewayv2/test/http/domain-name.test.ts b/packages/@aws-cdk/aws-apigatewayv2/test/http/domain-name.test.ts index dc64fbf5bf7c9..30c981a1da1d5 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/test/http/domain-name.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/test/http/domain-name.test.ts @@ -29,6 +29,22 @@ describe('DomainName', () => { }); }); + test('throws when domainName is empty string', () => { + // GIVEN + const stack = new Stack(); + + // WHEN + const t = () => { + new DomainName(stack, 'DomainName', { + domainName: '', + certificate: Certificate.fromCertificateArn(stack, 'cert', certArn), + }); + }; + + // THEN + expect(t).toThrow(/empty string for domainName not allowed/); + }); + test('import domain name correctly', () => { // GIVEN const stack = new Stack(); From 305f683e86cca221705c0138572faa38043396eb Mon Sep 17 00:00:00 2001 From: Giedrius Kaskonas <57504623+gkaskonas@users.noreply.github.com> Date: Tue, 24 Aug 2021 15:47:49 +0100 Subject: [PATCH 87/99] feat(lambda): nodejs14.x supports inline code (#16131) Cloudformation now supports Inline code for NodeJS14 runtime. Updating CDK to reflect that ---- *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/lib/runtime.ts | 2 +- .../integ.runtime.inlinecode.expected.json | 55 +++++++++++++++++++ .../test/integ.runtime.inlinecode.ts | 7 +++ 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-lambda/lib/runtime.ts b/packages/@aws-cdk/aws-lambda/lib/runtime.ts index e354e5862cc6e..ae26ca066e1c9 100644 --- a/packages/@aws-cdk/aws-lambda/lib/runtime.ts +++ b/packages/@aws-cdk/aws-lambda/lib/runtime.ts @@ -77,7 +77,7 @@ export class Runtime { /** * The NodeJS 14.x runtime (nodejs14.x) */ - public static readonly NODEJS_14_X = new Runtime('nodejs14.x', RuntimeFamily.NODEJS, { supportsInlineCode: false }); + public static readonly NODEJS_14_X = new Runtime('nodejs14.x', RuntimeFamily.NODEJS, { supportsInlineCode: true }); /** * The Python 2.7 runtime (python2.7) diff --git a/packages/@aws-cdk/aws-lambda/test/integ.runtime.inlinecode.expected.json b/packages/@aws-cdk/aws-lambda/test/integ.runtime.inlinecode.expected.json index 30d39828cc39d..59961a0755b84 100644 --- a/packages/@aws-cdk/aws-lambda/test/integ.runtime.inlinecode.expected.json +++ b/packages/@aws-cdk/aws-lambda/test/integ.runtime.inlinecode.expected.json @@ -299,6 +299,56 @@ "DependsOn": [ "PYTHON38ServiceRole3EA86BBE" ] + }, + "NODEJS14XServiceRole4523ECDB": { + "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" + ] + ] + } + ] + } + }, + "NODEJS14X930214A3": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "exports.handler = async function(event) { return \"success\" }" + }, + "Role": { + "Fn::GetAtt": [ + "NODEJS14XServiceRole4523ECDB", + "Arn" + ] + }, + "Handler": "index.handler", + "Runtime": "nodejs14.x" + }, + "DependsOn": [ + "NODEJS14XServiceRole4523ECDB" + ] } }, "Outputs": { @@ -331,6 +381,11 @@ "Value": { "Ref": "PYTHON38A180AE47" } + }, + "NODEJS14XfunctionName": { + "Value": { + "Ref": "NODEJS14X930214A3" + } } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda/test/integ.runtime.inlinecode.ts b/packages/@aws-cdk/aws-lambda/test/integ.runtime.inlinecode.ts index 56f5bd27f7746..3bde19e5cd22b 100644 --- a/packages/@aws-cdk/aws-lambda/test/integ.runtime.inlinecode.ts +++ b/packages/@aws-cdk/aws-lambda/test/integ.runtime.inlinecode.ts @@ -57,4 +57,11 @@ const python38 = new Function(stack, 'PYTHON_3_8', { }); new CfnOutput(stack, 'PYTHON_3_8-functionName', { value: python38.functionName }); +const node14xfn = new Function(stack, 'NODEJS_14_X', { + code: new InlineCode('exports.handler = async function(event) { return "success" }'), + handler: 'index.handler', + runtime: Runtime.NODEJS_14_X, +}); +new CfnOutput(stack, 'NODEJS_14_X-functionName', { value: node14xfn.functionName }); + app.synth(); From 64019bbf090e156261feb626a5a4bd7ff4f26545 Mon Sep 17 00:00:00 2001 From: Emil Rowland Date: Tue, 24 Aug 2021 17:28:27 +0200 Subject: [PATCH 88/99] feat(cognito): user pools - device tracking (#16055) fixes #15013 This pull request adds the support of device configuration for Cognito user pools. [DeviceConfiguration](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cognito-userpool-deviceconfiguration.html) ---- *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-cognito/README.md | 18 +++++++++++++ .../@aws-cdk/aws-cognito/lib/user-pool.ts | 27 +++++++++++++++++++ .../aws-cognito/test/user-pool.test.ts | 21 +++++++++++++++ 3 files changed, 66 insertions(+) diff --git a/packages/@aws-cdk/aws-cognito/README.md b/packages/@aws-cdk/aws-cognito/README.md index bdb93fc24d566..b015607589652 100644 --- a/packages/@aws-cdk/aws-cognito/README.md +++ b/packages/@aws-cdk/aws-cognito/README.md @@ -45,6 +45,7 @@ This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aw - [Multi-factor Authentication](#multi-factor-authentication-mfa) - [Account Recovery Settings](#account-recovery-settings) - [Emails](#emails) + - [Device Tracking](#device-tracking) - [Lambda Triggers](#lambda-triggers) - [Trigger Permissions](#trigger-permissions) - [Import](#importing-user-pools) @@ -337,6 +338,23 @@ layer](https://docs.aws.amazon.com/cdk/latest/guide/cfn_layer.html) to configure If an email address contains non-ASCII characters, it will be encoded using the [punycode encoding](https://en.wikipedia.org/wiki/Punycode) when generating the template for Cloudformation. +### Device Tracking + +User pools can be configured to track devices that users have logged in to. +Read more at [Device Tracking](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-device-tracking.html) + +```ts +new cognito.UserPool(this, 'myuserpool', { + // ... + deviceTracking: { + challengeRequiredOnNewDevice: true, + deviceOnlyRememberedOnUserPrompt: true, + }, +}); +``` + +The default is to not track devices. + ### Lambda Triggers User pools can be configured such that AWS Lambda functions can be triggered when certain user operations or actions diff --git a/packages/@aws-cdk/aws-cognito/lib/user-pool.ts b/packages/@aws-cdk/aws-cognito/lib/user-pool.ts index 9f598761ee843..6277ee0f467ee 100644 --- a/packages/@aws-cdk/aws-cognito/lib/user-pool.ts +++ b/packages/@aws-cdk/aws-cognito/lib/user-pool.ts @@ -429,6 +429,26 @@ export enum AccountRecovery { NONE, } +/** + * Device tracking settings + * @see https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-device-tracking.html + */ +export interface DeviceTracking { + /** + * Indicates whether a challenge is required on a new device. Only applicable to a new device. + * @see https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-device-tracking.html + * @default false + */ + readonly challengeRequiredOnNewDevice: boolean; + + /** + * If true, a device is only remembered on user prompt. + * @see https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-device-tracking.html + * @default false + */ + readonly deviceOnlyRememberedOnUserPrompt: boolean; +} + /** * Props for the UserPool construct */ @@ -581,6 +601,12 @@ export interface UserPoolProps { * @default RemovalPolicy.RETAIN */ readonly removalPolicy?: RemovalPolicy; + + /** + * Device tracking settings + * @default - see defaults on each property of DeviceTracking. + */ + readonly deviceTracking?: DeviceTracking; } /** @@ -787,6 +813,7 @@ export class UserPool extends UserPoolBase { caseSensitive: props.signInCaseSensitive, }), accountRecoverySetting: this.accountRecovery(props), + deviceConfiguration: props.deviceTracking, }); userPool.applyRemovalPolicy(props.removalPolicy); diff --git a/packages/@aws-cdk/aws-cognito/test/user-pool.test.ts b/packages/@aws-cdk/aws-cognito/test/user-pool.test.ts index 75ed3dcfa1a2d..0c61312222355 100644 --- a/packages/@aws-cdk/aws-cognito/test/user-pool.test.ts +++ b/packages/@aws-cdk/aws-cognito/test/user-pool.test.ts @@ -1390,6 +1390,27 @@ describe('User Pool', () => { }); }); +test('device tracking is configured correctly', () => { + // GIVEN + const stack = new Stack(); + + // WHEN + new UserPool(stack, 'Pool', { + deviceTracking: { + challengeRequiredOnNewDevice: true, + deviceOnlyRememberedOnUserPrompt: true, + }, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Cognito::UserPool', { + DeviceConfiguration: { + ChallengeRequiredOnNewDevice: true, + DeviceOnlyRememberedOnUserPrompt: true, + }, + }); +}); + function fooFunction(scope: Construct, name: string): lambda.IFunction { return new lambda.Function(scope, name, { From 90f95e10f4dd9e4992731d6262dcfc767b65ab3f Mon Sep 17 00:00:00 2001 From: Niranjan Jayakar Date: Tue, 24 Aug 2021 17:08:35 +0100 Subject: [PATCH 89/99] feat(assertions): queries and assertions against the Outputs and Mappings sections (#15892) Introduce APIs `hasOutput()`, `findOutputs()`, `hasMapping()` and `findMappings()` to assert the `Mappings` and `Outputs` section of the CloudFormation template. Also, refactored the implementation of `hasResource()` to increase re-usability of its implementation across these new APIs. Migrated the modules `aws-kinesisfirehose` and `aws-neptune` that use these new APIs. ---- *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 | 18 +- packages/@aws-cdk/assertions/lib/match.ts | 12 +- packages/@aws-cdk/assertions/lib/matcher.ts | 8 + .../assertions/lib/private/mappings.ts | 31 ++++ .../assertions/lib/private/outputs.ts | 31 ++++ .../assertions/lib/private/resource.ts | 82 --------- .../assertions/lib/private/resources.ts | 42 +++++ .../assertions/lib/private/section.ts | 58 ++++++ packages/@aws-cdk/assertions/lib/template.ts | 50 +++++- .../assertions/test/private/section.test.ts | 43 +++++ .../@aws-cdk/assertions/test/template.test.ts | 166 +++++++++++++++++- .../@aws-cdk/aws-kinesisfirehose/package.json | 2 +- .../test/delivery-stream.test.ts | 153 +++++++--------- packages/@aws-cdk/aws-neptune/package.json | 4 +- .../@aws-cdk/aws-neptune/test/cluster.test.ts | 49 +++--- .../aws-neptune/test/instance.test.ts | 30 ++-- .../aws-neptune/test/parameter-group.test.ts | 10 +- .../aws-neptune/test/subnet-group.test.ts | 10 +- 18 files changed, 566 insertions(+), 233 deletions(-) create mode 100644 packages/@aws-cdk/assertions/lib/private/mappings.ts create mode 100644 packages/@aws-cdk/assertions/lib/private/outputs.ts delete mode 100644 packages/@aws-cdk/assertions/lib/private/resource.ts create mode 100644 packages/@aws-cdk/assertions/lib/private/resources.ts create mode 100644 packages/@aws-cdk/assertions/lib/private/section.ts create mode 100644 packages/@aws-cdk/assertions/test/private/section.test.ts diff --git a/packages/@aws-cdk/assertions/README.md b/packages/@aws-cdk/assertions/README.md index bfeb893417c31..67109b1156964 100644 --- a/packages/@aws-cdk/assertions/README.md +++ b/packages/@aws-cdk/assertions/README.md @@ -107,11 +107,23 @@ By default, the `hasResource()` and `hasResourceProperties()` APIs perform deep partial object matching. This behavior can be configured using matchers. See subsequent section on [special matchers](#special-matchers). +## Other Sections + +Similar to the `hasResource()` and `findResources()`, we have equivalent methods +to check and find other sections of the CloudFormation resources. + +* Outputs - `hasOutput()` and `findOutputs()` +* Mapping - `hasMapping()` and `findMappings()` + +All of the defaults and behaviour documented for `hasResource()` and +`findResources()` apply to these methods. + ## Special Matchers -The expectation provided to the `hasResourceXXX()` methods, besides carrying -literal values, as seen in the above examples, can also have special matchers -encoded. +The expectation provided to the `hasXXX()` and `findXXX()` methods, besides +carrying literal values, as seen in the above examples, also accept special +matchers. + They are available as part of the `Match` class. ### Object Matchers diff --git a/packages/@aws-cdk/assertions/lib/match.ts b/packages/@aws-cdk/assertions/lib/match.ts index 0272f344efcbc..2a88bada59bac 100644 --- a/packages/@aws-cdk/assertions/lib/match.ts +++ b/packages/@aws-cdk/assertions/lib/match.ts @@ -99,7 +99,7 @@ class LiteralMatch extends Matcher { return new ObjectMatch(this.name, this.pattern, { partial: this.partialObjects }).test(actual); } - const result = new MatchResult(); + const result = new MatchResult(actual); if (typeof this.pattern !== typeof actual) { result.push(this, [], `Expected type ${typeof this.pattern} but received ${getType(actual)}`); return result; @@ -152,16 +152,16 @@ class ArrayMatch extends Matcher { public test(actual: any): MatchResult { if (!Array.isArray(actual)) { - return new MatchResult().push(this, [], `Expected type array but received ${getType(actual)}`); + return new MatchResult(actual).push(this, [], `Expected type array but received ${getType(actual)}`); } if (!this.partial && this.pattern.length !== actual.length) { - return new MatchResult().push(this, [], `Expected array of length ${this.pattern.length} but received ${actual.length}`); + return new MatchResult(actual).push(this, [], `Expected array of length ${this.pattern.length} but received ${actual.length}`); } let patternIdx = 0; let actualIdx = 0; - const result = new MatchResult(); + const result = new MatchResult(actual); while (patternIdx < this.pattern.length && actualIdx < actual.length) { const patternElement = this.pattern[patternIdx]; const matcher = Matcher.isMatcher(patternElement) ? patternElement : new LiteralMatch(this.name, patternElement); @@ -220,10 +220,10 @@ class ObjectMatch extends Matcher { public test(actual: any): MatchResult { if (typeof actual !== 'object' || Array.isArray(actual)) { - return new MatchResult().push(this, [], `Expected type object but received ${getType(actual)}`); + return new MatchResult(actual).push(this, [], `Expected type object but received ${getType(actual)}`); } - const result = new MatchResult(); + const result = new MatchResult(actual); if (!this.partial) { for (const a of Object.keys(actual)) { if (!(a in this.pattern)) { diff --git a/packages/@aws-cdk/assertions/lib/matcher.ts b/packages/@aws-cdk/assertions/lib/matcher.ts index 0495b72d25c5a..a3263d6f00829 100644 --- a/packages/@aws-cdk/assertions/lib/matcher.ts +++ b/packages/@aws-cdk/assertions/lib/matcher.ts @@ -27,8 +27,16 @@ export abstract class Matcher { * The result of `Match.test()`. */ export class MatchResult { + /** + * The target for which this result was generated. + */ + public readonly target: any; private readonly failures: MatchFailure[] = []; + constructor(target: any) { + this.target = target; + } + /** * Push a new failure into this result at a specific path. * If the failure occurred at root of the match tree, set the path to an empty list. diff --git a/packages/@aws-cdk/assertions/lib/private/mappings.ts b/packages/@aws-cdk/assertions/lib/private/mappings.ts new file mode 100644 index 0000000000000..0def435cc0e1d --- /dev/null +++ b/packages/@aws-cdk/assertions/lib/private/mappings.ts @@ -0,0 +1,31 @@ +import { StackInspector } from '../vendored/assert'; +import { formatFailure, matchSection } from './section'; + +export function findMappings(inspector: StackInspector, props: any = {}): { [key: string]: any }[] { + const section: { [key: string] : {} } = inspector.value.Mappings; + const result = matchSection(section, props); + + if (!result.match) { + return []; + } + + return result.matches; +} + +export function hasMapping(inspector: StackInspector, props: any): string | void { + const section: { [key: string]: {} } = inspector.value.Mappings; + const result = matchSection(section, props); + + if (result.match) { + return; + } + + if (result.closestResult === undefined) { + return 'No mappings found in the template'; + } + + return [ + `Template has ${result.analyzedCount} mappings, but none match as expected.`, + formatFailure(result.closestResult), + ].join('\n'); +} \ No newline at end of file diff --git a/packages/@aws-cdk/assertions/lib/private/outputs.ts b/packages/@aws-cdk/assertions/lib/private/outputs.ts new file mode 100644 index 0000000000000..46e5a6cb1d52b --- /dev/null +++ b/packages/@aws-cdk/assertions/lib/private/outputs.ts @@ -0,0 +1,31 @@ +import { StackInspector } from '../vendored/assert'; +import { formatFailure, matchSection } from './section'; + +export function findOutputs(inspector: StackInspector, props: any = {}): { [key: string]: any }[] { + const section: { [key: string] : {} } = inspector.value.Outputs; + const result = matchSection(section, props); + + if (!result.match) { + return []; + } + + return result.matches; +} + +export function hasOutput(inspector: StackInspector, props: any): string | void { + const section: { [key: string]: {} } = inspector.value.Outputs; + const result = matchSection(section, props); + + if (result.match) { + return; + } + + if (result.closestResult === undefined) { + return 'No outputs found in the template'; + } + + return [ + `Template has ${result.analyzedCount} outputs, but none match as expected.`, + formatFailure(result.closestResult), + ].join('\n'); +} \ No newline at end of file diff --git a/packages/@aws-cdk/assertions/lib/private/resource.ts b/packages/@aws-cdk/assertions/lib/private/resource.ts deleted file mode 100644 index 22a2b01734b70..0000000000000 --- a/packages/@aws-cdk/assertions/lib/private/resource.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { Match } from '../match'; -import { Matcher, MatchResult } from '../matcher'; -import { StackInspector } from '../vendored/assert'; - -export function findResources(inspector: StackInspector, type: string, props: any = {}): { [key: string]: any }[] { - const matcher = Matcher.isMatcher(props) ? props : Match.objectLike(props); - let results: { [key: string]: any }[] = []; - - eachResourceWithType(inspector, type, (resource) => { - const result = matcher.test(resource); - if (!result.hasFailed()) { - results.push(resource); - } - }); - - return results; -} - -export function hasResource(inspector: StackInspector, type: string, props: any): string | void { - const matcher = Matcher.isMatcher(props) ? props : Match.objectLike(props); - let closestResult: MatchResult | undefined = undefined; - let closestResource: { [key: string]: any } | undefined = undefined; - let count: number = 0; - - let match = false; - eachResourceWithType(inspector, type, (resource) => { - if (match) { return; } - count++; - const result = matcher.test(resource); - if (!result.hasFailed()) { - match = true; - } - if (closestResult === undefined || closestResult.failCount > result.failCount) { - closestResult = result; - closestResource = resource; - } - }); - - if (match) { - return; - } - - if (closestResult === undefined) { - return `No resource with type ${type} found`; - } - - if (!closestResource) { - throw new Error('unexpected: closestResult is null'); - } - - return [ - `${count} resources with type ${type} found, but none match as expected.`, - formatMessage(closestResult, closestResource), - ].join('\n'); -} - -function eachResourceWithType( - inspector: StackInspector, - type: string, - cb: (resource: {[key: string]: any}) => void): void { - - for (const logicalId of Object.keys(inspector.value.Resources ?? {})) { - const resource: { [key: string]: any } = inspector.value.Resources[logicalId]; - if (resource.Type === type) { - cb(resource); - } - } -} - -function formatMessage(closestResult: MatchResult, closestResource: {}): string { - return [ - 'The closest result is:', - reindent(JSON.stringify(closestResource, undefined, 2)), - 'with the following mismatches:', - ...closestResult.toHumanStrings().map(s => `\t${s}`), - ].join('\n'); -} - -function reindent(x: string, indent: number = 2): string { - const pad = ' '.repeat(indent); - return pad + x.split('\n').join(`\n${pad}`); -} \ No newline at end of file diff --git a/packages/@aws-cdk/assertions/lib/private/resources.ts b/packages/@aws-cdk/assertions/lib/private/resources.ts new file mode 100644 index 0000000000000..31286a8a6f1a4 --- /dev/null +++ b/packages/@aws-cdk/assertions/lib/private/resources.ts @@ -0,0 +1,42 @@ +import { StackInspector } from '../vendored/assert'; +import { formatFailure, matchSection } from './section'; + +// Partial type for CloudFormation Resource +type Resource = { + Type: string; +} + +export function findResources(inspector: StackInspector, type: string, props: any = {}): { [key: string]: any }[] { + const section: { [key: string] : Resource } = inspector.value.Resources; + const result = matchSection(filterType(section, type), props); + + if (!result.match) { + return []; + } + + return result.matches; +} + +export function hasResource(inspector: StackInspector, type: string, props: any): string | void { + const section: { [key: string]: Resource } = inspector.value.Resources; + const result = matchSection(filterType(section, type), props); + + if (result.match) { + return; + } + + if (result.closestResult === undefined) { + return `No resource with type ${type} found`; + } + + return [ + `Template has ${result.analyzedCount} resources with type ${type}, but none match as expected.`, + formatFailure(result.closestResult), + ].join('\n'); +} + +function filterType(section: { [key: string]: Resource }, type: string): { [key: string]: Resource } { + return Object.entries(section ?? {}) + .filter(([_, v]) => v.Type === type) + .reduce((agg, [k, v]) => { return { ...agg, [k]: v }; }, {}); +} \ No newline at end of file diff --git a/packages/@aws-cdk/assertions/lib/private/section.ts b/packages/@aws-cdk/assertions/lib/private/section.ts new file mode 100644 index 0000000000000..d8f0123de20d6 --- /dev/null +++ b/packages/@aws-cdk/assertions/lib/private/section.ts @@ -0,0 +1,58 @@ +import { Match } from '../match'; +import { Matcher, MatchResult } from '../matcher'; + +export type MatchSuccess = { match: true, matches: any[] }; +export type MatchFailure = { match: false, closestResult?: MatchResult, analyzedCount: number }; + +export function matchSection(section: any, props: any): MatchSuccess | MatchFailure { + const matcher = Matcher.isMatcher(props) ? props : Match.objectLike(props); + let closestResult: MatchResult | undefined = undefined; + let matching: any[] = []; + let count = 0; + + eachEntryInSection( + section, + + (entry) => { + const result = matcher.test(entry); + if (!result.hasFailed()) { + matching.push(entry); + } else { + count++; + if (closestResult === undefined || closestResult.failCount > result.failCount) { + closestResult = result; + } + } + }, + ); + + if (matching.length > 0) { + return { match: true, matches: matching }; + } else { + return { match: false, closestResult, analyzedCount: count }; + } +} + +function eachEntryInSection( + section: any, + cb: (entry: {[key: string]: any}) => void): void { + + for (const logicalId of Object.keys(section ?? {})) { + const resource: { [key: string]: any } = section[logicalId]; + cb(resource); + } +} + +export function formatFailure(closestResult: MatchResult): string { + return [ + 'The closest result is:', + leftPad(JSON.stringify(closestResult.target, undefined, 2)), + 'with the following mismatches:', + ...closestResult.toHumanStrings().map(s => `\t${s}`), + ].join('\n'); +} + +function leftPad(x: string, indent: number = 2): string { + const pad = ' '.repeat(indent); + return pad + x.split('\n').join(`\n${pad}`); +} \ No newline at end of file diff --git a/packages/@aws-cdk/assertions/lib/template.ts b/packages/@aws-cdk/assertions/lib/template.ts index 480290bc45b04..848c46bcc295a 100644 --- a/packages/@aws-cdk/assertions/lib/template.ts +++ b/packages/@aws-cdk/assertions/lib/template.ts @@ -1,7 +1,9 @@ import { Stack, Stage } from '@aws-cdk/core'; import { Match } from './match'; import { Matcher } from './matcher'; -import { findResources, hasResource } from './private/resource'; +import { findMappings, hasMapping } from './private/mappings'; +import { findOutputs, hasOutput } from './private/outputs'; +import { findResources, hasResource } from './private/resources'; import * as assert from './vendored/assert'; /** @@ -103,6 +105,52 @@ export class Template { return findResources(this.inspector, type, props); } + /** + * Assert that an Output with the given properties exists in the CloudFormation template. + * By default, performs partial matching on the resource, via the `Match.objectLike()`. + * To configure different behavour, use other matchers in the `Match` class. + * @param props the output as should be expected in the template. + */ + public hasOutput(props: any): void { + const matchError = hasOutput(this.inspector, props); + if (matchError) { + throw new Error(matchError); + } + } + + /** + * Get the set of matching Outputs that match the given properties in the CloudFormation template. + * @param props by default, matches all Outputs in the template. + * When a literal object is provided, performs a partial match via `Match.objectLike()`. + * Use the `Match` APIs to configure a different behaviour. + */ + public findOutputs(props: any = {}): { [key: string]: any }[] { + return findOutputs(this.inspector, props); + } + + /** + * Assert that a Mapping with the given properties exists in the CloudFormation template. + * By default, performs partial matching on the resource, via the `Match.objectLike()`. + * To configure different behavour, use other matchers in the `Match` class. + * @param props the output as should be expected in the template. + */ + public hasMapping(props: any): void { + const matchError = hasMapping(this.inspector, props); + if (matchError) { + throw new Error(matchError); + } + } + + /** + * Get the set of matching Mappings that match the given properties in the CloudFormation template. + * @param props by default, matches all Mappings in the template. + * When a literal object is provided, performs a partial match via `Match.objectLike()`. + * Use the `Match` APIs to configure a different behaviour. + */ + public findMappings(props: any = {}): { [key: string]: any }[] { + return findMappings(this.inspector, props); + } + /** * Assert that the CloudFormation template matches the given value * @param expected the expected CloudFormation template as key-value pairs. diff --git a/packages/@aws-cdk/assertions/test/private/section.test.ts b/packages/@aws-cdk/assertions/test/private/section.test.ts new file mode 100644 index 0000000000000..20cc2d5d14e0b --- /dev/null +++ b/packages/@aws-cdk/assertions/test/private/section.test.ts @@ -0,0 +1,43 @@ +import { Match } from '../../lib'; +import { MatchFailure, matchSection, MatchSuccess } from '../../lib/private/section'; + +describe('section', () => { + describe('matchSection', () => { + test('success', () => { + // GIVEN + const matcher = Match.objectLike({ foo: 'bar' }); + const section = { + Entry1: { foo: 'bar' }, + Entry2: { foo: 'bar', baz: 'qux' }, + Entry3: { fred: 'waldo' }, + }; + + // WHEN + const result = matchSection(section, matcher); + + // THEN + expect(result.match).toEqual(true); + const success = result as MatchSuccess; + expect(success.matches.length).toEqual(2); + }); + + test('failure', () => { + // GIVEN + const matcher = Match.objectLike({ foo: 'bar' }); + const section = { + Entry1: { foo: 'qux' }, + Entry3: { fred: 'waldo' }, + }; + + // WHEN + const result = matchSection(section, matcher); + + // THEN + expect(result.match).toEqual(false); + const success = result as MatchFailure; + expect(success.analyzedCount).toEqual(2); + expect(success.closestResult).toBeDefined(); + expect(success.closestResult?.target).toEqual({ foo: 'qux' }); + }); + }); +}); \ No newline at end of file diff --git a/packages/@aws-cdk/assertions/test/template.test.ts b/packages/@aws-cdk/assertions/test/template.test.ts index fcbc199f1f2da..50fb60a1a27f7 100644 --- a/packages/@aws-cdk/assertions/test/template.test.ts +++ b/packages/@aws-cdk/assertions/test/template.test.ts @@ -1,4 +1,4 @@ -import { App, CfnResource, Stack } from '@aws-cdk/core'; +import { App, CfnMapping, CfnOutput, CfnResource, Stack } from '@aws-cdk/core'; import { Construct } from 'constructs'; import { Match, Template } from '../lib'; @@ -330,6 +330,170 @@ describe('Template', () => { expect(inspect.findResources('Foo::Bar').length).toEqual(2); }); }); + + describe('hasOutput', () => { + test('matching', () => { + const stack = new Stack(); + new CfnOutput(stack, 'Foo', { + value: 'Bar', + }); + new CfnOutput(stack, 'Fred', { + value: 'Waldo', + }); + + const inspect = Template.fromStack(stack); + expect(() => inspect.hasOutput({ Value: 'Bar' })).not.toThrow(); + }); + + test('not matching', (done) => { + const stack = new Stack(); + new CfnOutput(stack, 'Foo', { + value: 'Bar', + exportName: 'ExportBar', + }); + new CfnOutput(stack, 'Fred', { + value: 'Waldo', + }); + + const inspect = Template.fromStack(stack); + expectToThrow( + () => inspect.hasOutput({ + Value: 'Bar', + Export: { Name: 'ExportBaz' }, + }), + [ + /2 outputs/, + /Expected ExportBaz but received ExportBar/, + ], + done, + ); + done(); + }); + }); + + describe('findOutputs', () => { + test('matching', () => { + const stack = new Stack(); + new CfnOutput(stack, 'Foo', { + value: 'Fred', + description: 'FooFred', + }); + new CfnOutput(stack, 'Bar', { + value: 'Fred', + description: 'BarFred', + }); + new CfnOutput(stack, 'Baz', { + value: 'Waldo', + description: 'BazWaldo', + }); + + const inspect = Template.fromStack(stack); + const result = inspect.findOutputs({ Value: 'Fred' }); + expect(result).toEqual([ + { Value: 'Fred', Description: 'FooFred' }, + { Value: 'Fred', Description: 'BarFred' }, + ]); + }); + + test('not matching', () => { + const stack = new Stack(); + new CfnOutput(stack, 'Foo', { + value: 'Fred', + }); + + const inspect = Template.fromStack(stack); + const result = inspect.findOutputs({ Value: 'Waldo' }); + expect(result.length).toEqual(0); + }); + }); + + describe('hasMapping', () => { + test('matching', () => { + const stack = new Stack(); + new CfnMapping(stack, 'Foo', { + mapping: { + Foo: { Bar: 'Lightning', Fred: 'Waldo' }, + Baz: { Bar: 'Qux' }, + }, + }); + new CfnMapping(stack, 'Fred', { + mapping: { + Foo: { Bar: 'Lightning' }, + }, + }); + + const inspect = Template.fromStack(stack); + expect(() => inspect.hasMapping({ Foo: { Bar: 'Lightning' } })).not.toThrow(); + }); + + test('not matching', (done) => { + const stack = new Stack(); + new CfnMapping(stack, 'Foo', { + mapping: { + Foo: { Bar: 'Fred', Baz: 'Waldo' }, + Qux: { Bar: 'Fred' }, + }, + }); + new CfnMapping(stack, 'Fred', { + mapping: { + Foo: { Baz: 'Baz' }, + }, + }); + + const inspect = Template.fromStack(stack); + expectToThrow( + () => inspect.hasMapping({ + Foo: { Bar: 'Qux' }, + }), + [ + /2 mappings/, + /Expected Qux but received Fred/, + ], + done, + ); + done(); + }); + }); + + describe('findMappings', () => { + test('matching', () => { + const stack = new Stack(); + new CfnMapping(stack, 'Foo', { + mapping: { + Foo: { Bar: 'Lightning', Fred: 'Waldo' }, + Baz: { Bar: 'Qux' }, + }, + }); + new CfnMapping(stack, 'Fred', { + mapping: { + Foo: { Bar: 'Lightning' }, + }, + }); + + const inspect = Template.fromStack(stack); + const result = inspect.findMappings({ Foo: { Bar: 'Lightning' } }); + expect(result).toEqual([ + { + Foo: { Bar: 'Lightning', Fred: 'Waldo' }, + Baz: { Bar: 'Qux' }, + }, + { Foo: { Bar: 'Lightning' } }, + ]); + }); + + test('not matching', () => { + const stack = new Stack(); + new CfnMapping(stack, 'Foo', { + mapping: { + Foo: { Bar: 'Fred', Baz: 'Waldo' }, + }, + }); + + const inspect = Template.fromStack(stack); + const result = inspect.findMappings({ Foo: { Bar: 'Waldo' } }); + expect(result.length).toEqual(0); + }); + }); }); function expectToThrow(fn: () => void, msgs: (RegExp | string)[], done: jest.DoneCallback): void { diff --git a/packages/@aws-cdk/aws-kinesisfirehose/package.json b/packages/@aws-cdk/aws-kinesisfirehose/package.json index 58c5568c8c299..fe73affa84c97 100644 --- a/packages/@aws-cdk/aws-kinesisfirehose/package.json +++ b/packages/@aws-cdk/aws-kinesisfirehose/package.json @@ -73,7 +73,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "@aws-cdk/aws-s3": "0.0.0", "@types/jest": "^26.0.24", "cdk-build-tools": "0.0.0", diff --git a/packages/@aws-cdk/aws-kinesisfirehose/test/delivery-stream.test.ts b/packages/@aws-cdk/aws-kinesisfirehose/test/delivery-stream.test.ts index 345e7feb0774a..7c36a29e379b5 100644 --- a/packages/@aws-cdk/aws-kinesisfirehose/test/delivery-stream.test.ts +++ b/packages/@aws-cdk/aws-kinesisfirehose/test/delivery-stream.test.ts @@ -1,5 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; -import { ABSENT, ResourcePart, SynthUtils, anything, arrayWith } from '@aws-cdk/assert-internal'; +import { Match, Template } from '@aws-cdk/assertions'; import * as cloudwatch from '@aws-cdk/aws-cloudwatch'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as iam from '@aws-cdk/aws-iam'; @@ -47,11 +46,11 @@ describe('delivery stream', () => { destinations: [mockS3Destination], }); - expect(stack).toHaveResource('AWS::KinesisFirehose::DeliveryStream', { - DeliveryStreamEncryptionConfigurationInput: ABSENT, - DeliveryStreamName: ABSENT, + Template.fromStack(stack).hasResourceProperties('AWS::KinesisFirehose::DeliveryStream', { + DeliveryStreamEncryptionConfigurationInput: Match.absentProperty(), + DeliveryStreamName: Match.absentProperty(), DeliveryStreamType: 'DirectPut', - KinesisStreamSourceConfiguration: ABSENT, + KinesisStreamSourceConfiguration: Match.absentProperty(), ExtendedS3DestinationConfiguration: { BucketARN: bucketArn, RoleARN: roleArn, @@ -77,14 +76,14 @@ describe('delivery stream', () => { destinations: [mockS3Destination], }); - expect(stack).toHaveResourceLike('AWS::IAM::Role', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Role', { AssumeRolePolicyDocument: { Statement: [ - { + Match.objectLike({ Principal: { Service: 'firehose.amazonaws.com', }, - }, + }), ], }, }); @@ -99,32 +98,33 @@ describe('delivery stream', () => { role: deliveryStreamRole, }); - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { - Action: arrayWith( - 'kinesis:DescribeStream', + Effect: 'Allow', + Action: Match.arrayWith([ 'kinesis:GetRecords', 'kinesis:GetShardIterator', 'kinesis:ListShards', - ), + 'kinesis:DescribeStream', + ]), Resource: stack.resolve(sourceStream.streamArn), }, ], }, Roles: [stack.resolve(deliveryStreamRole.roleName)], }); - expect(stack).toHaveResource('AWS::KinesisFirehose::DeliveryStream', { + Template.fromStack(stack).hasResourceProperties('AWS::KinesisFirehose::DeliveryStream', { DeliveryStreamType: 'KinesisStreamAsSource', KinesisStreamSourceConfiguration: { KinesisStreamARN: stack.resolve(sourceStream.streamArn), RoleARN: stack.resolve(deliveryStreamRole.roleArn), }, }); - expect(stack).toHaveResourceLike('AWS::KinesisFirehose::DeliveryStream', { - DependsOn: arrayWith('DeliveryStreamRoleDefaultPolicy2759968B'), - }, ResourcePart.CompleteDefinition); + Template.fromStack(stack).hasResource('AWS::KinesisFirehose::DeliveryStream', { + DependsOn: Match.arrayWith(['DeliveryStreamRoleDefaultPolicy2759968B']), + }); }); test('requesting customer-owned encryption creates key and configuration', () => { @@ -134,21 +134,21 @@ describe('delivery stream', () => { role: deliveryStreamRole, }); - expect(stack).toHaveResource('AWS::KMS::Key'); - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).resourceCountIs('AWS::KMS::Key', 1); + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ - { - Action: arrayWith( - 'kms:Encrypt', + Match.objectLike({ + Action: Match.arrayWith([ 'kms:Decrypt', - ), - }, + 'kms:Encrypt', + ]), + }), ], }, Roles: [stack.resolve(deliveryStreamRole.roleName)], }); - expect(stack).toHaveResourceLike('AWS::KinesisFirehose::DeliveryStream', { + Template.fromStack(stack).hasResourceProperties('AWS::KinesisFirehose::DeliveryStream', { DeliveryStreamEncryptionConfigurationInput: { KeyARN: { 'Fn::GetAtt': [ @@ -170,22 +170,22 @@ describe('delivery stream', () => { role: deliveryStreamRole, }); - expect(stack).toHaveResource('AWS::KMS::Key'); - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).resourceCountIs('AWS::KMS::Key', 1); + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ - { - Action: arrayWith( - 'kms:Encrypt', + Match.objectLike({ + Action: Match.arrayWith([ 'kms:Decrypt', - ), + 'kms:Encrypt', + ]), Resource: stack.resolve(key.keyArn), - }, + }), ], }, Roles: [stack.resolve(deliveryStreamRole.roleName)], }); - expect(stack).toHaveResourceLike('AWS::KinesisFirehose::DeliveryStream', { + Template.fromStack(stack).hasResourceProperties('AWS::KinesisFirehose::DeliveryStream', { DeliveryStreamEncryptionConfigurationInput: { KeyARN: stack.resolve(key.keyArn), KeyType: 'CUSTOMER_MANAGED_CMK', @@ -200,24 +200,12 @@ describe('delivery stream', () => { role: deliveryStreamRole, }); - expect(stack).not.toHaveResource('AWS::KMS::Key'); - expect(stack).not.toHaveResourceLike('AWS::IAM::Policy', { - PolicyDocument: { - Statement: [ - { - Action: arrayWith( - 'kms:Encrypt', - 'kms:Decrypt', - ), - }, - ], - }, - Roles: [stack.resolve(deliveryStreamRole.roleName)], - }); - expect(stack).toHaveResourceLike('AWS::KinesisFirehose::DeliveryStream', { + Template.fromStack(stack).resourceCountIs('AWS::KMS::Key', 0); + Template.fromStack(stack).resourceCountIs('AWS::IAM::Policy', 0); + Template.fromStack(stack).hasResourceProperties('AWS::KinesisFirehose::DeliveryStream', { DeliveryStreamType: 'DirectPut', DeliveryStreamEncryptionConfigurationInput: { - KeyARN: ABSENT, + KeyARN: Match.absentProperty(), KeyType: 'AWS_OWNED_CMK', }, }); @@ -230,23 +218,11 @@ describe('delivery stream', () => { role: deliveryStreamRole, }); - expect(stack).not.toHaveResource('AWS::KMS::Key'); - expect(stack).not.toHaveResourceLike('AWS::IAM::Policy', { - PolicyDocument: { - Statement: [ - { - Action: arrayWith( - 'kms:Encrypt', - 'kms:Decrypt', - ), - }, - ], - }, - Roles: [stack.resolve(deliveryStreamRole.roleName)], - }); - expect(stack).toHaveResourceLike('AWS::KinesisFirehose::DeliveryStream', { + Template.fromStack(stack).resourceCountIs('AWS::KMS::Key', 0); + Template.fromStack(stack).resourceCountIs('AWS::IAM::Policy', 0); + Template.fromStack(stack).hasResourceProperties('AWS::KinesisFirehose::DeliveryStream', { DeliveryStreamType: 'DirectPut', - DeliveryStreamEncryptionConfigurationInput: ABSENT, + DeliveryStreamEncryptionConfigurationInput: Match.absentProperty(), }); }); @@ -300,13 +276,13 @@ describe('delivery stream', () => { deliveryStream.grant(role, 'firehose:PutRecord'); - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ - { + Match.objectLike({ Action: 'firehose:PutRecord', Resource: stack.resolve(deliveryStream.deliveryStreamArn), - }, + }), ], }, Roles: [stack.resolve(role.roleName)], @@ -323,16 +299,16 @@ describe('delivery stream', () => { deliveryStream.grantPutRecords(role); - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ - { + Match.objectLike({ Action: [ 'firehose:PutRecord', 'firehose:PutRecordBatch', ], Resource: stack.resolve(deliveryStream.deliveryStreamArn), - }, + }), ], }, Roles: [stack.resolve(role.roleName)], @@ -346,12 +322,12 @@ describe('delivery stream', () => { destinations: [mockS3Destination], }); - expect(stack).toHaveResourceLike('AWS::KinesisFirehose::DeliveryStream', { + Template.fromStack(stack).hasResource('AWS::KinesisFirehose::DeliveryStream', { DependsOn: [dependableId], - }, ResourcePart.CompleteDefinition); - expect(stack).toHaveResourceLike('AWS::IAM::Role', { - DependsOn: ABSENT, - }, ResourcePart.CompleteDefinition); + }); + Template.fromStack(stack).hasResource('AWS::IAM::Role', { + DependsOn: Match.absentProperty(), + }); }); test('supplying 0 or multiple destinations throws', () => { @@ -472,19 +448,18 @@ describe('delivery stream', () => { securityGroup.connections.allowFrom(deliveryStream, ec2.Port.allTcp()); - expect(stack).toHaveResourceLike('AWS::EC2::SecurityGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroup', { SecurityGroupIngress: [ - { + Match.objectLike({ CidrIp: { - 'Fn::FindInMap': [ - anything(), + 'Fn::FindInMap': Match.arrayWith([ { Ref: 'AWS::Region', }, 'FirehoseCidrBlock', - ], + ]), }, - }, + }), ], }); }); @@ -499,11 +474,11 @@ describe('delivery stream', () => { securityGroup.connections.allowFrom(deliveryStream, ec2.Port.allTcp()); - expect(stack).toHaveResourceLike('AWS::EC2::SecurityGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroup', { SecurityGroupIngress: [ - { + Match.objectLike({ CidrIp: '13.57.135.192/27', - }, + }), ], }); }); @@ -516,7 +491,11 @@ describe('delivery stream', () => { destinations: [mockS3Destination], }); - expect(Object.keys(SynthUtils.toCloudFormation(stack).Mappings).length).toBe(1); + Template.fromStack(stack).hasMapping({ + 'af-south-1': { + FirehoseCidrBlock: '13.244.121.224/27', + }, + }); }); test('can add tags', () => { @@ -526,7 +505,7 @@ describe('delivery stream', () => { cdk.Tags.of(deliveryStream).add('tagKey', 'tagValue'); - expect(stack).toHaveResource('AWS::KinesisFirehose::DeliveryStream', { + Template.fromStack(stack).hasResourceProperties('AWS::KinesisFirehose::DeliveryStream', { Tags: [ { Key: 'tagKey', diff --git a/packages/@aws-cdk/aws-neptune/package.json b/packages/@aws-cdk/aws-neptune/package.json index dfc50d27ac70d..b3a429fb6642a 100644 --- a/packages/@aws-cdk/aws-neptune/package.json +++ b/packages/@aws-cdk/aws-neptune/package.json @@ -74,12 +74,12 @@ }, "license": "Apache-2.0", "devDependencies": { + "@aws-cdk/assertions": "0.0.0", "@types/jest": "^26.0.24", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", - "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "pkglint": "0.0.0" }, "dependencies": { "@aws-cdk/aws-ec2": "0.0.0", diff --git a/packages/@aws-cdk/aws-neptune/test/cluster.test.ts b/packages/@aws-cdk/aws-neptune/test/cluster.test.ts index 24e61c8be34a1..74f4770a8a74c 100644 --- a/packages/@aws-cdk/aws-neptune/test/cluster.test.ts +++ b/packages/@aws-cdk/aws-neptune/test/cluster.test.ts @@ -1,5 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; -import { ABSENT, ResourcePart } from '@aws-cdk/assert-internal'; +import { Match, Template } from '@aws-cdk/assertions'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as iam from '@aws-cdk/aws-iam'; import * as kms from '@aws-cdk/aws-kms'; @@ -21,7 +20,7 @@ describe('DatabaseCluster', () => { }); // THEN - expect(stack).toHaveResource('AWS::Neptune::DBCluster', { + Template.fromStack(stack).hasResource('AWS::Neptune::DBCluster', { Properties: { DBSubnetGroupName: { Ref: 'DatabaseSubnets3C9252C9' }, VpcSecurityGroupIds: [{ 'Fn::GetAtt': ['DatabaseSecurityGroup5C91FDCB', 'GroupId'] }], @@ -29,14 +28,14 @@ describe('DatabaseCluster', () => { }, DeletionPolicy: 'Retain', UpdateReplacePolicy: 'Retain', - }, ResourcePart.CompleteDefinition); + }); - expect(stack).toHaveResource('AWS::Neptune::DBInstance', { + Template.fromStack(stack).hasResource('AWS::Neptune::DBInstance', { DeletionPolicy: 'Retain', UpdateReplacePolicy: 'Retain', - }, ResourcePart.CompleteDefinition); + }); - expect(stack).toHaveResource('AWS::Neptune::DBSubnetGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::Neptune::DBSubnetGroup', { SubnetIds: [ { Ref: 'VPCPrivateSubnet1Subnet8BCA10E0' }, { Ref: 'VPCPrivateSubnet2SubnetCFCDAA7A' }, @@ -58,7 +57,7 @@ describe('DatabaseCluster', () => { }); // THEN - expect(stack).toHaveResource('AWS::Neptune::DBCluster', { + Template.fromStack(stack).hasResourceProperties('AWS::Neptune::DBCluster', { DBSubnetGroupName: { Ref: 'DatabaseSubnets3C9252C9' }, VpcSecurityGroupIds: [{ 'Fn::GetAtt': ['DatabaseSecurityGroup5C91FDCB', 'GroupId'] }], }); @@ -112,7 +111,7 @@ describe('DatabaseCluster', () => { }); // THEN - expect(stack).toHaveResource('AWS::Neptune::DBCluster', { + Template.fromStack(stack).hasResourceProperties('AWS::Neptune::DBCluster', { EngineVersion: '1.0.4.1', DBSubnetGroupName: { Ref: 'DatabaseSubnets3C9252C9' }, VpcSecurityGroupIds: [{ 'Fn::GetAtt': ['DatabaseSecurityGroup5C91FDCB', 'GroupId'] }], @@ -136,7 +135,7 @@ describe('DatabaseCluster', () => { }); // THEN - expect(stack).toHaveResource('AWS::Neptune::DBCluster', { + Template.fromStack(stack).hasResourceProperties('AWS::Neptune::DBCluster', { DBSubnetGroupName: { Ref: 'DatabaseSubnets3C9252C9' }, VpcSecurityGroupIds: ['SecurityGroupId12345'], }); @@ -161,7 +160,7 @@ describe('DatabaseCluster', () => { }); // THEN - expect(stack).toHaveResource('AWS::Neptune::DBCluster', { + Template.fromStack(stack).hasResourceProperties('AWS::Neptune::DBCluster', { DBClusterParameterGroupName: { Ref: 'ParamsA8366201' }, }); }); @@ -184,7 +183,7 @@ describe('DatabaseCluster', () => { }); // THEN - expect(stack).toHaveResource('AWS::Neptune::DBCluster', { + Template.fromStack(stack).hasResourceProperties('AWS::Neptune::DBCluster', { AssociatedRoles: [ { RoleArn: { @@ -213,7 +212,7 @@ describe('DatabaseCluster', () => { }); // THEN - expect(stack).toHaveResource('AWS::Neptune::DBCluster', { + Template.fromStack(stack).hasResourceProperties('AWS::Neptune::DBCluster', { DBClusterParameterGroupName: 'ParamGroupName', }); }); @@ -231,7 +230,7 @@ describe('DatabaseCluster', () => { }); // THEN - expect(stack).toHaveResource('AWS::Neptune::DBCluster', { + Template.fromStack(stack).hasResourceProperties('AWS::Neptune::DBCluster', { KmsKeyId: { 'Fn::GetAtt': [ 'Key961B73FD', @@ -254,7 +253,7 @@ describe('DatabaseCluster', () => { }); // THEN - expect(stack).toHaveResource('AWS::Neptune::DBCluster', { + Template.fromStack(stack).hasResourceProperties('AWS::Neptune::DBCluster', { StorageEncrypted: true, }); }); @@ -307,7 +306,7 @@ describe('DatabaseCluster', () => { }); // THEN - expect(stack).toHaveResource('AWS::Neptune::DBInstance', { + Template.fromStack(stack).hasResourceProperties('AWS::Neptune::DBInstance', { DBInstanceIdentifier: `${instanceIdentifierBase}1`, }); }); @@ -326,7 +325,7 @@ describe('DatabaseCluster', () => { }); // THEN - expect(stack).toHaveResource('AWS::Neptune::DBInstance', { + Template.fromStack(stack).hasResourceProperties('AWS::Neptune::DBInstance', { DBInstanceIdentifier: `${clusterIdentifier}instance1`, }); }); @@ -373,7 +372,7 @@ describe('DatabaseCluster', () => { cluster.connections.allowToAnyIpv4(ec2.Port.tcp(443)); // THEN - expect(stack).toHaveResource('AWS::EC2::SecurityGroupEgress', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupEgress', { GroupId: 'sg-123456789', }); }); @@ -391,7 +390,7 @@ describe('DatabaseCluster', () => { }); // THEN - expect(stack).toHaveResource('AWS::Neptune::DBCluster', { + Template.fromStack(stack).hasResourceProperties('AWS::Neptune::DBCluster', { BackupRetentionPeriod: 20, }); }); @@ -410,7 +409,7 @@ describe('DatabaseCluster', () => { }); // THEN - expect(stack).toHaveResource('AWS::Neptune::DBCluster', { + Template.fromStack(stack).hasResourceProperties('AWS::Neptune::DBCluster', { BackupRetentionPeriod: 20, PreferredBackupWindow: '07:34-08:04', }); @@ -429,7 +428,7 @@ describe('DatabaseCluster', () => { }); // THEN - expect(stack).toHaveResource('AWS::Neptune::DBCluster', { + Template.fromStack(stack).hasResourceProperties('AWS::Neptune::DBCluster', { PreferredMaintenanceWindow: '07:34-08:04', }); }); @@ -446,8 +445,8 @@ describe('DatabaseCluster', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::Neptune::DBCluster', { - IamAuthEnabled: ABSENT, + Template.fromStack(stack).hasResourceProperties('AWS::Neptune::DBCluster', { + IamAuthEnabled: Match.absentProperty(), }); }); @@ -467,10 +466,10 @@ describe('DatabaseCluster', () => { cluster.grantConnect(role); // THEN - expect(stack).toHaveResourceLike('AWS::Neptune::DBCluster', { + Template.fromStack(stack).hasResourceProperties('AWS::Neptune::DBCluster', { IamAuthEnabled: true, }); - expect(stack).toHaveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [{ Effect: 'Allow', diff --git a/packages/@aws-cdk/aws-neptune/test/instance.test.ts b/packages/@aws-cdk/aws-neptune/test/instance.test.ts index dff005199ffc7..38a6981ab2a78 100644 --- a/packages/@aws-cdk/aws-neptune/test/instance.test.ts +++ b/packages/@aws-cdk/aws-neptune/test/instance.test.ts @@ -1,4 +1,4 @@ -import { expect as expectCDK, haveOutput, haveResource, ResourcePart } from '@aws-cdk/assert-internal'; +import { Template } from '@aws-cdk/assertions'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as cdk from '@aws-cdk/core'; import * as constructs from 'constructs'; @@ -17,14 +17,14 @@ describe('DatabaseInstance', () => { }); // THEN - expectCDK(stack).to(haveResource('AWS::Neptune::DBInstance', { + Template.fromStack(stack).hasResource('AWS::Neptune::DBInstance', { Properties: { DBClusterIdentifier: { Ref: 'DatabaseB269D8BB' }, DBInstanceClass: 'db.r5.large', }, DeletionPolicy: 'Retain', UpdateReplacePolicy: 'Retain', - }, ResourcePart.CompleteDefinition)); + }); }); test('check that the endpoint works', () => { @@ -43,9 +43,9 @@ describe('DatabaseInstance', () => { }); // THEN - expectCDK(stack).to(haveOutput({ - exportName, - outputValue: { + Template.fromStack(stack).hasOutput({ + Export: { Name: exportName }, + Value: { 'Fn::Join': [ '', [ @@ -55,7 +55,7 @@ describe('DatabaseInstance', () => { ], ], }, - })); + }); }); test('check importing works as expected', () => { @@ -78,10 +78,10 @@ describe('DatabaseInstance', () => { }); // THEN - expectCDK(stack).to(haveOutput({ - exportName: endpointExportName, - outputValue: `${instanceEndpointAddress}:${port}`, - })); + Template.fromStack(stack).hasOutput({ + Export: { Name: endpointExportName }, + Value: `${instanceEndpointAddress}:${port}`, + }); }); test('instance with parameter group', () => { @@ -102,9 +102,9 @@ describe('DatabaseInstance', () => { }); // THEN - expectCDK(stack).to(haveResource('AWS::Neptune::DBInstance', { + Template.fromStack(stack).hasResourceProperties('AWS::Neptune::DBInstance', { DBParameterGroupName: { Ref: 'ParamsA8366201' }, - })); + }); }); test('instance type from CfnParameter', () => { @@ -130,11 +130,11 @@ describe('DatabaseInstance', () => { }); // THEN - expectCDK(stack).to(haveResource('AWS::Neptune::DBInstance', { + Template.fromStack(stack).hasResourceProperties('AWS::Neptune::DBInstance', { DBInstanceClass: { Ref: 'NeptuneInstaneType', }, - })); + }); }); test('instance type from string throws if missing db prefix', () => { diff --git a/packages/@aws-cdk/aws-neptune/test/parameter-group.test.ts b/packages/@aws-cdk/aws-neptune/test/parameter-group.test.ts index 3267f70aed062..57d71b1767734 100644 --- a/packages/@aws-cdk/aws-neptune/test/parameter-group.test.ts +++ b/packages/@aws-cdk/aws-neptune/test/parameter-group.test.ts @@ -1,4 +1,4 @@ -import { expect, haveResource } from '@aws-cdk/assert-internal'; +import { Template } from '@aws-cdk/assertions'; import { Stack } from '@aws-cdk/core'; import { ClusterParameterGroup, ParameterGroup } from '../lib'; @@ -17,12 +17,12 @@ describe('ClusterParameterGroup', () => { }); // THEN - expect(stack).to(haveResource('AWS::Neptune::DBClusterParameterGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::Neptune::DBClusterParameterGroup', { Description: 'desc', Parameters: { key: 'value', }, - })); + }); }); @@ -39,12 +39,12 @@ describe('ClusterParameterGroup', () => { }); // THEN - expect(stack).to(haveResource('AWS::Neptune::DBParameterGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::Neptune::DBParameterGroup', { Description: 'desc', Parameters: { key: 'value', }, - })); + }); }); }); diff --git a/packages/@aws-cdk/aws-neptune/test/subnet-group.test.ts b/packages/@aws-cdk/aws-neptune/test/subnet-group.test.ts index 675b2cf89a920..5e736d212a12e 100644 --- a/packages/@aws-cdk/aws-neptune/test/subnet-group.test.ts +++ b/packages/@aws-cdk/aws-neptune/test/subnet-group.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as ec2 from '@aws-cdk/aws-ec2'; import { Stack } from '@aws-cdk/core'; import { SubnetGroup } from '../lib'; @@ -17,7 +17,7 @@ test('creates a subnet group from minimal properties', () => { vpc, }); - expect(stack).toHaveResource('AWS::Neptune::DBSubnetGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::Neptune::DBSubnetGroup', { DBSubnetGroupDescription: 'MyGroup', SubnetIds: [ { Ref: 'VPCPrivateSubnet1Subnet8BCA10E0' }, @@ -34,7 +34,7 @@ test('creates a subnet group from all properties', () => { vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE }, }); - expect(stack).toHaveResource('AWS::Neptune::DBSubnetGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::Neptune::DBSubnetGroup', { DBSubnetGroupDescription: 'My Shared Group', DBSubnetGroupName: 'SharedGroup', SubnetIds: [ @@ -51,7 +51,7 @@ describe('subnet selection', () => { vpc, }); - expect(stack).toHaveResource('AWS::Neptune::DBSubnetGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::Neptune::DBSubnetGroup', { DBSubnetGroupDescription: 'MyGroup', SubnetIds: [ { Ref: 'VPCPrivateSubnet1Subnet8BCA10E0' }, @@ -67,7 +67,7 @@ describe('subnet selection', () => { vpcSubnets: { subnetType: ec2.SubnetType.PUBLIC }, }); - expect(stack).toHaveResource('AWS::Neptune::DBSubnetGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::Neptune::DBSubnetGroup', { DBSubnetGroupDescription: 'MyGroup', SubnetIds: [ { Ref: 'VPCPublicSubnet1SubnetB4246D30' }, From c06b161636425801de67f2f95166359ff0dd5dd6 Mon Sep 17 00:00:00 2001 From: Madeline Kusters <80541297+madeline-k@users.noreply.github.com> Date: Tue, 24 Aug 2021 09:48:31 -0700 Subject: [PATCH 90/99] chore(cli): Add node 10 deprecation warning (#16205) Testing: Downgraded to node 10.24.1 on my laptop, and saw the warning banner "Node v10.24.1 has reached end-of-life and will no longer be supported in new releases after 2021-09-01..." when running cli commands on a CDK app linked to this repo. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/aws-cdk/bin/cdk.ts | 1 + packages/aws-cdk/package.json | 1 + yarn.lock | 16 ++++++++++++++++ 3 files changed, 18 insertions(+) diff --git a/packages/aws-cdk/bin/cdk.ts b/packages/aws-cdk/bin/cdk.ts index 1103b6354bf67..29f217360355f 100644 --- a/packages/aws-cdk/bin/cdk.ts +++ b/packages/aws-cdk/bin/cdk.ts @@ -1,6 +1,7 @@ #!/usr/bin/env node import 'source-map-support/register'; import * as cxapi from '@aws-cdk/cx-api'; +import '@jsii/check-node/run'; import * as colors from 'colors/safe'; import * as yargs from 'yargs'; diff --git a/packages/aws-cdk/package.json b/packages/aws-cdk/package.json index 4485c964c105e..497afb2e2ec92 100644 --- a/packages/aws-cdk/package.json +++ b/packages/aws-cdk/package.json @@ -73,6 +73,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.33.0", "archiver": "^5.3.0", "aws-sdk": "^2.848.0", "camelcase": "^6.2.0", diff --git a/yarn.lock b/yarn.lock index 431e3492b2be6..dc35a18bf0134 100644 --- a/yarn.lock +++ b/yarn.lock @@ -557,6 +557,14 @@ "@types/yargs" "^15.0.0" chalk "^4.0.0" +"@jsii/check-node@1.33.0": + version "1.33.0" + resolved "https://registry.yarnpkg.com/@jsii/check-node/-/check-node-1.33.0.tgz#55d75cbef1c84e2012c67ab8d6de63f773be4a9b" + integrity sha512-Bajxa09dhkuQ8bM1ve6qtm2oFNhW9/+GaKRh4Deewsk/G86ovLXI/rRS6TfCsSw4E0TGPFWzWy0tBeJuEDo7sw== + dependencies: + chalk "^4.1.2" + semver "^7.3.5" + "@jsii/spec@^1.31.0": version "1.31.0" resolved "https://registry.yarnpkg.com/@jsii/spec/-/spec-1.31.0.tgz#9298dc163fdae0bab4006b817592235a29922871" @@ -2686,6 +2694,14 @@ chalk@^4.0.0, chalk@^4.1.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + char-regex@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" From a1a65bc9a38b06ec51dff462e52b1beb8d421a56 Mon Sep 17 00:00:00 2001 From: Julian Michel Date: Tue, 24 Aug 2021 19:37:21 +0200 Subject: [PATCH 91/99] fix(sqs): unable to import a FIFO queue when the queue ARN is a token (#15976) The fifo property of a SQS queue is determined based on the queue name. The suffix `.fifo` indicates that it is a fifo queue. When the queue is imported from a token, the name is not known on synthesis time. Therefore, the name of the queue can't be used to initialize the queue as a FIFO queue. In some constructs, CDK checks during synthesis if the given queue is a FIFIO queue. Because of that, an additional option is necessary to specify a FIFO queue. A new boolean property `fifo` is introduced which can be used to specify a FIFO queue that is imported from a token. The property is optional and is only necessary when a FIFO queue should be imported from a token. Closes #12466. ---- *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-sqs/lib/queue-base.ts | 9 +++ packages/@aws-cdk/aws-sqs/lib/queue.ts | 25 ++++++- packages/@aws-cdk/aws-sqs/test/test.sqs.ts | 83 ++++++++++++++++++++- 3 files changed, 113 insertions(+), 4 deletions(-) diff --git a/packages/@aws-cdk/aws-sqs/lib/queue-base.ts b/packages/@aws-cdk/aws-sqs/lib/queue-base.ts index 162c149aec2ad..23cf09218cc58 100644 --- a/packages/@aws-cdk/aws-sqs/lib/queue-base.ts +++ b/packages/@aws-cdk/aws-sqs/lib/queue-base.ts @@ -275,4 +275,13 @@ export interface QueueAttributes { * @default - None */ readonly keyArn?: string; + + /** + * Whether this queue is an Amazon SQS FIFO queue. If false, this is a standard queue. + * + * In case of a FIFO queue which is imported from a token, this value has to be explicitly set to true. + * + * @default - if fifo is not specified, the property will be determined based on the queue name (not possible for FIFO queues imported from a token) + */ + readonly fifo?: boolean; } diff --git a/packages/@aws-cdk/aws-sqs/lib/queue.ts b/packages/@aws-cdk/aws-sqs/lib/queue.ts index 414ddaaf8a919..db2992630aa63 100644 --- a/packages/@aws-cdk/aws-sqs/lib/queue.ts +++ b/packages/@aws-cdk/aws-sqs/lib/queue.ts @@ -1,5 +1,5 @@ import * as kms from '@aws-cdk/aws-kms'; -import { Duration, RemovalPolicy, Stack, Token } from '@aws-cdk/core'; +import { Duration, RemovalPolicy, Stack, Token, ArnFormat } from '@aws-cdk/core'; import { Construct } from 'constructs'; import { IQueue, QueueAttributes, QueueBase } from './queue-base'; import { CfnQueue } from './sqs.generated'; @@ -257,7 +257,7 @@ export class Queue extends QueueBase { */ public static fromQueueAttributes(scope: Construct, id: string, attrs: QueueAttributes): IQueue { const stack = Stack.of(scope); - const parsedArn = stack.parseArn(attrs.queueArn); + const parsedArn = stack.splitArn(attrs.queueArn, ArnFormat.NO_RESOURCE_NAME); const queueName = attrs.queueName || parsedArn.resource; const queueUrl = attrs.queueUrl || `https://sqs.${parsedArn.region}.${stack.urlSuffix}/${parsedArn.account}/${queueName}`; @@ -268,9 +268,28 @@ export class Queue extends QueueBase { public readonly encryptionMasterKey = attrs.keyArn ? kms.Key.fromKeyArn(this, 'Key', attrs.keyArn) : undefined; - public readonly fifo = queueName.endsWith('.fifo') ? true : false; + public readonly fifo: boolean = this.determineFifo();; protected readonly autoCreatePolicy = false; + + /** + * Determine fifo flag based on queueName and fifo attribute + */ + private determineFifo(): boolean { + if (Token.isUnresolved(this.queueArn)) { + return attrs.fifo || false; + } else { + if (typeof attrs.fifo !== 'undefined') { + if (attrs.fifo && !queueName.endsWith('.fifo')) { + throw new Error("FIFO queue names must end in '.fifo'"); + } + if (!attrs.fifo && queueName.endsWith('.fifo')) { + throw new Error("Non-FIFO queue name may not end in '.fifo'"); + } + } + return queueName.endsWith('.fifo') ? true : false; + } + } } return new Import(scope, id); diff --git a/packages/@aws-cdk/aws-sqs/test/test.sqs.ts b/packages/@aws-cdk/aws-sqs/test/test.sqs.ts index da8637ba5d4f5..ae334e5fcd4d3 100644 --- a/packages/@aws-cdk/aws-sqs/test/test.sqs.ts +++ b/packages/@aws-cdk/aws-sqs/test/test.sqs.ts @@ -1,7 +1,7 @@ import { expect, haveResource, ResourcePart } from '@aws-cdk/assert-internal'; import * as iam from '@aws-cdk/aws-iam'; import * as kms from '@aws-cdk/aws-kms'; -import { CfnParameter, Duration, Stack, App } from '@aws-cdk/core'; +import { CfnParameter, Duration, Stack, App, Token } from '@aws-cdk/core'; import { Test } from 'nodeunit'; import * as sqs from '../lib'; @@ -191,6 +191,87 @@ export = { test.done(); }, + 'import queueArn from token, fifo and standard queues can be defined'(test: Test) { + // GIVEN + const stack = new Stack(); + + // WHEN + const stdQueue1 = sqs.Queue.fromQueueAttributes(stack, 'StdQueue1', { + queueArn: Token.asString({ Ref: 'ARN' }), + }); + const stdQueue2 = sqs.Queue.fromQueueAttributes(stack, 'StdQueue2', { + queueArn: Token.asString({ Ref: 'ARN' }), + fifo: false, + }); + const fifoQueue = sqs.Queue.fromQueueAttributes(stack, 'FifoQueue', { + queueArn: Token.asString({ Ref: 'ARN' }), + fifo: true, + }); + + // THEN + test.deepEqual(stdQueue1.fifo, false); + test.deepEqual(stdQueue2.fifo, false); + test.deepEqual(fifoQueue.fifo, true); + test.done(); + }, + + 'import queueArn from token, check attributes'(test: Test) { + // GIVEN + const stack = new Stack(); + + // WHEN + const stdQueue1 = sqs.Queue.fromQueueArn(stack, 'StdQueue', Token.asString({ Ref: 'ARN' })); + + // THEN + test.deepEqual(stack.resolve(stdQueue1.queueArn), { + Ref: 'ARN', + }); + test.deepEqual(stack.resolve(stdQueue1.queueName), { + 'Fn::Select': [5, { 'Fn::Split': [':', { Ref: 'ARN' }] }], + }); + test.deepEqual(stack.resolve(stdQueue1.queueUrl), { + 'Fn::Join': + ['', + ['https://sqs.', + { 'Fn::Select': [3, { 'Fn::Split': [':', { Ref: 'ARN' }] }] }, + '.', + { Ref: 'AWS::URLSuffix' }, + '/', + { 'Fn::Select': [4, { 'Fn::Split': [':', { Ref: 'ARN' }] }] }, + '/', + { 'Fn::Select': [5, { 'Fn::Split': [':', { Ref: 'ARN' }] }] }]], + }); + test.deepEqual(stdQueue1.fifo, false); + test.done(); + }, + + 'fails if fifo flag is set for non fifo queue name'(test: Test) { + // GIVEN + const app = new App(); + const stack = new Stack(app, 'my-stack'); + + // THEN + test.throws(() => sqs.Queue.fromQueueAttributes(stack, 'ImportedStdQueue', { + queueArn: 'arn:aws:sqs:us-west-2:123456789012:queue1', + fifo: true, + }), /FIFO queue names must end in '.fifo'/); + test.done(); + }, + + + 'fails if fifo flag is false for fifo queue name'(test: Test) { + // GIVEN + const app = new App(); + const stack = new Stack(app, 'my-stack'); + + // THEN + test.throws(() => sqs.Queue.fromQueueAttributes(stack, 'ImportedFifoQueue', { + queueArn: 'arn:aws:sqs:us-west-2:123456789012:queue1.fifo', + fifo: false, + }), /Non-FIFO queue name may not end in '.fifo'/); + test.done(); + }, + 'importing works correctly for cross region queue'(test: Test) { // GIVEN const stack = new Stack(undefined, 'Stack', { env: { region: 'us-east-1' } }); From eb54cd416a48708898e30986058491e21125b2f7 Mon Sep 17 00:00:00 2001 From: Julian Michel Date: Tue, 24 Aug 2021 20:17:15 +0200 Subject: [PATCH 92/99] fix(ssm): StringParameter.fromStringParameterAttributes cannot accept version as a numeric Token (#16048) In `StringParameter.fromStringParameterAttributes()` and `StringParameter.fromSecureStringParameterAttributes()` the version of a parameter can be specified using data type number. If a token value (e.g. CloudFormation Parameter) was used here, the token was not resolved correctly. The conversion of property `version` was corrected by using method `Tokenization.stringifyNumber()`. Fixes #11913. ---- *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-ssm/lib/parameter.ts | 5 +- ...g.parameter-store-string.lit.expected.json | 18 +++++ .../test/integ.parameter-store-string.lit.ts | 20 ++++++ .../@aws-cdk/aws-ssm/test/test.parameter.ts | 68 +++++++++++++++++++ 4 files changed, 109 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/aws-ssm/lib/parameter.ts b/packages/@aws-cdk/aws-ssm/lib/parameter.ts index 416454c1ef8cc..df30c8197cf91 100644 --- a/packages/@aws-cdk/aws-ssm/lib/parameter.ts +++ b/packages/@aws-cdk/aws-ssm/lib/parameter.ts @@ -4,6 +4,7 @@ import * as cxschema from '@aws-cdk/cloud-assembly-schema'; import { CfnDynamicReference, CfnDynamicReferenceService, CfnParameter, Construct as CompatConstruct, ContextProvider, Fn, IResource, Resource, Stack, Token, + Tokenization, } from '@aws-cdk/core'; import { Construct } from 'constructs'; import * as ssm from './ssm.generated'; @@ -324,7 +325,7 @@ export class StringParameter extends ParameterBase implements IStringParameter { const type = attrs.type || ParameterType.STRING; const stringValue = attrs.version - ? new CfnDynamicReference(CfnDynamicReferenceService.SSM, `${attrs.parameterName}:${attrs.version}`).toString() + ? new CfnDynamicReference(CfnDynamicReferenceService.SSM, `${attrs.parameterName}:${Tokenization.stringifyNumber(attrs.version)}`).toString() : new CfnParameter(scope as CompatConstruct, `${id}.Parameter`, { type: `AWS::SSM::Parameter::Value<${type}>`, default: attrs.parameterName }).valueAsString; class Import extends ParameterBase { @@ -341,7 +342,7 @@ export class StringParameter extends ParameterBase implements IStringParameter { * Imports a secure string parameter from the SSM parameter store. */ public static fromSecureStringParameterAttributes(scope: Construct, id: string, attrs: SecureStringParameterAttributes): IStringParameter { - const stringValue = new CfnDynamicReference(CfnDynamicReferenceService.SSM_SECURE, `${attrs.parameterName}:${attrs.version}`).toString(); + const stringValue = new CfnDynamicReference(CfnDynamicReferenceService.SSM_SECURE, `${attrs.parameterName}:${Tokenization.stringifyNumber(attrs.version)}`).toString(); class Import extends ParameterBase { public readonly parameterName = attrs.parameterName; diff --git a/packages/@aws-cdk/aws-ssm/test/integ.parameter-store-string.lit.expected.json b/packages/@aws-cdk/aws-ssm/test/integ.parameter-store-string.lit.expected.json index 1d3d7baba28e0..074f6694ac41b 100644 --- a/packages/@aws-cdk/aws-ssm/test/integ.parameter-store-string.lit.expected.json +++ b/packages/@aws-cdk/aws-ssm/test/integ.parameter-store-string.lit.expected.json @@ -13,6 +13,10 @@ }, { "Parameters": { + "MyParameterVersion": { + "Type": "Number", + "Default": 1 + }, "MyValueParameter": { "Type": "AWS::SSM::Parameter::Value", "Default": "/My/Public/Parameter" @@ -28,6 +32,20 @@ "Value": { "Ref": "MyValueParameter" } + }, + "TheValueVersionFromToken": { + "Value": { + "Fn::Join": [ + "", + [ + "{{resolve:ssm:/My/Public/Parameter:", + { + "Ref": "MyParameterVersion" + }, + "}}" + ] + ] + } } } } diff --git a/packages/@aws-cdk/aws-ssm/test/integ.parameter-store-string.lit.ts b/packages/@aws-cdk/aws-ssm/test/integ.parameter-store-string.lit.ts index 7c4604fa79c9e..09e0f6f17f01f 100644 --- a/packages/@aws-cdk/aws-ssm/test/integ.parameter-store-string.lit.ts +++ b/packages/@aws-cdk/aws-ssm/test/integ.parameter-store-string.lit.ts @@ -17,6 +17,13 @@ class UsingStack extends cdk.Stack { constructor(scope: cdk.App, id: string) { super(scope, id); + // Parameter that contains version number, will be used to pass + // version value from token. + const parameterVersion = new cdk.CfnParameter(this, 'MyParameterVersion', { + type: 'Number', + default: 1, + }).valueAsNumber; + /// !show // Retrieve the latest value of the non-secret parameter // with name "/My/String/Parameter". @@ -24,6 +31,11 @@ class UsingStack extends cdk.Stack { parameterName: '/My/Public/Parameter', // 'version' can be specified but is optional. }).stringValue; + const stringValueVersionFromToken = ssm.StringParameter.fromStringParameterAttributes(this, 'MyValueVersionFromToken', { + parameterName: '/My/Public/Parameter', + // parameter version from token + version: parameterVersion, + }).stringValue; // Retrieve a specific version of the secret (SecureString) parameter. // 'version' is always required. @@ -31,13 +43,21 @@ class UsingStack extends cdk.Stack { parameterName: '/My/Secret/Parameter', version: 5, }); + const secretValueVersionFromToken = ssm.StringParameter.fromSecureStringParameterAttributes(this, 'MySecureValueVersionFromToken', { + parameterName: '/My/Secret/Parameter', + // parameter version from token + version: parameterVersion, + }); + /// !hide new cdk.CfnResource(this, 'Dummy', { type: 'AWS::SNS::Topic' }); new cdk.CfnOutput(this, 'TheValue', { value: stringValue }); + new cdk.CfnOutput(this, 'TheValueVersionFromToken', { value: stringValueVersionFromToken }); // Cannot be provisioned so cannot be actually used Array.isArray(secretValue); + Array.isArray(secretValueVersionFromToken); } } diff --git a/packages/@aws-cdk/aws-ssm/test/test.parameter.ts b/packages/@aws-cdk/aws-ssm/test/test.parameter.ts index 8ce26dd03a0c5..83b68eda4a508 100644 --- a/packages/@aws-cdk/aws-ssm/test/test.parameter.ts +++ b/packages/@aws-cdk/aws-ssm/test/test.parameter.ts @@ -344,6 +344,40 @@ export = { test.done(); }, + 'StringParameter.fromStringParameterAttributes with version from token'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + + // WHEN + const param = ssm.StringParameter.fromStringParameterAttributes(stack, 'MyParamName', { + parameterName: 'MyParamName', + version: cdk.Token.asNumber({ Ref: 'version' }), + }); + + // THEN + test.deepEqual(stack.resolve(param.parameterArn), { + 'Fn::Join': ['', [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':ssm:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':parameter/MyParamName', + ]], + }); + test.deepEqual(stack.resolve(param.parameterName), 'MyParamName'); + test.deepEqual(stack.resolve(param.parameterType), 'String'); + test.deepEqual(stack.resolve(param.stringValue), { + 'Fn::Join': ['', [ + '{{resolve:ssm:MyParamName:', + { Ref: 'version' }, + '}}', + ]], + }); + test.done(); + }, + 'StringParameter.fromSecureStringParameterAttributes'(test: Test) { // GIVEN const stack = new cdk.Stack(); @@ -372,6 +406,40 @@ export = { test.done(); }, + 'StringParameter.fromSecureStringParameterAttributes with version from token'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + + // WHEN + const param = ssm.StringParameter.fromSecureStringParameterAttributes(stack, 'MyParamName', { + parameterName: 'MyParamName', + version: cdk.Token.asNumber({ Ref: 'version' }), + }); + + // THEN + test.deepEqual(stack.resolve(param.parameterArn), { + 'Fn::Join': ['', [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':ssm:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':parameter/MyParamName', + ]], + }); + test.deepEqual(stack.resolve(param.parameterName), 'MyParamName'); + test.deepEqual(stack.resolve(param.parameterType), 'SecureString'); + test.deepEqual(stack.resolve(param.stringValue), { + 'Fn::Join': ['', [ + '{{resolve:ssm-secure:MyParamName:', + { Ref: 'version' }, + '}}', + ]], + }); + test.done(); + }, + 'StringParameter.fromSecureStringParameterAttributes with encryption key creates the correct policy for grantRead'(test: Test) { // GIVEN const stack = new cdk.Stack(); From 0f7beb29be18d809052f4d46e415a0394c9299ab Mon Sep 17 00:00:00 2001 From: Colin Ihrig Date: Tue, 24 Aug 2021 14:59:05 -0400 Subject: [PATCH 93/99] feat(docdb): cluster - deletion protection (#15216) This commit adds support for `deletionProtection` on docdb `DatabaseCluster`s. Fixes: https://github.com/aws/aws-cdk/issues/15170 ---- *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-docdb/README.md | 18 ++++++++++++++++ packages/@aws-cdk/aws-docdb/lib/cluster.ts | 11 ++++++++++ .../@aws-cdk/aws-docdb/test/cluster.test.ts | 21 +++++++++++++++++++ 3 files changed, 50 insertions(+) diff --git a/packages/@aws-cdk/aws-docdb/README.md b/packages/@aws-cdk/aws-docdb/README.md index fb1c4eeb270ee..6f7ed89e28e11 100644 --- a/packages/@aws-cdk/aws-docdb/README.md +++ b/packages/@aws-cdk/aws-docdb/README.md @@ -60,6 +60,24 @@ const securityGroup = new ec2.SecurityGroup(stack, 'SecurityGroup', { cluster.addSecurityGroups(securityGroup); ``` +## Deletion protection + +Deletion protection can be enabled on an Amazon DocumentDB cluster to prevent accidental deletion of the cluster: + +```ts +const cluster = new DatabaseCluster(this, 'Database', { + masterUser: { + username: 'myuser' + }, + instanceType: ec2.InstanceType.of(ec2.InstanceClass.R5, ec2.InstanceSize.LARGE), + vpcSubnets: { + subnetType: ec2.SubnetType.PUBLIC, + }, + vpc, + deletionProtection: true // Enable deletion protection. +}); +``` + ## Rotating credentials When the master password is generated and stored in AWS Secrets Manager, it can be rotated automatically: diff --git a/packages/@aws-cdk/aws-docdb/lib/cluster.ts b/packages/@aws-cdk/aws-docdb/lib/cluster.ts index f90e976db8798..56b5a724dd439 100644 --- a/packages/@aws-cdk/aws-docdb/lib/cluster.ts +++ b/packages/@aws-cdk/aws-docdb/lib/cluster.ts @@ -136,6 +136,16 @@ export interface DatabaseClusterProps { * @default - Retain cluster. */ readonly removalPolicy?: RemovalPolicy + + /** + * Specifies whether this cluster can be deleted. If deletionProtection is + * enabled, the cluster cannot be deleted unless it is modified and + * deletionProtection is disabled. deletionProtection protects clusters from + * being accidentally deleted. + * + * @default - false + */ + readonly deletionProtection?: boolean; } /** @@ -361,6 +371,7 @@ export class DatabaseCluster extends DatabaseClusterBase { port: props.port, vpcSecurityGroupIds: [this.securityGroupId], dbClusterParameterGroupName: props.parameterGroup?.parameterGroupName, + deletionProtection: props.deletionProtection, // Admin masterUsername: secret ? secret.secretValueFromJson('username').toString() : props.masterUser.username, masterUserPassword: secret diff --git a/packages/@aws-cdk/aws-docdb/test/cluster.test.ts b/packages/@aws-cdk/aws-docdb/test/cluster.test.ts index beb564ed738e5..cb1f8653509df 100644 --- a/packages/@aws-cdk/aws-docdb/test/cluster.test.ts +++ b/packages/@aws-cdk/aws-docdb/test/cluster.test.ts @@ -167,6 +167,27 @@ describe('DatabaseCluster', () => { })); }); + test('can configure cluster deletion protection', () => { + // GIVEN + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + + // WHEN + new DatabaseCluster(stack, 'Database', { + masterUser: { + username: 'admin', + }, + instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.SMALL), + vpc, + deletionProtection: true, + }); + + // THEN + expectCDK(stack).to(haveResource('AWS::DocDB::DBCluster', { + DeletionProtection: true, + })); + }); + test('cluster with parameter group', () => { // GIVEN const stack = testStack(); From cdee1af03c34a1c08988e672bae6edc2538a8877 Mon Sep 17 00:00:00 2001 From: Madeline Kusters <80541297+madeline-k@users.noreply.github.com> Date: Tue, 24 Aug 2021 13:12:06 -0700 Subject: [PATCH 94/99] fix(resourcegroups): ResourceGroup not using TagType.STANDARD, causes deploy failure (#16211) This PR removes a patch to the cloudformation spec that is no longer necessary. Without the patch, the correct tag type of STANDARD is generated for CfnResourceGroup. PR where the patch was introduced: https://github.com/aws/aws-cdk/pull/6995 Closes #12986 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../530_ResourceGroups_Tags_patch.json | 24 ------------------- 1 file changed, 24 deletions(-) delete mode 100644 packages/@aws-cdk/cfnspec/spec-source/530_ResourceGroups_Tags_patch.json diff --git a/packages/@aws-cdk/cfnspec/spec-source/530_ResourceGroups_Tags_patch.json b/packages/@aws-cdk/cfnspec/spec-source/530_ResourceGroups_Tags_patch.json deleted file mode 100644 index da2d3c603ddbd..0000000000000 --- a/packages/@aws-cdk/cfnspec/spec-source/530_ResourceGroups_Tags_patch.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "ResourceTypes": { - "AWS::ResourceGroups::Group": { - "patch": { - "description": "Sets AWS::ResourceGroups::Group#Tags to Json", - "operations": [ - { - "op": "remove", - "path": "/Properties/Tags/ItemType" - }, - { - "op": "remove", - "path": "/Properties/Tags/Type" - }, - { - "op": "add", - "path": "/Properties/Tags/PrimitiveType", - "value": "Json" - } - ] - } - } - } -} From 27a37ac26172301178a87fda93370b1554f5d513 Mon Sep 17 00:00:00 2001 From: Eli Polonsky Date: Tue, 24 Aug 2021 16:17:26 -0700 Subject: [PATCH 95/99] chore(integ): node check breaks cli integ tests (#16216) The Node runtime check performed by jsii and introduced in this [PR](https://github.com/aws/aws-cdk/pull/16205) breaks the CLI integration tests since it changes the output of the `synth` command. This PR makes it so the test asserts on the content of the template rather than the output of the CLI. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../aws-cdk/test/integ/cli/cli.integtest.ts | 47 ++++++++++++------- packages/aws-cdk/test/integ/helpers/cdk.ts | 6 +++ 2 files changed, 36 insertions(+), 17 deletions(-) diff --git a/packages/aws-cdk/test/integ/cli/cli.integtest.ts b/packages/aws-cdk/test/integ/cli/cli.integtest.ts index 957d04bf09fd9..873e3a1787ee5 100644 --- a/packages/aws-cdk/test/integ/cli/cli.integtest.ts +++ b/packages/aws-cdk/test/integ/cli/cli.integtest.ts @@ -39,23 +39,36 @@ integTest('Termination protection', withDefaultFixture(async (fixture) => { })); integTest('cdk synth', withDefaultFixture(async (fixture) => { - await expect(fixture.cdk(['synth', fixture.fullStackName('test-1')], { verbose: false })).resolves.toEqual( - `Resources: - topic69831491: - Type: AWS::SNS::Topic - Metadata: - aws:cdk:path: ${fixture.stackNamePrefix}-test-1/topic/Resource`); - - await expect(fixture.cdk(['synth', fixture.fullStackName('test-2')], { verbose: false })).resolves.toEqual( - `Resources: - topic152D84A37: - Type: AWS::SNS::Topic - Metadata: - aws:cdk:path: ${fixture.stackNamePrefix}-test-2/topic1/Resource - topic2A4FB547F: - Type: AWS::SNS::Topic - Metadata: - aws:cdk:path: ${fixture.stackNamePrefix}-test-2/topic2/Resource`); + await fixture.cdk(['synth', fixture.fullStackName('test-1')]); + expect(fixture.template('test-1')).toEqual({ + Resources: { + topic69831491: { + Type: 'AWS::SNS::Topic', + Metadata: { + 'aws:cdk:path': `${fixture.stackNamePrefix}-test-1/topic/Resource`, + }, + }, + }, + }); + + await fixture.cdk(['synth', fixture.fullStackName('test-2')], { verbose: false }); + expect(fixture.template('test-2')).toEqual({ + Resources: { + topic152D84A37: { + Type: 'AWS::SNS::Topic', + Metadata: { + 'aws:cdk:path': `${fixture.stackNamePrefix}-test-2/topic1/Resource`, + }, + }, + topic2A4FB547F: { + Type: 'AWS::SNS::Topic', + Metadata: { + 'aws:cdk:path': `${fixture.stackNamePrefix}-test-2/topic2/Resource`, + }, + }, + }, + }); + })); integTest('ssm parameter provider error', withDefaultFixture(async (fixture) => { diff --git a/packages/aws-cdk/test/integ/helpers/cdk.ts b/packages/aws-cdk/test/integ/helpers/cdk.ts index 8bf256140d13b..4a09f43063600 100644 --- a/packages/aws-cdk/test/integ/helpers/cdk.ts +++ b/packages/aws-cdk/test/integ/helpers/cdk.ts @@ -382,6 +382,12 @@ export class TestFixture { }); } + public template(stackName: string): any { + const fullStackName = this.fullStackName(stackName); + const templatePath = path.join(this.integTestDir, 'cdk.out', `${fullStackName}.template.json`); + return JSON.parse(fs.readFileSync(templatePath, { encoding: 'utf-8' }).toString()); + } + public get bootstrapStackName() { return this.fullStackName('bootstrap-stack'); } From e547ba0d1491af0abe703132fa06fe786ffd7070 Mon Sep 17 00:00:00 2001 From: kaizen3031593 <36202692+kaizen3031593@users.noreply.github.com> Date: Tue, 24 Aug 2021 20:16:53 -0400 Subject: [PATCH 96/99] feat(cloudwatch): add support for cross-account alarms (#16007) Allows `accountId` to be specified in a CloudWatch Alarm. This opens up the ability to create cross-account alarms, which was just [announced](https://aws.amazon.com/about-aws/whats-new/2021/08/announcing-amazon-cloudwatch-cross-account-alarms/). closes #15959. ---- *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 | 4 ++ packages/@aws-cdk/aws-cloudwatch/lib/alarm.ts | 11 +-- .../test/cross-environment.test.ts | 67 ++++++++++++++++++- 3 files changed, 76 insertions(+), 6 deletions(-) diff --git a/packages/@aws-cdk/aws-cloudwatch/README.md b/packages/@aws-cdk/aws-cloudwatch/README.md index ff1f1997489f4..bdcf58e61024f 100644 --- a/packages/@aws-cdk/aws-cloudwatch/README.md +++ b/packages/@aws-cdk/aws-cloudwatch/README.md @@ -28,6 +28,8 @@ represents the amount of errors reported by that Lambda function: const errors = fn.metricErrors(); ``` +`Metric` objects can be account and region aware. You can specify `account` and `region` as properties of the metric, or use the `metric.attachTo(Construct)` method. `metric.attachTo()` will automatically copy the `region` and `account` fields of the `Construct`, which can come from anywhere in the Construct tree. + You can also instantiate `Metric` objects to reference any [published metric](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/aws-services-cloudwatch-metrics.html) that's not exposed using a convenience method on the CDK construct. @@ -160,6 +162,8 @@ The most important properties to set while creating an Alarms are: - `evaluationPeriods`: how many consecutive periods the metric has to be breaching the the threshold for the alarm to trigger. +To create a cross-account alarm, make sure you have enabled [cross-account functionality](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Cross-Account-Cross-Region.html) in CloudWatch. Then, set the `account` property in the `Metric` object either manually or via the `metric.attachTo()` method. + ### Alarm Actions To add actions to an alarm, use the integration classes from the diff --git a/packages/@aws-cdk/aws-cloudwatch/lib/alarm.ts b/packages/@aws-cdk/aws-cloudwatch/lib/alarm.ts index 6b102d567125f..41928d0af7193 100644 --- a/packages/@aws-cdk/aws-cloudwatch/lib/alarm.ts +++ b/packages/@aws-cdk/aws-cloudwatch/lib/alarm.ts @@ -257,7 +257,10 @@ export class Alarm extends AlarmBase { return dispatchMetric(metric, { withStat(stat, conf) { self.validateMetricStat(stat, metric); - if (conf.renderingProperties?.label == undefined) { + const canRenderAsLegacyMetric = conf.renderingProperties?.label == undefined && + (stat.account == undefined || Stack.of(self).account == stat.account); + // Do this to disturb existing templates as little as possible + if (canRenderAsLegacyMetric) { return dropUndefined({ dimensions: stat.dimensions, namespace: stat.namespace, @@ -283,6 +286,7 @@ export class Alarm extends AlarmBase { unit: stat.unitFilter, }, id: 'm1', + accountId: stat.account, label: conf.renderingProperties?.label, returnData: true, } as CfnAlarm.MetricDataQueryProperty, @@ -344,7 +348,7 @@ export class Alarm extends AlarmBase { } /** - * Validate that if a region and account are in the given stat config, they match the Alarm + * Validate that if a region is in the given stat config, they match the Alarm */ private validateMetricStat(stat: MetricStatConfig, metric: IMetric) { const stack = Stack.of(this); @@ -352,9 +356,6 @@ export class Alarm extends AlarmBase { if (definitelyDifferent(stat.region, stack.region)) { throw new Error(`Cannot create an Alarm in region '${stack.region}' based on metric '${metric}' in '${stat.region}'`); } - if (definitelyDifferent(stat.account, stack.account)) { - throw new Error(`Cannot create an Alarm in account '${stack.account}' based on metric '${metric}' in '${stat.account}'`); - } } } diff --git a/packages/@aws-cdk/aws-cloudwatch/test/cross-environment.test.ts b/packages/@aws-cdk/aws-cloudwatch/test/cross-environment.test.ts index 7c7ed7d04bf6f..f17391591a8c5 100644 --- a/packages/@aws-cdk/aws-cloudwatch/test/cross-environment.test.ts +++ b/packages/@aws-cdk/aws-cloudwatch/test/cross-environment.test.ts @@ -6,11 +6,12 @@ const a = new Metric({ namespace: 'Test', metricName: 'ACount' }); let stack1: Stack; let stack2: Stack; +let stack3: Stack; describe('cross environment', () => { beforeEach(() => { stack1 = new Stack(undefined, undefined, { env: { region: 'pluto', account: '1234' } }); stack2 = new Stack(undefined, undefined, { env: { region: 'mars', account: '5678' } }); - + stack3 = new Stack(undefined, undefined, { env: { region: 'pluto', account: '0000' } }); }); describe('in graphs', () => { @@ -112,6 +113,70 @@ describe('cross environment', () => { }); + + test('metric attached to stack3 will render in stack1', () => { + //Cross-account metrics are supported in Alarms + + // GIVEN + new Alarm(stack1, 'Alarm', { + threshold: 1, + evaluationPeriods: 1, + metric: a.attachTo(stack3), + }); + + // THEN + Template.fromStack(stack1).hasResourceProperties('AWS::CloudWatch::Alarm', { + Metrics: [ + { + AccountId: '0000', + Id: 'm1', + MetricStat: { + Metric: { + MetricName: 'ACount', + Namespace: 'Test', + }, + Period: 300, + Stat: 'Average', + }, + ReturnData: true, + }, + ], + }); + }); + + test('metric can render in a different account', () => { + // GIVEN + const b = new Metric({ + namespace: 'Test', + metricName: 'ACount', + account: '0000', + }); + + new Alarm(stack1, 'Alarm', { + threshold: 1, + evaluationPeriods: 1, + metric: b, + }); + + // THEN + Template.fromStack(stack1).hasResourceProperties('AWS::CloudWatch::Alarm', { + Metrics: [ + { + AccountId: '0000', + Id: 'm1', + MetricStat: { + Metric: { + MetricName: 'ACount', + Namespace: 'Test', + }, + Period: 300, + Stat: 'Average', + }, + ReturnData: true, + }, + ], + }); + }); }); }); From e678f104df4fb0377c6ad5c8abc4132433363871 Mon Sep 17 00:00:00 2001 From: Ben Chaimberg Date: Wed, 25 Aug 2021 05:51:34 -0700 Subject: [PATCH 97/99] revert: temporarily transfer @skinny85 module ownership (#16206) This reverts commit 77dfa2f8546d03671b3304d2910a9c7e387ff6a8. --- .github/workflows/issue-label-assign.yml | 116 +++++++++++------------ 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/.github/workflows/issue-label-assign.yml b/.github/workflows/issue-label-assign.yml index 618de4693571f..64e3daf97887b 100644 --- a/.github/workflows/issue-label-assign.yml +++ b/.github/workflows/issue-label-assign.yml @@ -21,23 +21,23 @@ jobs: [ {"keywords":["(cli)","(command line)"],"labels":["package/tools"],"assignees":["rix0rrr"]}, {"keywords":["(@aws-cdk/alexa-ask)","(alexa-ask)","(alexa ask)"],"labels":["@aws-cdk/alexa-ask"],"assignees":["madeline-k"]}, - {"keywords":["(@aws-cdk/app-delivery)","(app-delivery)","(app delivery)"],"labels":["@aws-cdk/app-delivery"],"assignees":["madeline-k"]}, + {"keywords":["(@aws-cdk/app-delivery)","(app-delivery)","(app delivery)"],"labels":["@aws-cdk/app-delivery"],"assignees":["skinny85"]}, {"keywords":["(@aws-cdk/assert)","(assert)"],"labels":["@aws-cdk/assert"],"assignees":["nija-at"]}, {"keywords":["(@aws-cdk/assets)","(assets)"],"labels":["@aws-cdk/assets"],"assignees":["eladb"]}, - {"keywords":["(@aws-cdk/aws-accessanalyzer)","(aws-accessanalyzer)","(accessanalyzer)","(access analyzer)"],"labels":["@aws-cdk/aws-accessanalyzer"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-acmpca)","(aws-acmpca)","(acmpca)"],"labels":["@aws-cdk/aws-acmpca"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-accessanalyzer)","(aws-accessanalyzer)","(accessanalyzer)","(access analyzer)"],"labels":["@aws-cdk/aws-accessanalyzer"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-acmpca)","(aws-acmpca)","(acmpca)"],"labels":["@aws-cdk/aws-acmpca"],"assignees":["skinny85"]}, {"keywords":["(@aws-cdk/aws-amazonmq)","(aws-amazonmq)","(amazonmq)","(amazon mq)","(amazon-mq)"],"labels":["@aws-cdk/aws-amazonmq"],"assignees":["otaviomacedo"]}, - {"keywords":["(@aws-cdk/aws-amplify)","(aws-amplify)","(amplify)"],"labels":["@aws-cdk/aws-amplify"],"assignees":["madeline-k"]}, + {"keywords":["(@aws-cdk/aws-amplify)","(aws-amplify)","(amplify)"],"labels":["@aws-cdk/aws-amplify"],"assignees":["skinny85"]}, {"keywords":["(@aws-cdk/aws-apigateway)","(aws-apigateway)","(apigateway)","(api gateway)","(api-gateway)"],"labels":["@aws-cdk/aws-apigateway"],"assignees":["nija-at"]}, {"keywords":["(@aws-cdk/aws-apigatewayv2)","(aws-apigatewayv2)","(apigatewayv2)","(apigateway v2)","(api-gateway-v2)"],"labels":["@aws-cdk/aws-apigatewayv2"],"assignees":["nija-at"]}, {"keywords":["(@aws-cdk/aws-apigatewayv2-authorizers)","(aws-apigatewayv2-authorizers)","(apigatewayv2-authorizers)"],"labels":["@aws-cdk/aws-apigatewayv2-authorizers"],"assignees":["nija-at"]}, {"keywords":["(@aws-cdk/aws-apigatewayv2-integrations)","(aws-apigatewayv2-integrations)","(apigatewayv2-integrations)","(apigateway v2 integrations)","(api-gateway-v2-integrations)"],"labels":["@aws-cdk/aws-apigatewayv2-integrations"],"assignees":["nija-at"]}, {"keywords":["(@aws-cdk/aws-appconfig)","(aws-appconfig)","(appconfig)","(app config)","(app-config)"],"labels":["@aws-cdk/aws-appconfig"],"assignees":["rix0rrr"]}, - {"keywords":["(@aws-cdk/aws-appflow)","(aws-appflow)","(appflow)","(app flow)","(app-flow)"],"labels":["@aws-cdk/aws-appflow"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-appintegrations)","(aws-appintegrations)","(appintegrations)"],"labels":["@aws-cdk/aws-appintegrations"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-appflow)","(aws-appflow)","(appflow)","(app flow)","(app-flow)"],"labels":["@aws-cdk/aws-appflow"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-appintegrations)","(aws-appintegrations)","(appintegrations)"],"labels":["@aws-cdk/aws-appintegrations"],"assignees":["skinny85"]}, {"keywords":["(@aws-cdk/aws-applicationautoscaling)","(aws-applicationautoscaling)","(applicationautoscaling)","(application autoscaling)","(application-autoscaling)"],"labels":["@aws-cdk/aws-applicationautoscaling"],"assignees":["comcalvi"]}, {"keywords":["(@aws-cdk/aws-applicationinsights)","(aws-applicationinsights)","(applicationinsights)","(application insights)","(application-insights)"],"labels":["@aws-cdk/aws-applicationinsights"],"assignees":["njlynch"]}, - {"keywords":["(@aws-cdk/aws-appmesh)","(aws-appmesh)","(appmesh)","(app mesh)","(app-mesh)"],"labels":["@aws-cdk/aws-appmesh"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-appmesh)","(aws-appmesh)","(appmesh)","(app mesh)","(app-mesh)"],"labels":["@aws-cdk/aws-appmesh"],"assignees":["skinny85"]}, {"keywords":["(@aws-cdk/aws-appstream)","(aws-appstream)","(appstream)","(app stream)","(app-stream)"],"labels":["@aws-cdk/aws-appstream"],"assignees":["madeline-k"]}, {"keywords":["(@aws-cdk/aws-appsync)","(aws-appsync)","(appsync)","(app sync)","(app-sync)"],"labels":["@aws-cdk/aws-appsync"],"assignees":["otaviomacedo"]}, {"keywords":["(@aws-cdk/aws-athena)","(aws-athena)","(athena)"],"labels":["@aws-cdk/aws-athena"],"assignees":["BenChaimberg"]}, @@ -54,7 +54,7 @@ jobs: {"keywords":["(@aws-cdk/aws-ce)","(aws-ce)","(ce)"],"labels":["@aws-cdk/aws-ce"],"assignees":["njlynch"]}, {"keywords":["(@aws-cdk/aws-certificatemanager)","(aws-certificatemanager)","(certificatemanager)","(certificate manager)","(certificate-manager)","(acm)"],"labels":["@aws-cdk/aws-certificatemanager"],"assignees":["njlynch"]}, {"keywords":["(@aws-cdk/aws-chatbot)","(aws-chatbot)","(chatbot)"],"labels":["@aws-cdk/aws-chatbot"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-cloud9)","(aws-cloud9)","(cloud9)","(cloud 9)"],"labels":["@aws-cdk/aws-cloud9"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-cloud9)","(aws-cloud9)","(cloud9)","(cloud 9)"],"labels":["@aws-cdk/aws-cloud9"],"assignees":["skinny85"]}, {"keywords":["(@aws-cdk/aws-cloudformation)","(aws-cloudformation)","(cloudformation)","(cloud formation)"],"labels":["@aws-cdk/aws-cloudformation"],"assignees":["rix0rrr"]}, {"keywords":["(@aws-cdk/aws-cloudfront)","(aws-cloudfront)","(cloudfront)","(cloud front)"],"labels":["@aws-cdk/aws-cloudfront"],"assignees":["njlynch"]}, {"keywords":["(@aws-cdk/aws-cloudfront-origins)","(aws-cloudfront-origins)","(cloudfront-origins)","(cloudfront origins)"],"labels":["@aws-cdk/aws-cloudfront-origins"],"assignees":["njlynch"]}, @@ -62,31 +62,31 @@ jobs: {"keywords":["(@aws-cdk/aws-cloudwatch)","(aws-cloudwatch)","(cloudwatch)","(cloud watch)"],"labels":["@aws-cdk/aws-cloudwatch"],"assignees":["madeline-k"]}, {"keywords":["(@aws-cdk/aws-cloudwatch-actions)","(aws-cloudwatch-actions)","(cloudwatch-actions)","(cloudwatch actions)"],"labels":["@aws-cdk/aws-cloudwatch-actions"],"assignees":["madeline-k"]}, {"keywords":["(@aws-cdk/aws-codeartifact)","(aws-codeartifact)","(codeartifact)","(code artifact)","(code-artifact)"],"labels":["@aws-cdk/aws-codeartifact"],"assignees":["njlynch"]}, - {"keywords":["(@aws-cdk/aws-codebuild)","(aws-codebuild)","(codebuild)","(code build)","(code-build)"],"labels":["@aws-cdk/aws-codebuild"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-codecommit)","(aws-codecommit)","(codecommit)","(code commit)", "(code-commit)"],"labels":["@aws-cdk/aws-codecommit"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-codedeploy)","(aws-codedeploy)","(codedeploy)","(code deploy)","(code-deploy)"],"labels":["@aws-cdk/aws-codedeploy"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-codeguruprofiler)","(aws-codeguruprofiler)","(codeguruprofiler)","(codeguru profiler)","(codeguru-profiler)"],"labels":["@aws-cdk/aws-codeguruprofiler"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-codegurureviewer)","(aws-codegurureviewer)","(codegurureviewer)","(codeguru reviewer)","(codeguru-reviewer)"],"labels":["@aws-cdk/aws-codegurureviewer"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-codepipeline)","(aws-codepipeline)","(codepipeline)","(code pipeline)","(code-pipeline)"],"labels":["@aws-cdk/aws-codepipeline"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-codepipeline-actions)","(aws-codepipeline-actions)","(codepipeline-actions)","(codepipeline actions)"],"labels":["@aws-cdk/aws-codepipeline-actions"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-codestar)","(aws-codestar)","(codestar)"],"labels":["@aws-cdk/aws-codestar"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-codestarconnections)","(aws-codestarconnections)","(codestarconnections)","(codestar connections)","(codestar-connections)"],"labels":["@aws-cdk/aws-codestarconnections"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-codestarnotifications)","(aws-codestarnotifications)","(codestarnotifications)","(codestar notifications)","(codestar-notifications)"],"labels":["@aws-cdk/aws-codestarnotifications"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-codebuild)","(aws-codebuild)","(codebuild)","(code build)","(code-build)"],"labels":["@aws-cdk/aws-codebuild"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-codecommit)","(aws-codecommit)","(codecommit)","(code commit)", "(code-commit)"],"labels":["@aws-cdk/aws-codecommit"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-codedeploy)","(aws-codedeploy)","(codedeploy)","(code deploy)","(code-deploy)"],"labels":["@aws-cdk/aws-codedeploy"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-codeguruprofiler)","(aws-codeguruprofiler)","(codeguruprofiler)","(codeguru profiler)","(codeguru-profiler)"],"labels":["@aws-cdk/aws-codeguruprofiler"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-codegurureviewer)","(aws-codegurureviewer)","(codegurureviewer)","(codeguru reviewer)","(codeguru-reviewer)"],"labels":["@aws-cdk/aws-codegurureviewer"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-codepipeline)","(aws-codepipeline)","(codepipeline)","(code pipeline)","(code-pipeline)"],"labels":["@aws-cdk/aws-codepipeline"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-codepipeline-actions)","(aws-codepipeline-actions)","(codepipeline-actions)","(codepipeline actions)"],"labels":["@aws-cdk/aws-codepipeline-actions"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-codestar)","(aws-codestar)","(codestar)"],"labels":["@aws-cdk/aws-codestar"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-codestarconnections)","(aws-codestarconnections)","(codestarconnections)","(codestar connections)","(codestar-connections)"],"labels":["@aws-cdk/aws-codestarconnections"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-codestarnotifications)","(aws-codestarnotifications)","(codestarnotifications)","(codestar notifications)","(codestar-notifications)"],"labels":["@aws-cdk/aws-codestarnotifications"],"assignees":["skinny85"]}, {"keywords":["(@aws-cdk/aws-cognito)","(aws-cognito)","(cognito)"],"labels":["@aws-cdk/aws-cognito"],"assignees":["nija-at"]}, {"keywords":["(@aws-cdk/aws-config)","(aws-config)","(config)"],"labels":["@aws-cdk/aws-config"],"assignees":["rix0rrr"]}, {"keywords":["(@aws-cdk/aws-customerprofiles)","(aws-customerprofiles)","(customerprofiles)"],"labels":["@aws-cdk/aws-customerprofiles"],"assignees":["otaviomacedo"]}, {"keywords":["(@aws-cdk/aws-databrew)","(aws-databrew)","(databrew)"],"labels":["@aws-cdk/aws-databrew"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/aws-datapipeline)","(aws-datapipeline)","(datapipeline)","(data pipeline)","(data-pipeline)"],"labels":["@aws-cdk/aws-datapipeline"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/aws-datasync)","(aws-datasync)","(datasync)"],"labels":["@aws-cdk/aws-datasync"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-dax)","(aws-dax)","(dax)"],"labels":["@aws-cdk/aws-dax"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-detective)","(aws-detective)","(detective)"],"labels":["@aws-cdk/aws-detective"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-dax)","(aws-dax)","(dax)"],"labels":["@aws-cdk/aws-dax"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-detective)","(aws-detective)","(detective)"],"labels":["@aws-cdk/aws-detective"],"assignees":["skinny85"]}, {"keywords":["(@aws-cdk/aws-devopsguru)","(aws-devopsguru)","(devopsguru)"],"labels":["@aws-cdk/aws-devopsguru"],"assignees":["nija-at"]}, {"keywords":["(@aws-cdk/aws-directoryservice)","(aws-directoryservice)","(directoryservice)","(directory service)","(directory-service)"],"labels":["@aws-cdk/aws-directoryservice"],"assignees":["rix0rrr"]}, {"keywords":["(@aws-cdk/aws-dlm)","(aws-dlm)","(dlm)"],"labels":["@aws-cdk/aws-dlm"],"assignees":["njlynch"]}, {"keywords":["(@aws-cdk/aws-dms)","(aws-dms)","(dms)"],"labels":["@aws-cdk/aws-dms"],"assignees":["njlynch"]}, - {"keywords":["(@aws-cdk/aws-docdb)","(aws-docdb)","(docdb)","(doc db)","(doc-db)"],"labels":["@aws-cdk/aws-docdb"],"assignees":["madeline-k"]}, - {"keywords":["(@aws-cdk/aws-dynamodb)","(aws-dynamodb)","(dynamodb)","(dynamo db)","(dynamo-db)"],"labels":["@aws-cdk/aws-dynamodb"],"assignees":["madeline-k"]}, - {"keywords":["(@aws-cdk/aws-dynamodb-global)","(aws-dynamodb-global)","(dynamodb-global)","(dynamodb global)"],"labels":["@aws-cdk/aws-dynamodb-global"],"assignees":["madeline-k"]}, + {"keywords":["(@aws-cdk/aws-docdb)","(aws-docdb)","(docdb)","(doc db)","(doc-db)"],"labels":["@aws-cdk/aws-docdb"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-dynamodb)","(aws-dynamodb)","(dynamodb)","(dynamo db)","(dynamo-db)"],"labels":["@aws-cdk/aws-dynamodb"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-dynamodb-global)","(aws-dynamodb-global)","(dynamodb-global)","(dynamodb global)"],"labels":["@aws-cdk/aws-dynamodb-global"],"assignees":["skinny85"]}, {"keywords":["(@aws-cdk/aws-ec2)","(aws-ec2)","(ec2)","(vpc)"],"labels":["@aws-cdk/aws-ec2"],"assignees":["njlynch"]}, {"keywords":["(@aws-cdk/aws-ecr)","(aws-ecr)","(ecr)"],"labels":["@aws-cdk/aws-ecr"],"assignees":["madeline-k"]}, {"keywords":["(@aws-cdk/aws-ecr-assets)","(aws-ecr-assets)","(ecr-assets)","(ecr assets)","(ecrassets)"],"labels":["@aws-cdk/aws-ecr-assets"],"assignees":["eladb"]}, @@ -96,7 +96,7 @@ jobs: {"keywords":["(@aws-cdk/aws-eks)","(aws-eks)","(eks)"],"labels":["@aws-cdk/aws-eks"],"assignees":["otaviomacedo"]}, {"keywords":["(@aws-cdk/aws-eks-legacy)","(aws-eks-legacy)","(eks-legacy)"],"labels":["@aws-cdk/aws-eks-legacy"],"assignees":["otaviomacedo"]}, {"keywords":["(@aws-cdk/aws-elasticache)","(aws-elasticache)","(elasticache)","(elastic cache)","(elastic-cache)"],"labels":["@aws-cdk/aws-elasticache"],"assignees":["otaviomacedo"]}, - {"keywords":["(@aws-cdk/aws-elasticbeanstalk)","(aws-elasticbeanstalk)","(elasticbeanstalk)","(elastic beanstalk)","(elastic-beanstalk)"],"labels":["@aws-cdk/aws-elasticbeanstalk"],"assignees":["madeline-k"]}, + {"keywords":["(@aws-cdk/aws-elasticbeanstalk)","(aws-elasticbeanstalk)","(elasticbeanstalk)","(elastic beanstalk)","(elastic-beanstalk)"],"labels":["@aws-cdk/aws-elasticbeanstalk"],"assignees":["skinny85"]}, {"keywords":["(@aws-cdk/aws-elasticloadbalancing)","(aws-elasticloadbalancing)","(elasticloadbalancing)","(elastic loadbalancing)","(elastic-loadbalancing)","(elb)"],"labels":["@aws-cdk/aws-elasticloadbalancing"],"assignees":["njlynch"]}, {"keywords":["(@aws-cdk/aws-elasticloadbalancingv2)","(aws-elasticloadbalancingv2)","(elasticloadbalancingv2)","(elastic-loadbalancing-v2)","(elbv2)","(elb v2)"],"labels":["@aws-cdk/aws-elasticloadbalancingv2"],"assignees":["njlynch"]}, {"keywords":["(@aws-cdk/aws-elasticloadbalancingv2-actions)","(aws-elasticloadbalancingv2-actions)","(elasticloadbalancingv2-actions)"],"labels":["@aws-cdk/aws-elasticloadbalancingv2-actions"],"assignees":["njlynch"]}, @@ -106,7 +106,7 @@ jobs: {"keywords":["(@aws-cdk/aws-emrcontainers)","(aws-emrcontainers)","(emrcontainers)"],"labels":["@aws-cdk/aws-emrcontainers"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/aws-events)","(aws-events)","(events)","(eventbridge)","(event-bridge)"],"labels":["@aws-cdk/aws-events"],"assignees":["rix0rrr"]}, {"keywords":["(@aws-cdk/aws-events-targets)","(aws-events-targets)","(events-targets)","(events targets)"],"labels":["@aws-cdk/aws-events-targets"],"assignees":["rix0rrr"]}, - {"keywords":["(@aws-cdk/aws-eventschemas)","(aws-eventschemas)","(eventschemas)","(event schemas)"],"labels":["@aws-cdk/aws-eventschemas"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-eventschemas)","(aws-eventschemas)","(eventschemas)","(event schemas)"],"labels":["@aws-cdk/aws-eventschemas"],"assignees":["skinny85"]}, {"keywords":["(@aws-cdk/aws-finspace)","(aws-finspace)","(finspace)"],"labels":["@aws-cdk/aws-finspace"],"assignees":["njlynch"]}, {"keywords":["(@aws-cdk/aws-fis)","(aws-fis)","(fis)"],"labels":["@aws-cdk/aws-fis"],"assignees":["njlynch"]}, {"keywords":["(@aws-cdk/aws-fms)","(aws-fms)","(fms)"],"labels":["@aws-cdk/aws-fms"],"assignees":["rix0rrr"]}, @@ -116,23 +116,23 @@ jobs: {"keywords":["(@aws-cdk/aws-globalaccelerator)","(aws-globalaccelerator)","(globalaccelerator)","(global accelerator)","(global-accelerator)"],"labels":["@aws-cdk/aws-globalaccelerator"],"assignees":["rix0rrr"]}, {"keywords":["(@aws-cdk/aws-globalaccelerator-endpoints)","(aws-globalaccelerator-endpoints)","(globalaccelerator-endpoints)"],"labels":["@aws-cdk/aws-globalaccelerator-endpoints"],"assignees":["rix0rrr"]}, {"keywords":["(@aws-cdk/aws-glue)","(aws-glue)","(glue)"],"labels":["@aws-cdk/aws-glue"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-greengrass)","(aws-greengrass)","(greengrass)","(green grass)","(green-grass)"],"labels":["@aws-cdk/aws-greengrass"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-greengrassv2)","(aws-greengrassv2)","(greengrassv2)"],"labels":["@aws-cdk/aws-greengrassv2"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-greengrass)","(aws-greengrass)","(greengrass)","(green grass)","(green-grass)"],"labels":["@aws-cdk/aws-greengrass"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-greengrassv2)","(aws-greengrassv2)","(greengrassv2)"],"labels":["@aws-cdk/aws-greengrassv2"],"assignees":["skinny85"]}, {"keywords":["(@aws-cdk/aws-groundstation)","(aws-groundstation)","(groundstation)"],"labels":["@aws-cdk/aws-groundstation"],"assignees":["rix0rrr"]}, {"keywords":["(@aws-cdk/aws-guardduty)","(aws-guardduty)","(guardduty)","(guard duty)","(guard-duty)"],"labels":["@aws-cdk/aws-guardduty"],"assignees":["rix0rrr"]}, {"keywords":["(@aws-cdk/aws-iam)","(aws-iam)","(iam)"],"labels":["@aws-cdk/aws-iam"],"assignees":["rix0rrr"]}, - {"keywords":["(@aws-cdk/aws-imagebuilder)","(aws-imagebuilder)","(imagebuilder)","(image builder)","(image-builder)"],"labels":["@aws-cdk/aws-imagebuilder"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-inspector)","(aws-inspector)","(inspector)"],"labels":["@aws-cdk/aws-inspector"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-iot)","(aws-iot)","(iot)"],"labels":["@aws-cdk/aws-iot"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-iot1click)","(aws-iot1click)","(iot1click)","(iot 1click)"],"labels":["@aws-cdk/aws-iot1click"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-iotanalytics)","(aws-iotanalytics)","(iotanalytics)","(iot analytics)","(iot-analytics)"],"labels":["@aws-cdk/aws-iotanalytics"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-iotevents)","(aws-iotevents)","(iotevents)","(iot events)","(iot-events)"],"labels":["@aws-cdk/aws-iotevents"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-iotfleethub)","(aws-iotfleethub)","(iotfleethub)"],"labels":["@aws-cdk/aws-iotfleethub"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-iotsitewise)","(aws-iotsitewise)","(iotsitewise)","(iot sitewise)","(iot-sitewise)","(iot-site-wise)","(iot site wise)"],"labels":["@aws-cdk/aws-iotsitewise"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-iotthingsgraph)","(aws-iotthingsgraph)","(iotthingsgraph)","(iot things graph)","(iot-things-graph)"],"labels":["@aws-cdk/aws-iotthingsgraph"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-iotwireless)","(aws-iotwireless)","(iotwireless)"],"labels":["@aws-cdk/aws-iotwireless"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-ivs)","(aws-ivs)","(Interactive Video Service)","(ivs)"],"labels":["@aws-cdk/aws-ivs"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-kendra)","(aws-kendra)","(kendra)"],"labels":["@aws-cdk/aws-kendra"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-imagebuilder)","(aws-imagebuilder)","(imagebuilder)","(image builder)","(image-builder)"],"labels":["@aws-cdk/aws-imagebuilder"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-inspector)","(aws-inspector)","(inspector)"],"labels":["@aws-cdk/aws-inspector"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-iot)","(aws-iot)","(iot)"],"labels":["@aws-cdk/aws-iot"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-iot1click)","(aws-iot1click)","(iot1click)","(iot 1click)"],"labels":["@aws-cdk/aws-iot1click"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-iotanalytics)","(aws-iotanalytics)","(iotanalytics)","(iot analytics)","(iot-analytics)"],"labels":["@aws-cdk/aws-iotanalytics"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-iotevents)","(aws-iotevents)","(iotevents)","(iot events)","(iot-events)"],"labels":["@aws-cdk/aws-iotevents"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-iotfleethub)","(aws-iotfleethub)","(iotfleethub)"],"labels":["@aws-cdk/aws-iotfleethub"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-iotsitewise)","(aws-iotsitewise)","(iotsitewise)","(iot sitewise)","(iot-sitewise)","(iot-site-wise)","(iot site wise)"],"labels":["@aws-cdk/aws-iotsitewise"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-iotthingsgraph)","(aws-iotthingsgraph)","(iotthingsgraph)","(iot things graph)","(iot-things-graph)"],"labels":["@aws-cdk/aws-iotthingsgraph"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-iotwireless)","(aws-iotwireless)","(iotwireless)"],"labels":["@aws-cdk/aws-iotwireless"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-ivs)","(aws-ivs)","(Interactive Video Service)","(ivs)"],"labels":["@aws-cdk/aws-ivs"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-kendra)","(aws-kendra)","(kendra)"],"labels":["@aws-cdk/aws-kendra"],"assignees":["skinny85"]}, {"keywords":["(@aws-cdk/aws-kinesis)","(aws-kinesis)","(kinesis)"],"labels":["@aws-cdk/aws-kinesis"],"assignees":["otaviomacedo"]}, {"keywords":["(@aws-cdk/aws-kinesisanalytics)","(aws-kinesisanalytics)","(kinesisanalytics)","(kinesis analytics)","(kinesis-analytics)"],"labels":["@aws-cdk/aws-kinesisanalytics"],"assignees":["otaviomacedo"]}, {"keywords":["(@aws-cdk/aws-kinesisanalytics-flink)","(aws-kinesisanalytics-flink)","(kinesisanalytics-flink)"],"labels":["@aws-cdk/aws-kinesisanalytics-flink"],"assignees":["otaviomacedo"]}, @@ -151,27 +151,27 @@ jobs: {"keywords":["(@aws-cdk/aws-lookoutmetrics)","(aws-lookoutmetrics)","(lookoutmetrics)"],"labels":["@aws-cdk/aws-lookoutmetrics"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/aws-lookoutvision)","(aws-lookoutvision)","(lookoutvision)"],"labels":["@aws-cdk/aws-lookoutvision"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/aws-macie)","(aws-macie)","(macie)"],"labels":["@aws-cdk/aws-macie"],"assignees":["njlynch"]}, - {"keywords":["(@aws-cdk/aws-managedblockchain)","(aws-managedblockchain)","(managedblockchain)","(managed blockchain)","(managed-blockchain)"],"labels":["@aws-cdk/aws-managedblockchain"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-mediaconnect)","(aws-mediaconnect)","(mediaconnect)"],"labels":["@aws-cdk/aws-mediaconnect"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-mediaconvert)","(aws-mediaconvert)","(mediaconvert)","(media convert)","(media-convert)"],"labels":["@aws-cdk/aws-mediaconvert"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-medialive)","(aws-medialive)","(medialive)","(media live)","(media-live)"],"labels":["@aws-cdk/aws-medialive"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-mediastore)","(aws-mediastore)","(mediastore)","(media store)","(media-store)"],"labels":["@aws-cdk/aws-mediastore"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-mediapackage)","(aws-mediapackage)","(mediapackage)","(media package)","(media-package)"],"labels":["@aws-cdk/aws-mediapackage"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-managedblockchain)","(aws-managedblockchain)","(managedblockchain)","(managed blockchain)","(managed-blockchain)"],"labels":["@aws-cdk/aws-managedblockchain"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-mediaconnect)","(aws-mediaconnect)","(mediaconnect)"],"labels":["@aws-cdk/aws-mediaconnect"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-mediaconvert)","(aws-mediaconvert)","(mediaconvert)","(media convert)","(media-convert)"],"labels":["@aws-cdk/aws-mediaconvert"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-medialive)","(aws-medialive)","(medialive)","(media live)","(media-live)"],"labels":["@aws-cdk/aws-medialive"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-mediastore)","(aws-mediastore)","(mediastore)","(media store)","(media-store)"],"labels":["@aws-cdk/aws-mediastore"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-mediapackage)","(aws-mediapackage)","(mediapackage)","(media package)","(media-package)"],"labels":["@aws-cdk/aws-mediapackage"],"assignees":["skinny85"]}, {"keywords":["(@aws-cdk/aws-msk)","(aws-msk)","(msk)"],"labels":["@aws-cdk/aws-msk"],"assignees":["otaviomacedo"]}, {"keywords":["(@aws-cdk/aws-mwaa)","(aws-mwaa)","(mwaa)"],"labels":["@aws-cdk/aws-mwaa"],"assignees":["rix0rrr"]}, {"keywords":["(@aws-cdk/aws-neptune)","(aws-neptune)","(neptune)"],"labels":["@aws-cdk/aws-neptune"],"assignees":["njlynch"]}, - {"keywords":["(@aws-cdk/aws-networkfirewall)","(aws-networkfirewall)","(networkfirewall)"],"labels":["@aws-cdk/aws-networkfirewall"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-networkmanager)","(aws-networkmanager)","(networkmanager)","(network manager)","(network-manager)"],"labels":["@aws-cdk/aws-networkmanager"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-networkfirewall)","(aws-networkfirewall)","(networkfirewall)"],"labels":["@aws-cdk/aws-networkfirewall"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-networkmanager)","(aws-networkmanager)","(networkmanager)","(network manager)","(network-manager)"],"labels":["@aws-cdk/aws-networkmanager"],"assignees":["skinny85"]}, {"keywords":["(@aws-cdk/aws-nimblestudio)","(aws-nimblestudio)","(nimblestudio)"],"labels":["@aws-cdk/aws-nimblestudio"],"assignees":["madeline-k"]}, {"keywords":["(@aws-cdk/aws-opsworks)","(aws-opsworks)","(opsworks)","(ops works)","(ops-works)"],"labels":["@aws-cdk/aws-opsworks"],"assignees":["madeline-k"]}, {"keywords":["(@aws-cdk/aws-opsworkscm)","(aws-opsworkscm)","(opsworkscm)","(opsworks cm)","(opsworks-cm)"],"labels":["@aws-cdk/aws-opsworkscm"],"assignees":["madeline-k"]}, {"keywords":["(@aws-cdk/aws-personalize)","(aws-personalize)","(personalize)"],"labels":["@aws-cdk/aws-personalize"],"assignees":["njlynch"]}, {"keywords":["(@aws-cdk/aws-pinpoint)","(aws-pinpoint)","(pinpoint)"],"labels":["@aws-cdk/aws-pinpoint"],"assignees":["otaviomacedo"]}, {"keywords":["(@aws-cdk/aws-pinpointemail)","(aws-pinpointemail)","(pinpointemail)","(pinpoint email)","(pinpoint-email)"],"labels":["@aws-cdk/aws-pinpointemail"],"assignees":["otaviomacedo"]}, - {"keywords":["(@aws-cdk/aws-qldb)","(aws-qldb)","(qldb)"],"labels":["@aws-cdk/aws-qldb"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-qldb)","(aws-qldb)","(qldb)"],"labels":["@aws-cdk/aws-qldb"],"assignees":["skinny85"]}, {"keywords":["(@aws-cdk/aws-quicksight)","(aws-quicksight)","(quicksight)"],"labels":["@aws-cdk/aws-quicksight"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/aws-ram)","(aws-ram)","(ram)"],"labels":["@aws-cdk/aws-ram"],"assignees":["madeline-k"]}, - {"keywords":["(@aws-cdk/aws-rds)","(aws-rds)","(rds)"],"labels":["@aws-cdk/aws-rds"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-rds)","(aws-rds)","(rds)"],"labels":["@aws-cdk/aws-rds"],"assignees":["skinny85"]}, {"keywords":["(@aws-cdk/aws-redshift)","(aws-redshift)","(redshift)","(red shift)","(red-shift)"],"labels":["@aws-cdk/aws-redshift"],"assignees":["njlynch"]}, {"keywords":["(@aws-cdk/aws-resourcegroups)","(aws-resourcegroups)","(resourcegroups)","(resource groups)","(resource-groups)"],"labels":["@aws-cdk/aws-resourcegroups"],"assignees":["madeline-k"]}, {"keywords":["(@aws-cdk/aws-robomaker)","(aws-robomaker)","(robomaker)","(robo maker)","(robo-maker)"],"labels":["@aws-cdk/aws-robomaker"],"assignees":["njlynch"]}, @@ -189,9 +189,9 @@ jobs: {"keywords":["(@aws-cdk/aws-sam)","(aws-sam)","(sam)"],"labels":["@aws-cdk/aws-sam"],"assignees":["njlynch"]}, {"keywords":["(@aws-cdk/aws-sdb)","(aws-sdb)","(sdb)"],"labels":["@aws-cdk/aws-sdb"],"assignees":["njlynch"]}, {"keywords":["(@aws-cdk/aws-secretsmanager)","(aws-secretsmanager)","(secretsmanager)","(secrets manager)","(secrets-manager)"],"labels":["@aws-cdk/aws-secretsmanager"],"assignees":["njlynch"]}, - {"keywords":["(@aws-cdk/aws-securityhub)","(aws-securityhub)","(securityhub)","(security hub)","(security-hub)"],"labels":["@aws-cdk/aws-securityhub"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-servicecatalog)","(aws-servicecatalog)","(servicecatalog)","(service catalog)","(service-catalog)"],"labels":["@aws-cdk/aws-servicecatalog"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-servicecatalogappregistry)","(aws-servicecatalogappregistry)","(servicecatalogappregistry)"],"labels":["@aws-cdk/aws-servicecatalogappregistry"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-securityhub)","(aws-securityhub)","(securityhub)","(security hub)","(security-hub)"],"labels":["@aws-cdk/aws-securityhub"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-servicecatalog)","(aws-servicecatalog)","(servicecatalog)","(service catalog)","(service-catalog)"],"labels":["@aws-cdk/aws-servicecatalog"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/aws-servicecatalogappregistry)","(aws-servicecatalogappregistry)","(servicecatalogappregistry)"],"labels":["@aws-cdk/aws-servicecatalogappregistry"],"assignees":["skinny85"]}, {"keywords":["(@aws-cdk/aws-servicediscovery)","(aws-servicediscovery)","(servicediscovery)","(service discovery)","(service-discovery)"],"labels":["@aws-cdk/aws-servicediscovery"],"assignees":["madeline-k"]}, {"keywords":["(@aws-cdk/aws-ses)","(aws-ses)","(ses)"],"labels":["@aws-cdk/aws-ses"],"assignees":["otaviomacedo"]}, {"keywords":["(@aws-cdk/aws-ses-actions)","(aws-ses-actions)","(ses-actions)","(ses actions)"],"labels":["@aws-cdk/aws-ses-actions"],"assignees":["otaviomacedo"]}, @@ -200,11 +200,11 @@ jobs: {"keywords":["(@aws-cdk/aws-sns-subscriptions)","(aws-sns-subscriptions)","(sns-subscriptions)","(sns subscriptions)"],"labels":["@aws-cdk/aws-sns-subscriptions"],"assignees":["njlynch"]}, {"keywords":["(@aws-cdk/aws-sqs)","(aws-sqs)","(sqs)"],"labels":["@aws-cdk/aws-sqs"],"assignees":["njlynch"]}, {"keywords":["(@aws-cdk/aws-ssm)","(aws-ssm)","(ssm)"],"labels":["@aws-cdk/aws-ssm"],"assignees":["njlynch"]}, - {"keywords":["(@aws-cdk/aws-sso)","(aws-sso)","(sso)"],"labels":["@aws-cdk/aws-sso"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-sso)","(aws-sso)","(sso)"],"labels":["@aws-cdk/aws-sso"],"assignees":["skinny85"]}, {"keywords":["(@aws-cdk/aws-stepfunctions)","(aws-stepfunctions)","(stepfunctions)","(step functions)","(step-functions)"],"labels":["@aws-cdk/aws-stepfunctions"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/aws-stepfunctions-tasks)","(aws-stepfunctions-tasks)","(stepfunctions-tasks)","(stepfunctions tasks)"],"labels":["@aws-cdk/aws-stepfunctions-tasks"],"assignees":["BenChaimberg"]}, {"keywords":["(@aws-cdk/aws-synthetics)","(aws-synthetics)","(synthetics)"],"labels":["@aws-cdk/aws-synthetics"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/aws-timestream)","(aws-timestream)","(timestream)"],"labels":["@aws-cdk/aws-timestream"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/aws-timestream)","(aws-timestream)","(timestream)"],"labels":["@aws-cdk/aws-timestream"],"assignees":["skinny85"]}, {"keywords":["(@aws-cdk/aws-transfer)","(aws-transfer)","(transfer)"],"labels":["@aws-cdk/aws-transfer"],"assignees":["otaviomacedo"]}, {"keywords":["(@aws-cdk/aws-waf)","(aws-waf)","(waf)"],"labels":["@aws-cdk/aws-waf"],"assignees":["njlynch"]}, {"keywords":["(@aws-cdk/aws-wafregional)","(aws-wafregional)","(wafregional)","(waf regional)","(waf-regional)"],"labels":["@aws-cdk/aws-wafregional"],"assignees":["njlynch"]}, @@ -213,16 +213,16 @@ jobs: {"keywords":["(@aws-cdk/aws-xray)","(aws-xray)","(xray)"],"labels":["@aws-cdk/aws-xray"],"assignees":["nija-at"]}, {"keywords":["(@aws-cdk/cfnspec)","(cfnspec)","(cfn spec)","(cfn-spec)"],"labels":["@aws-cdk/cfnspec"],"assignees":["rix0rrr"]}, {"keywords":["(@aws-cdk/cloud-assembly-schema)","(cloud-assembly-schema)","(cloud assembly schema)"],"labels":["@aws-cdk/cloud-assembly-schema"],"assignees":["rix0rrr"]}, - {"keywords":["(@aws-cdk/cloudformation-diff)","(cloudformation-diff)","(cloudformation diff)","(cfn diff)"],"labels":["@aws-cdk/cloudformation-diff"],"assignees":["BenChaimberg"]}, - {"keywords":["(@aws-cdk/cloudformation-include)","(cloudformation-include)","(cloudformation include)","(cfn include)","(cfn-include)"],"labels":["@aws-cdk/cloudformation-include"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/cloudformation-diff)","(cloudformation-diff)","(cloudformation diff)","(cfn diff)"],"labels":["@aws-cdk/cloudformation-diff"],"assignees":["skinny85"]}, + {"keywords":["(@aws-cdk/cloudformation-include)","(cloudformation-include)","(cloudformation include)","(cfn include)","(cfn-include)"],"labels":["@aws-cdk/cloudformation-include"],"assignees":["skinny85"]}, {"keywords":["(@aws-cdk/core)","(core)"],"labels":["@aws-cdk/core"],"assignees":["rix0rrr"]}, {"keywords":["(@aws-cdk/custom-resources)","(custom-resources)","(custom resources)"],"labels":["@aws-cdk/custom-resources"],"assignees":["rix0rrr"]}, {"keywords":["(@aws-cdk/cx-api)","(cx-api)","(cx api)"],"labels":["@aws-cdk/cx-api"],"assignees":["rix0rrr"]}, {"keywords":["(@aws-cdk/aws-lambda-layer-awscli)","(aws-lambda-layer-awscli)","(lambda-layer-awscli)"],"labels":["@aws-cdk/aws-lambda-layer-awscli"],"assignees":["rix0rrr"]}, {"keywords":["(@aws-cdk/aws-lambda-layer-kubectl)","(aws-lambda-layer-kubectl)","(lambda-layer-kubectl)"],"labels":["@aws-cdk/aws-lambda-layer-kubectl"],"assignees":["eladb"]}, {"keywords":["(@aws-cdk/pipelines)","(pipelines)","(cdk pipelines)","(cdk-pipelines)"],"labels":["@aws-cdk/pipelines"],"assignees":["rix0rrr"]}, - {"keywords":["(@aws-cdk/region-info)","(region-info)","(region info)"],"labels":["@aws-cdk/region-info"],"assignees":["BenChaimberg"]}, + {"keywords":["(@aws-cdk/region-info)","(region-info)","(region info)"],"labels":["@aws-cdk/region-info"],"assignees":["skinny85"]}, {"keywords":["(aws-cdk-lib)","(cdk-v2)", "(v2)", "(ubergen)"],"labels":["aws-cdk-lib"],"assignees":["nija-at"]}, {"keywords":["(monocdk)","(monocdk-experiment)"],"labels":["monocdk"],"assignees":["nija-at"]}, - {"keywords":["(@aws-cdk/yaml-cfn)","(aws-yaml-cfn)","(yaml-cfn)"],"labels":["@aws-cdk/aws-yaml-cfn"],"assignees":["BenChaimberg"]} + {"keywords":["(@aws-cdk/yaml-cfn)","(aws-yaml-cfn)","(yaml-cfn)"],"labels":["@aws-cdk/aws-yaml-cfn"],"assignees":["skinny85"]} ] From b1d69d7b06cd2a2ae8f578e217bdf7fef50a0163 Mon Sep 17 00:00:00 2001 From: Otavio Macedo Date: Wed, 25 Aug 2021 17:53:28 +0100 Subject: [PATCH 98/99] fix(s3): bucket is not emptied before update when the name changes (#16203) Changing the bucket name leads CloudFormation to try to delete the bucket and create a new one with the new name. If the bucket is not empty, the deployment will fail. With this change, the custom resource will clear the old bucket when it detects that there has been a name change. NB: this custom resource is created only when `autoDeleteObjects: true` is passed to the bucket. Fixes #14011. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../test/integ.s3-bucket.lit.expected.json | 18 +-- .../lib/auto-delete-objects-handler/index.ts | 24 +++- .../test/auto-delete-objects-handler.test.ts | 103 +++++++++++++++++- ...g.bucket-auto-delete-objects.expected.json | 18 +-- 4 files changed, 139 insertions(+), 24 deletions(-) diff --git a/packages/@aws-cdk/aws-kinesisfirehose-destinations/test/integ.s3-bucket.lit.expected.json b/packages/@aws-cdk/aws-kinesisfirehose-destinations/test/integ.s3-bucket.lit.expected.json index 2a85e28a6984d..ba6e2aecacda8 100644 --- a/packages/@aws-cdk/aws-kinesisfirehose-destinations/test/integ.s3-bucket.lit.expected.json +++ b/packages/@aws-cdk/aws-kinesisfirehose-destinations/test/integ.s3-bucket.lit.expected.json @@ -102,7 +102,7 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParameters1a8becf42c48697a059094af1e94aa6bc6df0512d30433db8c22618ca02dfca1S3BucketF01ADF6B" + "Ref": "AssetParametersfe5df38824187483182e1459db47adfae2a515aa4caedd437fc4033a0c5b3de9S3BucketD715D8B0" }, "S3Key": { "Fn::Join": [ @@ -115,7 +115,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters1a8becf42c48697a059094af1e94aa6bc6df0512d30433db8c22618ca02dfca1S3VersionKey6FC34F51" + "Ref": "AssetParametersfe5df38824187483182e1459db47adfae2a515aa4caedd437fc4033a0c5b3de9S3VersionKey6E76822C" } ] } @@ -128,7 +128,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters1a8becf42c48697a059094af1e94aa6bc6df0512d30433db8c22618ca02dfca1S3VersionKey6FC34F51" + "Ref": "AssetParametersfe5df38824187483182e1459db47adfae2a515aa4caedd437fc4033a0c5b3de9S3VersionKey6E76822C" } ] } @@ -751,17 +751,17 @@ } }, "Parameters": { - "AssetParameters1a8becf42c48697a059094af1e94aa6bc6df0512d30433db8c22618ca02dfca1S3BucketF01ADF6B": { + "AssetParametersfe5df38824187483182e1459db47adfae2a515aa4caedd437fc4033a0c5b3de9S3BucketD715D8B0": { "Type": "String", - "Description": "S3 bucket for asset \"1a8becf42c48697a059094af1e94aa6bc6df0512d30433db8c22618ca02dfca1\"" + "Description": "S3 bucket for asset \"fe5df38824187483182e1459db47adfae2a515aa4caedd437fc4033a0c5b3de9\"" }, - "AssetParameters1a8becf42c48697a059094af1e94aa6bc6df0512d30433db8c22618ca02dfca1S3VersionKey6FC34F51": { + "AssetParametersfe5df38824187483182e1459db47adfae2a515aa4caedd437fc4033a0c5b3de9S3VersionKey6E76822C": { "Type": "String", - "Description": "S3 key for asset version \"1a8becf42c48697a059094af1e94aa6bc6df0512d30433db8c22618ca02dfca1\"" + "Description": "S3 key for asset version \"fe5df38824187483182e1459db47adfae2a515aa4caedd437fc4033a0c5b3de9\"" }, - "AssetParameters1a8becf42c48697a059094af1e94aa6bc6df0512d30433db8c22618ca02dfca1ArtifactHash9ECACDFD": { + "AssetParametersfe5df38824187483182e1459db47adfae2a515aa4caedd437fc4033a0c5b3de9ArtifactHash9AE3702B": { "Type": "String", - "Description": "Artifact hash for asset \"1a8becf42c48697a059094af1e94aa6bc6df0512d30433db8c22618ca02dfca1\"" + "Description": "Artifact hash for asset \"fe5df38824187483182e1459db47adfae2a515aa4caedd437fc4033a0c5b3de9\"" }, "AssetParameters5ee078f2a1957fe672d6cfd84faf49e07b8460758b5cd2669b3df1212a14cd19S3BucketFEDDFB43": { "Type": "String", diff --git a/packages/@aws-cdk/aws-s3/lib/auto-delete-objects-handler/index.ts b/packages/@aws-cdk/aws-s3/lib/auto-delete-objects-handler/index.ts index 5dd144b446e8e..f431aacf3fca2 100644 --- a/packages/@aws-cdk/aws-s3/lib/auto-delete-objects-handler/index.ts +++ b/packages/@aws-cdk/aws-s3/lib/auto-delete-objects-handler/index.ts @@ -6,10 +6,25 @@ const s3 = new S3(); export async function handler(event: AWSLambda.CloudFormationCustomResourceEvent) { switch (event.RequestType) { case 'Create': - case 'Update': return; + case 'Update': + return onUpdate(event); case 'Delete': - return onDelete(event); + return onDelete(event.ResourceProperties?.BucketName); + } +} + +async function onUpdate(event: AWSLambda.CloudFormationCustomResourceEvent) { + const updateEvent = event as AWSLambda.CloudFormationCustomResourceUpdateEvent; + const oldBucketName = updateEvent.OldResourceProperties?.BucketName; + const newBucketName = updateEvent.ResourceProperties?.BucketName; + const bucketNameHasChanged = newBucketName != null && oldBucketName != null && newBucketName !== oldBucketName; + + /* If the name of the bucket has changed, CloudFormation will try to delete the bucket + and create a new one with the new name. So we have to delete the contents of the + bucket so that this operation does not fail. */ + if (bucketNameHasChanged) { + return onDelete(oldBucketName); } } @@ -23,7 +38,7 @@ async function emptyBucket(bucketName: string) { const contents = [...listedObjects.Versions ?? [], ...listedObjects.DeleteMarkers ?? []]; if (contents.length === 0) { return; - }; + } const records = contents.map((record: any) => ({ Key: record.Key, VersionId: record.VersionId })); await s3.deleteObjects({ Bucket: bucketName, Delete: { Objects: records } }).promise(); @@ -33,8 +48,7 @@ async function emptyBucket(bucketName: string) { } } -async function onDelete(deleteEvent: AWSLambda.CloudFormationCustomResourceDeleteEvent) { - const bucketName = deleteEvent.ResourceProperties?.BucketName; +async function onDelete(bucketName?: string) { if (!bucketName) { throw new Error('No BucketName was provided.'); } diff --git a/packages/@aws-cdk/aws-s3/test/auto-delete-objects-handler.test.ts b/packages/@aws-cdk/aws-s3/test/auto-delete-objects-handler.test.ts index e5a7072441974..b09b9e5e4f5b3 100644 --- a/packages/@aws-cdk/aws-s3/test/auto-delete-objects-handler.test.ts +++ b/packages/@aws-cdk/aws-s3/test/auto-delete-objects-handler.test.ts @@ -37,7 +37,51 @@ test('does nothing on create event', async () => { expect(mockS3Client.deleteObjects).toHaveBeenCalledTimes(0); }); -test('does nothing on update event', async () => { +test('does nothing on update event when everything remains the same', async () => { + // GIVEN + const event: Partial = { + RequestType: 'Update', + ResourceProperties: { + ServiceToken: 'Foo', + BucketName: 'MyBucket', + }, + OldResourceProperties: { + ServiceToken: 'Foo', + BucketName: 'MyBucket', + }, + }; + + // WHEN + await invokeHandler(event); + + // THEN + expect(mockS3Client.listObjectVersions).toHaveBeenCalledTimes(0); + expect(mockS3Client.deleteObjects).toHaveBeenCalledTimes(0); +}); + +test('does nothing on update event when the bucket name remains the same but the service token changes', async () => { + // GIVEN + const event: Partial = { + RequestType: 'Update', + ResourceProperties: { + ServiceToken: 'Foo', + BucketName: 'MyBucket', + }, + OldResourceProperties: { + ServiceToken: 'Bar', + BucketName: 'MyBucket', + }, + }; + + // WHEN + await invokeHandler(event); + + // THEN + expect(mockS3Client.listObjectVersions).toHaveBeenCalledTimes(0); + expect(mockS3Client.deleteObjects).toHaveBeenCalledTimes(0); +}); + +test('does nothing on update event when the old resource properties are absent', async () => { // GIVEN const event: Partial = { RequestType: 'Update', @@ -55,6 +99,63 @@ test('does nothing on update event', async () => { expect(mockS3Client.deleteObjects).toHaveBeenCalledTimes(0); }); +test('does nothing on update event when the new resource properties are absent', async () => { + // GIVEN + const event: Partial = { + RequestType: 'Update', + OldResourceProperties: { + ServiceToken: 'Foo', + BucketName: 'MyBucket', + }, + }; + + // WHEN + await invokeHandler(event); + + // THEN + expect(mockS3Client.listObjectVersions).toHaveBeenCalledTimes(0); + expect(mockS3Client.deleteObjects).toHaveBeenCalledTimes(0); +}); + +test('deletes all objects when the name changes on update event', async () => { + // GIVEN + mockS3Client.promise.mockResolvedValue({ // listObjectVersions() call + Versions: [ + { Key: 'Key1', VersionId: 'VersionId1' }, + { Key: 'Key2', VersionId: 'VersionId2' }, + ], + }); + + const event: Partial = { + RequestType: 'Update', + OldResourceProperties: { + ServiceToken: 'Foo', + BucketName: 'MyBucket', + }, + ResourceProperties: { + ServiceToken: 'Foo', + BucketName: 'MyBucket-renamed', + }, + }; + + // WHEN + await invokeHandler(event); + + // THEN + expect(mockS3Client.listObjectVersions).toHaveBeenCalledTimes(1); + expect(mockS3Client.listObjectVersions).toHaveBeenCalledWith({ Bucket: 'MyBucket' }); + expect(mockS3Client.deleteObjects).toHaveBeenCalledTimes(1); + expect(mockS3Client.deleteObjects).toHaveBeenCalledWith({ + Bucket: 'MyBucket', + Delete: { + Objects: [ + { Key: 'Key1', VersionId: 'VersionId1' }, + { Key: 'Key2', VersionId: 'VersionId2' }, + ], + }, + }); +}); + test('deletes no objects on delete event when bucket has no objects', async () => { // GIVEN mockS3Client.promise.mockResolvedValue({ Versions: [] }); // listObjectVersions() call diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.expected.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.expected.json index 107132c1cd2dd..6623d9d3e7a8c 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.expected.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.expected.json @@ -102,7 +102,7 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParameters1a8becf42c48697a059094af1e94aa6bc6df0512d30433db8c22618ca02dfca1S3BucketF01ADF6B" + "Ref": "AssetParametersfe5df38824187483182e1459db47adfae2a515aa4caedd437fc4033a0c5b3de9S3BucketD715D8B0" }, "S3Key": { "Fn::Join": [ @@ -115,7 +115,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters1a8becf42c48697a059094af1e94aa6bc6df0512d30433db8c22618ca02dfca1S3VersionKey6FC34F51" + "Ref": "AssetParametersfe5df38824187483182e1459db47adfae2a515aa4caedd437fc4033a0c5b3de9S3VersionKey6E76822C" } ] } @@ -128,7 +128,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters1a8becf42c48697a059094af1e94aa6bc6df0512d30433db8c22618ca02dfca1S3VersionKey6FC34F51" + "Ref": "AssetParametersfe5df38824187483182e1459db47adfae2a515aa4caedd437fc4033a0c5b3de9S3VersionKey6E76822C" } ] } @@ -289,17 +289,17 @@ } }, "Parameters": { - "AssetParameters1a8becf42c48697a059094af1e94aa6bc6df0512d30433db8c22618ca02dfca1S3BucketF01ADF6B": { + "AssetParametersfe5df38824187483182e1459db47adfae2a515aa4caedd437fc4033a0c5b3de9S3BucketD715D8B0": { "Type": "String", - "Description": "S3 bucket for asset \"1a8becf42c48697a059094af1e94aa6bc6df0512d30433db8c22618ca02dfca1\"" + "Description": "S3 bucket for asset \"fe5df38824187483182e1459db47adfae2a515aa4caedd437fc4033a0c5b3de9\"" }, - "AssetParameters1a8becf42c48697a059094af1e94aa6bc6df0512d30433db8c22618ca02dfca1S3VersionKey6FC34F51": { + "AssetParametersfe5df38824187483182e1459db47adfae2a515aa4caedd437fc4033a0c5b3de9S3VersionKey6E76822C": { "Type": "String", - "Description": "S3 key for asset version \"1a8becf42c48697a059094af1e94aa6bc6df0512d30433db8c22618ca02dfca1\"" + "Description": "S3 key for asset version \"fe5df38824187483182e1459db47adfae2a515aa4caedd437fc4033a0c5b3de9\"" }, - "AssetParameters1a8becf42c48697a059094af1e94aa6bc6df0512d30433db8c22618ca02dfca1ArtifactHash9ECACDFD": { + "AssetParametersfe5df38824187483182e1459db47adfae2a515aa4caedd437fc4033a0c5b3de9ArtifactHash9AE3702B": { "Type": "String", - "Description": "Artifact hash for asset \"1a8becf42c48697a059094af1e94aa6bc6df0512d30433db8c22618ca02dfca1\"" + "Description": "Artifact hash for asset \"fe5df38824187483182e1459db47adfae2a515aa4caedd437fc4033a0c5b3de9\"" }, "AssetParametersf7ee44e9b6217d201200d9abd42c6493b0b11e86be8a7f36163c3ea049c54653S3BucketDB5FAF47": { "Type": "String", From 5812340bfaebfef2bc41d5e7fbd0d45af92e0e49 Mon Sep 17 00:00:00 2001 From: Eli Polonsky Date: Wed, 25 Aug 2021 11:05:24 -0700 Subject: [PATCH 99/99] chore(integ): fix regression suite failures (#16226) Follow up to https://github.com/aws/aws-cdk/pull/16216 We need to apply a patch for the regression suite to pass because its running the older tests which still make the wrong assertion. See `NOTES.md` for more details. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../cli-regression-patches/v1.119.0/NOTES.md | 5 + .../v1.119.0/cli.integtest.js | 659 ++++++++++++++++++ 2 files changed, 664 insertions(+) create mode 100644 packages/aws-cdk/test/integ/cli-regression-patches/v1.119.0/NOTES.md create mode 100644 packages/aws-cdk/test/integ/cli-regression-patches/v1.119.0/cli.integtest.js diff --git a/packages/aws-cdk/test/integ/cli-regression-patches/v1.119.0/NOTES.md b/packages/aws-cdk/test/integ/cli-regression-patches/v1.119.0/NOTES.md new file mode 100644 index 0000000000000..5ca96b632f75a --- /dev/null +++ b/packages/aws-cdk/test/integ/cli-regression-patches/v1.119.0/NOTES.md @@ -0,0 +1,5 @@ +This [PR](https://github.com/aws/aws-cdk/pull/16205) added a node version check to our CLI courtesy of [`@jsii/check-node/run`](https://github.com/aws/jsii/tree/main/packages/%40jsii/check-node). + +This check now causes the CLI to print a deprecation warning that changes the output of the `synth` command. We don't consider this a breaking change since we have no guarantess for CLI output, but it did break some our integ tests (namely `cdk synth`) that used to rely on a specific output. + +This patch brings the [fix](https://github.com/aws/aws-cdk/pull/16216) into the regression suite. \ No newline at end of file diff --git a/packages/aws-cdk/test/integ/cli-regression-patches/v1.119.0/cli.integtest.js b/packages/aws-cdk/test/integ/cli-regression-patches/v1.119.0/cli.integtest.js new file mode 100644 index 0000000000000..b8009dcaab00e --- /dev/null +++ b/packages/aws-cdk/test/integ/cli-regression-patches/v1.119.0/cli.integtest.js @@ -0,0 +1,659 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const fs_1 = require("fs"); +const os = require("os"); +const path = require("path"); +const aws_1 = require("../helpers/aws"); +const cdk_1 = require("../helpers/cdk"); +const test_helpers_1 = require("../helpers/test-helpers"); +jest.setTimeout(600 * 1000); +test_helpers_1.integTest('VPC Lookup', cdk_1.withDefaultFixture(async (fixture) => { + fixture.log('Making sure we are clean before starting.'); + await fixture.cdkDestroy('define-vpc', { modEnv: { ENABLE_VPC_TESTING: 'DEFINE' } }); + fixture.log('Setting up: creating a VPC with known tags'); + await fixture.cdkDeploy('define-vpc', { modEnv: { ENABLE_VPC_TESTING: 'DEFINE' } }); + fixture.log('Setup complete!'); + fixture.log('Verifying we can now import that VPC'); + await fixture.cdkDeploy('import-vpc', { modEnv: { ENABLE_VPC_TESTING: 'IMPORT' } }); +})); +test_helpers_1.integTest('Two ways of shoing the version', cdk_1.withDefaultFixture(async (fixture) => { + const version1 = await fixture.cdk(['version'], { verbose: false }); + const version2 = await fixture.cdk(['--version'], { verbose: false }); + expect(version1).toEqual(version2); +})); +test_helpers_1.integTest('Termination protection', cdk_1.withDefaultFixture(async (fixture) => { + const stackName = 'termination-protection'; + await fixture.cdkDeploy(stackName); + // Try a destroy that should fail + await expect(fixture.cdkDestroy(stackName)).rejects.toThrow('exited with error'); + // Can update termination protection even though the change set doesn't contain changes + await fixture.cdkDeploy(stackName, { modEnv: { TERMINATION_PROTECTION: 'FALSE' } }); + await fixture.cdkDestroy(stackName); +})); +test_helpers_1.integTest('cdk synth', cdk_1.withDefaultFixture(async (fixture) => { + await fixture.cdk(['synth', fixture.fullStackName('test-1')]); + const template1 = await readTemplate(fixture, 'test-1'); + expect(template1).toEqual({ + Resources: { + topic69831491: { + Type: 'AWS::SNS::Topic', + Metadata: { + 'aws:cdk:path': `${fixture.stackNamePrefix}-test-1/topic/Resource`, + }, + }, + }, + }); + await fixture.cdk(['synth', fixture.fullStackName('test-2')], { verbose: false }); + const template2 = await readTemplate(fixture, 'test-2'); + expect(template2).toEqual({ + Resources: { + topic152D84A37: { + Type: 'AWS::SNS::Topic', + Metadata: { + 'aws:cdk:path': `${fixture.stackNamePrefix}-test-2/topic1/Resource`, + }, + }, + topic2A4FB547F: { + Type: 'AWS::SNS::Topic', + Metadata: { + 'aws:cdk:path': `${fixture.stackNamePrefix}-test-2/topic2/Resource`, + }, + }, + }, + }); +})); +test_helpers_1.integTest('ssm parameter provider error', cdk_1.withDefaultFixture(async (fixture) => { + await expect(fixture.cdk(['synth', + fixture.fullStackName('missing-ssm-parameter'), + '-c', 'test:ssm-parameter-name=/does/not/exist'], { + allowErrExit: true, + })).resolves.toContain('SSM parameter not available in account'); +})); +test_helpers_1.integTest('automatic ordering', cdk_1.withDefaultFixture(async (fixture) => { + // Deploy the consuming stack which will include the producing stack + await fixture.cdkDeploy('order-consuming'); + // Destroy the providing stack which will include the consuming stack + await fixture.cdkDestroy('order-providing'); +})); +test_helpers_1.integTest('context setting', cdk_1.withDefaultFixture(async (fixture) => { + await fs_1.promises.writeFile(path.join(fixture.integTestDir, 'cdk.context.json'), JSON.stringify({ + contextkey: 'this is the context value', + })); + try { + await expect(fixture.cdk(['context'])).resolves.toContain('this is the context value'); + // Test that deleting the contextkey works + await fixture.cdk(['context', '--reset', 'contextkey']); + await expect(fixture.cdk(['context'])).resolves.not.toContain('this is the context value'); + // Test that forced delete of the context key does not throw + await fixture.cdk(['context', '-f', '--reset', 'contextkey']); + } + finally { + await fs_1.promises.unlink(path.join(fixture.integTestDir, 'cdk.context.json')); + } +})); +test_helpers_1.integTest('context in stage propagates to top', cdk_1.withDefaultFixture(async (fixture) => { + await expect(fixture.cdkSynth({ + // This will make it error to prove that the context bubbles up, and also that we can fail on command + options: ['--no-lookups'], + modEnv: { + INTEG_STACK_SET: 'stage-using-context', + }, + allowErrExit: true, + })).resolves.toContain('Context lookups have been disabled'); +})); +test_helpers_1.integTest('deploy', cdk_1.withDefaultFixture(async (fixture) => { + var _a; + const stackArn = await fixture.cdkDeploy('test-2', { captureStderr: false }); + // verify the number of resources in the stack + const response = await fixture.aws.cloudFormation('describeStackResources', { + StackName: stackArn, + }); + expect((_a = response.StackResources) === null || _a === void 0 ? void 0 : _a.length).toEqual(2); +})); +test_helpers_1.integTest('deploy all', cdk_1.withDefaultFixture(async (fixture) => { + const arns = await fixture.cdkDeploy('test-*', { captureStderr: false }); + // verify that we only deployed a single stack (there's a single ARN in the output) + expect(arns.split('\n').length).toEqual(2); +})); +test_helpers_1.integTest('nested stack with parameters', cdk_1.withDefaultFixture(async (fixture) => { + var _a; + // STACK_NAME_PREFIX is used in MyTopicParam to allow multiple instances + // of this test to run in parallel, othewise they will attempt to create the same SNS topic. + const stackArn = await fixture.cdkDeploy('with-nested-stack-using-parameters', { + options: ['--parameters', `MyTopicParam=${fixture.stackNamePrefix}ThereIsNoSpoon`], + captureStderr: false, + }); + // verify that we only deployed a single stack (there's a single ARN in the output) + expect(stackArn.split('\n').length).toEqual(1); + // verify the number of resources in the stack + const response = await fixture.aws.cloudFormation('describeStackResources', { + StackName: stackArn, + }); + expect((_a = response.StackResources) === null || _a === void 0 ? void 0 : _a.length).toEqual(1); +})); +test_helpers_1.integTest('deploy without execute a named change set', cdk_1.withDefaultFixture(async (fixture) => { + var _a; + const changeSetName = 'custom-change-set-name'; + const stackArn = await fixture.cdkDeploy('test-2', { + options: ['--no-execute', '--change-set-name', changeSetName], + captureStderr: false, + }); + // verify that we only deployed a single stack (there's a single ARN in the output) + expect(stackArn.split('\n').length).toEqual(1); + const response = await fixture.aws.cloudFormation('describeStacks', { + StackName: stackArn, + }); + expect((_a = response.Stacks) === null || _a === void 0 ? void 0 : _a[0].StackStatus).toEqual('REVIEW_IN_PROGRESS'); + //verify a change set was created with the provided name + const changeSetResponse = await fixture.aws.cloudFormation('listChangeSets', { + StackName: stackArn, + }); + const changeSets = changeSetResponse.Summaries || []; + expect(changeSets.length).toEqual(1); + expect(changeSets[0].ChangeSetName).toEqual(changeSetName); + expect(changeSets[0].Status).toEqual('CREATE_COMPLETE'); +})); +test_helpers_1.integTest('security related changes without a CLI are expected to fail', cdk_1.withDefaultFixture(async (fixture) => { + // redirect /dev/null to stdin, which means there will not be tty attached + // since this stack includes security-related changes, the deployment should + // immediately fail because we can't confirm the changes + const stackName = 'iam-test'; + await expect(fixture.cdkDeploy(stackName, { + options: ['<', '/dev/null'], + neverRequireApproval: false, + })).rejects.toThrow('exited with error'); + // Ensure stack was not deployed + await expect(fixture.aws.cloudFormation('describeStacks', { + StackName: fixture.fullStackName(stackName), + })).rejects.toThrow('does not exist'); +})); +test_helpers_1.integTest('deploy wildcard with outputs', cdk_1.withDefaultFixture(async (fixture) => { + const outputsFile = path.join(fixture.integTestDir, 'outputs', 'outputs.json'); + await fs_1.promises.mkdir(path.dirname(outputsFile), { recursive: true }); + await fixture.cdkDeploy(['outputs-test-*'], { + options: ['--outputs-file', outputsFile], + }); + const outputs = JSON.parse((await fs_1.promises.readFile(outputsFile, { encoding: 'utf-8' })).toString()); + expect(outputs).toEqual({ + [`${fixture.stackNamePrefix}-outputs-test-1`]: { + TopicName: `${fixture.stackNamePrefix}-outputs-test-1MyTopic`, + }, + [`${fixture.stackNamePrefix}-outputs-test-2`]: { + TopicName: `${fixture.stackNamePrefix}-outputs-test-2MyOtherTopic`, + }, + }); +})); +test_helpers_1.integTest('deploy with parameters', cdk_1.withDefaultFixture(async (fixture) => { + var _a; + const stackArn = await fixture.cdkDeploy('param-test-1', { + options: [ + '--parameters', `TopicNameParam=${fixture.stackNamePrefix}bazinga`, + ], + captureStderr: false, + }); + const response = await fixture.aws.cloudFormation('describeStacks', { + StackName: stackArn, + }); + expect((_a = response.Stacks) === null || _a === void 0 ? void 0 : _a[0].Parameters).toEqual([ + { + ParameterKey: 'TopicNameParam', + ParameterValue: `${fixture.stackNamePrefix}bazinga`, + }, + ]); +})); +test_helpers_1.integTest('update to stack in ROLLBACK_COMPLETE state will delete stack and create a new one', cdk_1.withDefaultFixture(async (fixture) => { + var _a, _b, _c, _d; + // GIVEN + await expect(fixture.cdkDeploy('param-test-1', { + options: [ + '--parameters', `TopicNameParam=${fixture.stackNamePrefix}@aww`, + ], + captureStderr: false, + })).rejects.toThrow('exited with error'); + const response = await fixture.aws.cloudFormation('describeStacks', { + StackName: fixture.fullStackName('param-test-1'), + }); + const stackArn = (_a = response.Stacks) === null || _a === void 0 ? void 0 : _a[0].StackId; + expect((_b = response.Stacks) === null || _b === void 0 ? void 0 : _b[0].StackStatus).toEqual('ROLLBACK_COMPLETE'); + // WHEN + const newStackArn = await fixture.cdkDeploy('param-test-1', { + options: [ + '--parameters', `TopicNameParam=${fixture.stackNamePrefix}allgood`, + ], + captureStderr: false, + }); + const newStackResponse = await fixture.aws.cloudFormation('describeStacks', { + StackName: newStackArn, + }); + // THEN + expect(stackArn).not.toEqual(newStackArn); // new stack was created + expect((_c = newStackResponse.Stacks) === null || _c === void 0 ? void 0 : _c[0].StackStatus).toEqual('CREATE_COMPLETE'); + expect((_d = newStackResponse.Stacks) === null || _d === void 0 ? void 0 : _d[0].Parameters).toEqual([ + { + ParameterKey: 'TopicNameParam', + ParameterValue: `${fixture.stackNamePrefix}allgood`, + }, + ]); +})); +test_helpers_1.integTest('stack in UPDATE_ROLLBACK_COMPLETE state can be updated', cdk_1.withDefaultFixture(async (fixture) => { + var _a, _b, _c, _d; + // GIVEN + const stackArn = await fixture.cdkDeploy('param-test-1', { + options: [ + '--parameters', `TopicNameParam=${fixture.stackNamePrefix}nice`, + ], + captureStderr: false, + }); + let response = await fixture.aws.cloudFormation('describeStacks', { + StackName: stackArn, + }); + expect((_a = response.Stacks) === null || _a === void 0 ? void 0 : _a[0].StackStatus).toEqual('CREATE_COMPLETE'); + // bad parameter name with @ will put stack into UPDATE_ROLLBACK_COMPLETE + await expect(fixture.cdkDeploy('param-test-1', { + options: [ + '--parameters', `TopicNameParam=${fixture.stackNamePrefix}@aww`, + ], + captureStderr: false, + })).rejects.toThrow('exited with error'); + ; + response = await fixture.aws.cloudFormation('describeStacks', { + StackName: stackArn, + }); + expect((_b = response.Stacks) === null || _b === void 0 ? void 0 : _b[0].StackStatus).toEqual('UPDATE_ROLLBACK_COMPLETE'); + // WHEN + await fixture.cdkDeploy('param-test-1', { + options: [ + '--parameters', `TopicNameParam=${fixture.stackNamePrefix}allgood`, + ], + captureStderr: false, + }); + response = await fixture.aws.cloudFormation('describeStacks', { + StackName: stackArn, + }); + // THEN + expect((_c = response.Stacks) === null || _c === void 0 ? void 0 : _c[0].StackStatus).toEqual('UPDATE_COMPLETE'); + expect((_d = response.Stacks) === null || _d === void 0 ? void 0 : _d[0].Parameters).toEqual([ + { + ParameterKey: 'TopicNameParam', + ParameterValue: `${fixture.stackNamePrefix}allgood`, + }, + ]); +})); +test_helpers_1.integTest('deploy with wildcard and parameters', cdk_1.withDefaultFixture(async (fixture) => { + await fixture.cdkDeploy('param-test-*', { + options: [ + '--parameters', `${fixture.stackNamePrefix}-param-test-1:TopicNameParam=${fixture.stackNamePrefix}bazinga`, + '--parameters', `${fixture.stackNamePrefix}-param-test-2:OtherTopicNameParam=${fixture.stackNamePrefix}ThatsMySpot`, + '--parameters', `${fixture.stackNamePrefix}-param-test-3:DisplayNameParam=${fixture.stackNamePrefix}HeyThere`, + '--parameters', `${fixture.stackNamePrefix}-param-test-3:OtherDisplayNameParam=${fixture.stackNamePrefix}AnotherOne`, + ], + }); +})); +test_helpers_1.integTest('deploy with parameters multi', cdk_1.withDefaultFixture(async (fixture) => { + var _a; + const paramVal1 = `${fixture.stackNamePrefix}bazinga`; + const paramVal2 = `${fixture.stackNamePrefix}=jagshemash`; + const stackArn = await fixture.cdkDeploy('param-test-3', { + options: [ + '--parameters', `DisplayNameParam=${paramVal1}`, + '--parameters', `OtherDisplayNameParam=${paramVal2}`, + ], + captureStderr: false, + }); + const response = await fixture.aws.cloudFormation('describeStacks', { + StackName: stackArn, + }); + expect((_a = response.Stacks) === null || _a === void 0 ? void 0 : _a[0].Parameters).toEqual([ + { + ParameterKey: 'DisplayNameParam', + ParameterValue: paramVal1, + }, + { + ParameterKey: 'OtherDisplayNameParam', + ParameterValue: paramVal2, + }, + ]); +})); +test_helpers_1.integTest('deploy with notification ARN', cdk_1.withDefaultFixture(async (fixture) => { + var _a; + const topicName = `${fixture.stackNamePrefix}-test-topic`; + const response = await fixture.aws.sns('createTopic', { Name: topicName }); + const topicArn = response.TopicArn; + try { + await fixture.cdkDeploy('test-2', { + options: ['--notification-arns', topicArn], + }); + // verify that the stack we deployed has our notification ARN + const describeResponse = await fixture.aws.cloudFormation('describeStacks', { + StackName: fixture.fullStackName('test-2'), + }); + expect((_a = describeResponse.Stacks) === null || _a === void 0 ? void 0 : _a[0].NotificationARNs).toEqual([topicArn]); + } + finally { + await fixture.aws.sns('deleteTopic', { + TopicArn: topicArn, + }); + } +})); +test_helpers_1.integTest('deploy with role', cdk_1.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', { + RoleName: roleName, + PolicyName: 'DefaultPolicy', + PolicyDocument: JSON.stringify({ + Version: '2012-10-17', + Statement: [{ + Action: '*', + Resource: '*', + Effect: 'Allow', + }], + }), + }); + await aws_1.retry(fixture.output, 'Trying to assume fresh role', aws_1.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 aws_1.sleep(5000); + 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'); + } + 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, + }); + } + await fixture.aws.iam('deleteRole', { RoleName: roleName }); + } + catch (e) { + if (e.message.indexOf('cannot be found') > -1) { + return; + } + throw e; + } + } +})); +test_helpers_1.integTest('cdk diff', cdk_1.withDefaultFixture(async (fixture) => { + const diff1 = await fixture.cdk(['diff', fixture.fullStackName('test-1')]); + expect(diff1).toContain('AWS::SNS::Topic'); + const diff2 = await fixture.cdk(['diff', fixture.fullStackName('test-2')]); + expect(diff2).toContain('AWS::SNS::Topic'); + // We can make it fail by passing --fail + await expect(fixture.cdk(['diff', '--fail', fixture.fullStackName('test-1')])) + .rejects.toThrow('exited with error'); +})); +test_helpers_1.integTest('cdk diff --fail on multiple stacks exits with error if any of the stacks contains a diff', cdk_1.withDefaultFixture(async (fixture) => { + // GIVEN + const diff1 = await fixture.cdk(['diff', fixture.fullStackName('test-1')]); + expect(diff1).toContain('AWS::SNS::Topic'); + await fixture.cdkDeploy('test-2'); + const diff2 = await fixture.cdk(['diff', fixture.fullStackName('test-2')]); + expect(diff2).toContain('There were no differences'); + // WHEN / THEN + await expect(fixture.cdk(['diff', '--fail', fixture.fullStackName('test-1'), fixture.fullStackName('test-2')])).rejects.toThrow('exited with error'); +})); +test_helpers_1.integTest('cdk diff --fail with multiple stack exits with if any of the stacks contains a diff', cdk_1.withDefaultFixture(async (fixture) => { + // GIVEN + await fixture.cdkDeploy('test-1'); + const diff1 = await fixture.cdk(['diff', fixture.fullStackName('test-1')]); + expect(diff1).toContain('There were no differences'); + const diff2 = await fixture.cdk(['diff', fixture.fullStackName('test-2')]); + expect(diff2).toContain('AWS::SNS::Topic'); + // WHEN / THEN + await expect(fixture.cdk(['diff', '--fail', fixture.fullStackName('test-1'), fixture.fullStackName('test-2')])).rejects.toThrow('exited with error'); +})); +test_helpers_1.integTest('cdk diff --security-only --fail exits when security changes are present', cdk_1.withDefaultFixture(async (fixture) => { + const stackName = 'iam-test'; + await expect(fixture.cdk(['diff', '--security-only', '--fail', fixture.fullStackName(stackName)])).rejects.toThrow('exited with error'); +})); +test_helpers_1.integTest('deploy stack with docker asset', cdk_1.withDefaultFixture(async (fixture) => { + await fixture.cdkDeploy('docker'); +})); +test_helpers_1.integTest('deploy and test stack with lambda asset', cdk_1.withDefaultFixture(async (fixture) => { + var _a, _b; + const stackArn = await fixture.cdkDeploy('lambda', { captureStderr: false }); + const response = await fixture.aws.cloudFormation('describeStacks', { + StackName: stackArn, + }); + const lambdaArn = (_b = (_a = response.Stacks) === null || _a === void 0 ? void 0 : _a[0].Outputs) === null || _b === void 0 ? void 0 : _b[0].OutputValue; + if (lambdaArn === undefined) { + throw new Error('Stack did not have expected Lambda ARN output'); + } + const output = await fixture.aws.lambda('invoke', { + FunctionName: lambdaArn, + }); + expect(JSON.stringify(output.Payload)).toContain('dear asset'); +})); +test_helpers_1.integTest('cdk ls', cdk_1.withDefaultFixture(async (fixture) => { + const listing = await fixture.cdk(['ls'], { captureStderr: false }); + const expectedStacks = [ + 'conditional-resource', + 'docker', + 'docker-with-custom-file', + 'failed', + 'iam-test', + 'lambda', + 'missing-ssm-parameter', + 'order-providing', + 'outputs-test-1', + 'outputs-test-2', + 'param-test-1', + 'param-test-2', + 'param-test-3', + 'termination-protection', + 'test-1', + 'test-2', + 'with-nested-stack', + 'with-nested-stack-using-parameters', + 'order-consuming', + ]; + for (const stack of expectedStacks) { + expect(listing).toContain(fixture.fullStackName(stack)); + } +})); +test_helpers_1.integTest('synthing a stage with errors leads to failure', cdk_1.withDefaultFixture(async (fixture) => { + const output = await fixture.cdk(['synth'], { + allowErrExit: true, + modEnv: { + INTEG_STACK_SET: 'stage-with-errors', + }, + }); + expect(output).toContain('This is an error'); +})); +test_helpers_1.integTest('synthing a stage with errors can be suppressed', cdk_1.withDefaultFixture(async (fixture) => { + await fixture.cdk(['synth', '--no-validation'], { + modEnv: { + INTEG_STACK_SET: 'stage-with-errors', + }, + }); +})); +test_helpers_1.integTest('deploy stack without resource', cdk_1.withDefaultFixture(async (fixture) => { + // Deploy the stack without resources + await fixture.cdkDeploy('conditional-resource', { modEnv: { NO_RESOURCE: 'TRUE' } }); + // This should have succeeded but not deployed the stack. + await expect(fixture.aws.cloudFormation('describeStacks', { StackName: fixture.fullStackName('conditional-resource') })) + .rejects.toThrow('conditional-resource does not exist'); + // Deploy the stack with resources + await fixture.cdkDeploy('conditional-resource'); + // Then again WITHOUT resources (this should destroy the stack) + await fixture.cdkDeploy('conditional-resource', { modEnv: { NO_RESOURCE: 'TRUE' } }); + await expect(fixture.aws.cloudFormation('describeStacks', { StackName: fixture.fullStackName('conditional-resource') })) + .rejects.toThrow('conditional-resource does not exist'); +})); +test_helpers_1.integTest('IAM diff', cdk_1.withDefaultFixture(async (fixture) => { + const output = await fixture.cdk(['diff', fixture.fullStackName('iam-test')]); + // Roughly check for a table like this: + // + // ┌───┬─────────────────┬────────┬────────────────┬────────────────────────────-──┬───────────┐ + // │ │ Resource │ Effect │ Action │ Principal │ Condition │ + // ├───┼─────────────────┼────────┼────────────────┼───────────────────────────────┼───────────┤ + // │ + │ ${SomeRole.Arn} │ Allow │ sts:AssumeRole │ Service:ec2.amazonaws.com │ │ + // └───┴─────────────────┴────────┴────────────────┴───────────────────────────────┴───────────┘ + expect(output).toContain('${SomeRole.Arn}'); + expect(output).toContain('sts:AssumeRole'); + expect(output).toContain('ec2.amazonaws.com'); +})); +test_helpers_1.integTest('fast deploy', cdk_1.withDefaultFixture(async (fixture) => { + // we are using a stack with a nested stack because CFN will always attempt to + // update a nested stack, which will allow us to verify that updates are actually + // skipped unless --force is specified. + const stackArn = await fixture.cdkDeploy('with-nested-stack', { captureStderr: false }); + const changeSet1 = await getLatestChangeSet(); + // Deploy the same stack again, there should be no new change set created + await fixture.cdkDeploy('with-nested-stack'); + const changeSet2 = await getLatestChangeSet(); + expect(changeSet2.ChangeSetId).toEqual(changeSet1.ChangeSetId); + // Deploy the stack again with --force, now we should create a changeset + await fixture.cdkDeploy('with-nested-stack', { options: ['--force'] }); + const changeSet3 = await getLatestChangeSet(); + expect(changeSet3.ChangeSetId).not.toEqual(changeSet2.ChangeSetId); + // Deploy the stack again with tags, expected to create a new changeset + // even though the resources didn't change. + await fixture.cdkDeploy('with-nested-stack', { options: ['--tags', 'key=value'] }); + const changeSet4 = await getLatestChangeSet(); + expect(changeSet4.ChangeSetId).not.toEqual(changeSet3.ChangeSetId); + async function getLatestChangeSet() { + var _a, _b, _c; + const response = await fixture.aws.cloudFormation('describeStacks', { StackName: stackArn }); + if (!((_a = response.Stacks) === null || _a === void 0 ? void 0 : _a[0])) { + throw new Error('Did not get a ChangeSet at all'); + } + fixture.log(`Found Change Set ${(_b = response.Stacks) === null || _b === void 0 ? void 0 : _b[0].ChangeSetId}`); + return (_c = response.Stacks) === null || _c === void 0 ? void 0 : _c[0]; + } +})); +test_helpers_1.integTest('failed deploy does not hang', cdk_1.withDefaultFixture(async (fixture) => { + // this will hang if we introduce https://github.com/aws/aws-cdk/issues/6403 again. + await expect(fixture.cdkDeploy('failed')).rejects.toThrow('exited with error'); +})); +test_helpers_1.integTest('can still load old assemblies', cdk_1.withDefaultFixture(async (fixture) => { + const cxAsmDir = path.join(os.tmpdir(), 'cdk-integ-cx'); + const testAssembliesDirectory = path.join(__dirname, 'cloud-assemblies'); + for (const asmdir of await listChildDirs(testAssembliesDirectory)) { + fixture.log(`ASSEMBLY ${asmdir}`); + await cdk_1.cloneDirectory(asmdir, cxAsmDir); + // Some files in the asm directory that have a .js extension are + // actually treated as templates. Evaluate them using NodeJS. + const templates = await listChildren(cxAsmDir, fullPath => Promise.resolve(fullPath.endsWith('.js'))); + for (const template of templates) { + const targetName = template.replace(/.js$/, ''); + await cdk_1.shell([process.execPath, template, '>', targetName], { + cwd: cxAsmDir, + output: fixture.output, + modEnv: { + TEST_ACCOUNT: await fixture.aws.account(), + TEST_REGION: fixture.aws.region, + }, + }); + } + // Use this directory as a Cloud Assembly + const output = await fixture.cdk([ + '--app', cxAsmDir, + '-v', + 'synth', + ]); + // Assert that there was no providerError in CDK's stderr + // Because we rely on the app/framework to actually error in case the + // provider fails, we inspect the logs here. + expect(output).not.toContain('$providerError'); + } +})); +test_helpers_1.integTest('generating and loading assembly', cdk_1.withDefaultFixture(async (fixture) => { + const asmOutputDir = `${fixture.integTestDir}-cdk-integ-asm`; + await fixture.shell(['rm', '-rf', asmOutputDir]); + // Synthesize a Cloud Assembly tothe default directory (cdk.out) and a specific directory. + await fixture.cdk(['synth']); + await fixture.cdk(['synth', '--output', asmOutputDir]); + // cdk.out in the current directory and the indicated --output should be the same + await fixture.shell(['diff', 'cdk.out', asmOutputDir]); + // Check that we can 'ls' the synthesized asm. + // Change to some random directory to make sure we're not accidentally loading cdk.json + const list = await fixture.cdk(['--app', asmOutputDir, 'ls'], { cwd: os.tmpdir() }); + // Same stacks we know are in the app + expect(list).toContain(`${fixture.stackNamePrefix}-lambda`); + expect(list).toContain(`${fixture.stackNamePrefix}-test-1`); + expect(list).toContain(`${fixture.stackNamePrefix}-test-2`); + // Check that we can use '.' and just synth ,the generated asm + const stackTemplate = await fixture.cdk(['--app', '.', 'synth', fixture.fullStackName('test-2')], { + cwd: asmOutputDir, + }); + expect(stackTemplate).toContain('topic152D84A37'); + // Deploy a Lambda from the copied asm + await fixture.cdkDeploy('lambda', { options: ['-a', '.'], cwd: asmOutputDir }); + // Remove (rename) the original custom docker file that was used during synth. + // this verifies that the assemly has a copy of it and that the manifest uses + // relative paths to reference to it. + const customDockerFile = path.join(fixture.integTestDir, 'docker', 'Dockerfile.Custom'); + await fs_1.promises.rename(customDockerFile, `${customDockerFile}~`); + try { + // deploy a docker image with custom file without synth (uses assets) + await fixture.cdkDeploy('docker-with-custom-file', { options: ['-a', '.'], cwd: asmOutputDir }); + } + finally { + // Rename back to restore fixture to original state + await fs_1.promises.rename(`${customDockerFile}~`, customDockerFile); + } +})); +test_helpers_1.integTest('templates on disk contain metadata resource, also in nested assemblies', cdk_1.withDefaultFixture(async (fixture) => { + // Synth first, and switch on version reporting because cdk.json is disabling it + await fixture.cdk(['synth', '--version-reporting=true']); + // Load template from disk from root assembly + const templateContents = await fixture.shell(['cat', 'cdk.out/*-lambda.template.json']); + 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']); + expect(JSON.parse(nestedTemplateContents).Resources.CDKMetadata).toBeTruthy(); +})); +async function listChildren(parent, pred) { + const ret = new Array(); + for (const child of await fs_1.promises.readdir(parent, { encoding: 'utf-8' })) { + const fullPath = path.join(parent, child.toString()); + if (await pred(fullPath)) { + ret.push(fullPath); + } + } + return ret; +} +async function listChildDirs(parent) { + return listChildren(parent, async (fullPath) => (await fs_1.promises.stat(fullPath)).isDirectory()); +} +async function readTemplate(fixture, stackName) { + const fullStackName = fixture.fullStackName(stackName); + const templatePath = path.join(fixture.integTestDir, 'cdk.out', `${fullStackName}.template.json`); + return JSON.parse((await fs_1.promises.readFile(templatePath, { encoding: 'utf-8' })).toString()); +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpLmludGVndGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsaS5pbnRlZ3Rlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSwyQkFBb0M7QUFDcEMseUJBQXlCO0FBQ3pCLDZCQUE2QjtBQUM3Qix3Q0FBOEM7QUFDOUMsd0NBQXdGO0FBQ3hGLDBEQUFvRDtBQUVwRCxJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsQ0FBQztBQUU1Qix3QkFBUyxDQUFDLFlBQVksRUFBRSx3QkFBa0IsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7SUFDM0QsT0FBTyxDQUFDLEdBQUcsQ0FBQywyQ0FBMkMsQ0FBQyxDQUFDO0lBQ3pELE1BQU0sT0FBTyxDQUFDLFVBQVUsQ0FBQyxZQUFZLEVBQUUsRUFBRSxNQUFNLEVBQUUsRUFBRSxrQkFBa0IsRUFBRSxRQUFRLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFFckYsT0FBTyxDQUFDLEdBQUcsQ0FBQyw0Q0FBNEMsQ0FBQyxDQUFDO0lBQzFELE1BQU0sT0FBTyxDQUFDLFNBQVMsQ0FBQyxZQUFZLEVBQUUsRUFBRSxNQUFNLEVBQUUsRUFBRSxrQkFBa0IsRUFBRSxRQUFRLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDcEYsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0lBRS9CLE9BQU8sQ0FBQyxHQUFHLENBQUMsc0NBQXNDLENBQUMsQ0FBQztJQUNwRCxNQUFNLE9BQU8sQ0FBQyxTQUFTLENBQUMsWUFBWSxFQUFFLEVBQUUsTUFBTSxFQUFFLEVBQUUsa0JBQWtCLEVBQUUsUUFBUSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0FBQ3RGLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFFSix3QkFBUyxDQUFDLGdDQUFnQyxFQUFFLHdCQUFrQixDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRTtJQUMvRSxNQUFNLFFBQVEsR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsRUFBRSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO0lBQ3BFLE1BQU0sUUFBUSxHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxFQUFFLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7SUFFdEUsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQztBQUNyQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBRUosd0JBQVMsQ0FBQyx3QkFBd0IsRUFBRSx3QkFBa0IsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7SUFDdkUsTUFBTSxTQUFTLEdBQUcsd0JBQXdCLENBQUM7SUFDM0MsTUFBTSxPQUFPLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBRW5DLGlDQUFpQztJQUNqQyxNQUFNLE1BQU0sQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO0lBRWpGLHVGQUF1RjtJQUN2RixNQUFNLE9BQU8sQ0FBQyxTQUFTLENBQUMsU0FBUyxFQUFFLEVBQUUsTUFBTSxFQUFFLEVBQUUsc0JBQXNCLEVBQUUsT0FBTyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3BGLE1BQU0sT0FBTyxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQztBQUN0QyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBRUosd0JBQVMsQ0FBQyxXQUFXLEVBQUUsd0JBQWtCLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxFQUFFO0lBQzFELE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM5RCxNQUFNLFNBQVMsR0FBRyxNQUFNLFlBQVksQ0FBQyxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDeEQsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLE9BQU8sQ0FBQztRQUN4QixTQUFTLEVBQUU7WUFDVCxhQUFhLEVBQUU7Z0JBQ2IsSUFBSSxFQUFFLGlCQUFpQjtnQkFDdkIsUUFBUSxFQUFFO29CQUNSLGNBQWMsRUFBRSxHQUFHLE9BQU8sQ0FBQyxlQUFlLHdCQUF3QjtpQkFDbkU7YUFDRjtTQUNGO0tBQ0YsQ0FBQyxDQUFDO0lBRUgsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO0lBQ2xGLE1BQU0sU0FBUyxHQUFHLE1BQU0sWUFBWSxDQUFDLE9BQU8sRUFBRSxRQUFRLENBQUMsQ0FBQztJQUN4RCxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUMsT0FBTyxDQUFDO1FBQ3hCLFNBQVMsRUFBRTtZQUNULGNBQWMsRUFBRTtnQkFDZCxJQUFJLEVBQUUsaUJBQWlCO2dCQUN2QixRQUFRLEVBQUU7b0JBQ1IsY0FBYyxFQUFFLEdBQUcsT0FBTyxDQUFDLGVBQWUseUJBQXlCO2lCQUNwRTthQUNGO1lBQ0QsY0FBYyxFQUFFO2dCQUNkLElBQUksRUFBRSxpQkFBaUI7Z0JBQ3ZCLFFBQVEsRUFBRTtvQkFDUixjQUFjLEVBQUUsR0FBRyxPQUFPLENBQUMsZUFBZSx5QkFBeUI7aUJBQ3BFO2FBQ0Y7U0FDRjtLQUNGLENBQUMsQ0FBQztBQUVMLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFFSix3QkFBUyxDQUFDLDhCQUE4QixFQUFFLHdCQUFrQixDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRTtJQUM3RSxNQUFNLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTztRQUMvQixPQUFPLENBQUMsYUFBYSxDQUFDLHVCQUF1QixDQUFDO1FBQzlDLElBQUksRUFBRSx5Q0FBeUMsQ0FBQyxFQUFFO1FBQ2xELFlBQVksRUFBRSxJQUFJO0tBQ25CLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsd0NBQXdDLENBQUMsQ0FBQztBQUNuRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBRUosd0JBQVMsQ0FBQyxvQkFBb0IsRUFBRSx3QkFBa0IsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7SUFDbkUsb0VBQW9FO0lBQ3BFLE1BQU0sT0FBTyxDQUFDLFNBQVMsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0lBRTNDLHFFQUFxRTtJQUNyRSxNQUFNLE9BQU8sQ0FBQyxVQUFVLENBQUMsaUJBQWlCLENBQUMsQ0FBQztBQUM5QyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBRUosd0JBQVMsQ0FBQyxpQkFBaUIsRUFBRSx3QkFBa0IsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7SUFDaEUsTUFBTSxhQUFFLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLFlBQVksRUFBRSxrQkFBa0IsQ0FBQyxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUM7UUFDckYsVUFBVSxFQUFFLDJCQUEyQjtLQUN4QyxDQUFDLENBQUMsQ0FBQztJQUNKLElBQUk7UUFDRixNQUFNLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsMkJBQTJCLENBQUMsQ0FBQztRQUV2RiwwQ0FBMEM7UUFDMUMsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsU0FBUyxFQUFFLFNBQVMsRUFBRSxZQUFZLENBQUMsQ0FBQyxDQUFDO1FBQ3hELE1BQU0sTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsMkJBQTJCLENBQUMsQ0FBQztRQUUzRiw0REFBNEQ7UUFDNUQsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsU0FBUyxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsWUFBWSxDQUFDLENBQUMsQ0FBQztLQUUvRDtZQUFTO1FBQ1IsTUFBTSxhQUFFLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLFlBQVksRUFBRSxrQkFBa0IsQ0FBQyxDQUFDLENBQUM7S0FDdEU7QUFDSCxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBRUosd0JBQVMsQ0FBQyxvQ0FBb0MsRUFBRSx3QkFBa0IsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7SUFDbkYsTUFBTSxNQUFNLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQztRQUM1QixxR0FBcUc7UUFDckcsT0FBTyxFQUFFLENBQUMsY0FBYyxDQUFDO1FBQ3pCLE1BQU0sRUFBRTtZQUNOLGVBQWUsRUFBRSxxQkFBcUI7U0FDdkM7UUFDRCxZQUFZLEVBQUUsSUFBSTtLQUNuQixDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLG9DQUFvQyxDQUFDLENBQUM7QUFDL0QsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUVKLHdCQUFTLENBQUMsUUFBUSxFQUFFLHdCQUFrQixDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRTs7SUFDdkQsTUFBTSxRQUFRLEdBQUcsTUFBTSxPQUFPLENBQUMsU0FBUyxDQUFDLFFBQVEsRUFBRSxFQUFFLGFBQWEsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO0lBRTdFLDhDQUE4QztJQUM5QyxNQUFNLFFBQVEsR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLHdCQUF3QixFQUFFO1FBQzFFLFNBQVMsRUFBRSxRQUFRO0tBQ3BCLENBQUMsQ0FBQztJQUNILE1BQU0sT0FBQyxRQUFRLENBQUMsY0FBYywwQ0FBRSxNQUFNLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDckQsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUVKLHdCQUFTLENBQUMsWUFBWSxFQUFFLHdCQUFrQixDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRTtJQUMzRCxNQUFNLElBQUksR0FBRyxNQUFNLE9BQU8sQ0FBQyxTQUFTLENBQUMsUUFBUSxFQUFFLEVBQUUsYUFBYSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7SUFFekUsbUZBQW1GO0lBQ25GLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUM3QyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBRUosd0JBQVMsQ0FBQyw4QkFBOEIsRUFBRSx3QkFBa0IsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7O0lBQzdFLHdFQUF3RTtJQUN4RSw0RkFBNEY7SUFDNUYsTUFBTSxRQUFRLEdBQUcsTUFBTSxPQUFPLENBQUMsU0FBUyxDQUFDLG9DQUFvQyxFQUFFO1FBQzdFLE9BQU8sRUFBRSxDQUFDLGNBQWMsRUFBRSxnQkFBZ0IsT0FBTyxDQUFDLGVBQWUsZ0JBQWdCLENBQUM7UUFDbEYsYUFBYSxFQUFFLEtBQUs7S0FDckIsQ0FBQyxDQUFDO0lBRUgsbUZBQW1GO0lBQ25GLE1BQU0sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUUvQyw4Q0FBOEM7SUFDOUMsTUFBTSxRQUFRLEdBQUcsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQyx3QkFBd0IsRUFBRTtRQUMxRSxTQUFTLEVBQUUsUUFBUTtLQUNwQixDQUFDLENBQUM7SUFDSCxNQUFNLE9BQUMsUUFBUSxDQUFDLGNBQWMsMENBQUUsTUFBTSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ3JELENBQUMsQ0FBQyxDQUFDLENBQUM7QUFFSix3QkFBUyxDQUFDLDJDQUEyQyxFQUFFLHdCQUFrQixDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRTs7SUFDMUYsTUFBTSxhQUFhLEdBQUcsd0JBQXdCLENBQUM7SUFDL0MsTUFBTSxRQUFRLEdBQUcsTUFBTSxPQUFPLENBQUMsU0FBUyxDQUFDLFFBQVEsRUFBRTtRQUNqRCxPQUFPLEVBQUUsQ0FBQyxjQUFjLEVBQUUsbUJBQW1CLEVBQUUsYUFBYSxDQUFDO1FBQzdELGFBQWEsRUFBRSxLQUFLO0tBQ3JCLENBQUMsQ0FBQztJQUNILG1GQUFtRjtJQUNuRixNQUFNLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFL0MsTUFBTSxRQUFRLEdBQUcsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQyxnQkFBZ0IsRUFBRTtRQUNsRSxTQUFTLEVBQUUsUUFBUTtLQUNwQixDQUFDLENBQUM7SUFDSCxNQUFNLE9BQUMsUUFBUSxDQUFDLE1BQU0sMENBQUcsQ0FBQyxFQUFFLFdBQVcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO0lBRXZFLHdEQUF3RDtJQUN4RCxNQUFNLGlCQUFpQixHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxjQUFjLENBQUMsZ0JBQWdCLEVBQUU7UUFDM0UsU0FBUyxFQUFFLFFBQVE7S0FDcEIsQ0FBQyxDQUFDO0lBQ0gsTUFBTSxVQUFVLEdBQUcsaUJBQWlCLENBQUMsU0FBUyxJQUFJLEVBQUUsQ0FBQztJQUNyRCxNQUFNLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNyQyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsQ0FBQztJQUMzRCxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0FBQzFELENBQUMsQ0FBQyxDQUFDLENBQUM7QUFFSix3QkFBUyxDQUFDLDZEQUE2RCxFQUFFLHdCQUFrQixDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRTtJQUM1RywwRUFBMEU7SUFDMUUsNEVBQTRFO0lBQzVFLHdEQUF3RDtJQUN4RCxNQUFNLFNBQVMsR0FBRyxVQUFVLENBQUM7SUFDN0IsTUFBTSxNQUFNLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxTQUFTLEVBQUU7UUFDeEMsT0FBTyxFQUFFLENBQUMsR0FBRyxFQUFFLFdBQVcsQ0FBQztRQUMzQixvQkFBb0IsRUFBRSxLQUFLO0tBQzVCLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsbUJBQW1CLENBQUMsQ0FBQztJQUV6QyxnQ0FBZ0M7SUFDaEMsTUFBTSxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxjQUFjLENBQUMsZ0JBQWdCLEVBQUU7UUFDeEQsU0FBUyxFQUFFLE9BQU8sQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDO0tBQzVDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztBQUN4QyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBRUosd0JBQVMsQ0FBQyw4QkFBOEIsRUFBRSx3QkFBa0IsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7SUFDN0UsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsWUFBWSxFQUFFLFNBQVMsRUFBRSxjQUFjLENBQUMsQ0FBQztJQUMvRSxNQUFNLGFBQUUsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsRUFBRSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBRS9ELE1BQU0sT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDLGdCQUFnQixDQUFDLEVBQUU7UUFDMUMsT0FBTyxFQUFFLENBQUMsZ0JBQWdCLEVBQUUsV0FBVyxDQUFDO0tBQ3pDLENBQUMsQ0FBQztJQUVILE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxNQUFNLGFBQUUsQ0FBQyxRQUFRLENBQUMsV0FBVyxFQUFFLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDO0lBQy9GLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxPQUFPLENBQUM7UUFDdEIsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxlQUFlLGlCQUFpQixDQUFDLEVBQUU7WUFDN0MsU0FBUyxFQUFFLEdBQUcsT0FBTyxDQUFDLGVBQWUsd0JBQXdCO1NBQzlEO1FBQ0QsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxlQUFlLGlCQUFpQixDQUFDLEVBQUU7WUFDN0MsU0FBUyxFQUFFLEdBQUcsT0FBTyxDQUFDLGVBQWUsNkJBQTZCO1NBQ25FO0tBQ0YsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUVKLHdCQUFTLENBQUMsd0JBQXdCLEVBQUUsd0JBQWtCLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxFQUFFOztJQUN2RSxNQUFNLFFBQVEsR0FBRyxNQUFNLE9BQU8sQ0FBQyxTQUFTLENBQUMsY0FBYyxFQUFFO1FBQ3ZELE9BQU8sRUFBRTtZQUNQLGNBQWMsRUFBRSxrQkFBa0IsT0FBTyxDQUFDLGVBQWUsU0FBUztTQUNuRTtRQUNELGFBQWEsRUFBRSxLQUFLO0tBQ3JCLENBQUMsQ0FBQztJQUVILE1BQU0sUUFBUSxHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxjQUFjLENBQUMsZ0JBQWdCLEVBQUU7UUFDbEUsU0FBUyxFQUFFLFFBQVE7S0FDcEIsQ0FBQyxDQUFDO0lBRUgsTUFBTSxPQUFDLFFBQVEsQ0FBQyxNQUFNLDBDQUFHLENBQUMsRUFBRSxVQUFVLENBQUMsQ0FBQyxPQUFPLENBQUM7UUFDOUM7WUFDRSxZQUFZLEVBQUUsZ0JBQWdCO1lBQzlCLGNBQWMsRUFBRSxHQUFHLE9BQU8sQ0FBQyxlQUFlLFNBQVM7U0FDcEQ7S0FDRixDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBRUosd0JBQVMsQ0FBQyxtRkFBbUYsRUFBRSx3QkFBa0IsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7O0lBQ2xJLFFBQVE7SUFDUixNQUFNLE1BQU0sQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLGNBQWMsRUFBRTtRQUM3QyxPQUFPLEVBQUU7WUFDUCxjQUFjLEVBQUUsa0JBQWtCLE9BQU8sQ0FBQyxlQUFlLE1BQU07U0FDaEU7UUFDRCxhQUFhLEVBQUUsS0FBSztLQUNyQixDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLG1CQUFtQixDQUFDLENBQUM7SUFFekMsTUFBTSxRQUFRLEdBQUcsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQyxnQkFBZ0IsRUFBRTtRQUNsRSxTQUFTLEVBQUUsT0FBTyxDQUFDLGFBQWEsQ0FBQyxjQUFjLENBQUM7S0FDakQsQ0FBQyxDQUFDO0lBRUgsTUFBTSxRQUFRLFNBQUcsUUFBUSxDQUFDLE1BQU0sMENBQUcsQ0FBQyxFQUFFLE9BQU8sQ0FBQztJQUM5QyxNQUFNLE9BQUMsUUFBUSxDQUFDLE1BQU0sMENBQUcsQ0FBQyxFQUFFLFdBQVcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO0lBRXRFLE9BQU87SUFDUCxNQUFNLFdBQVcsR0FBRyxNQUFNLE9BQU8sQ0FBQyxTQUFTLENBQUMsY0FBYyxFQUFFO1FBQzFELE9BQU8sRUFBRTtZQUNQLGNBQWMsRUFBRSxrQkFBa0IsT0FBTyxDQUFDLGVBQWUsU0FBUztTQUNuRTtRQUNELGFBQWEsRUFBRSxLQUFLO0tBQ3JCLENBQUMsQ0FBQztJQUVILE1BQU0sZ0JBQWdCLEdBQUcsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQyxnQkFBZ0IsRUFBRTtRQUMxRSxTQUFTLEVBQUUsV0FBVztLQUN2QixDQUFDLENBQUM7SUFFSCxPQUFPO0lBQ1AsTUFBTSxDQUFFLFFBQVEsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyx3QkFBd0I7SUFDcEUsTUFBTSxPQUFDLGdCQUFnQixDQUFDLE1BQU0sMENBQUcsQ0FBQyxFQUFFLFdBQVcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0lBQzVFLE1BQU0sT0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLDBDQUFHLENBQUMsRUFBRSxVQUFVLENBQUMsQ0FBQyxPQUFPLENBQUM7UUFDdEQ7WUFDRSxZQUFZLEVBQUUsZ0JBQWdCO1lBQzlCLGNBQWMsRUFBRSxHQUFHLE9BQU8sQ0FBQyxlQUFlLFNBQVM7U0FDcEQ7S0FDRixDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBRUosd0JBQVMsQ0FBQyx3REFBd0QsRUFBRSx3QkFBa0IsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7O0lBQ3ZHLFFBQVE7SUFDUixNQUFNLFFBQVEsR0FBRyxNQUFNLE9BQU8sQ0FBQyxTQUFTLENBQUMsY0FBYyxFQUFFO1FBQ3ZELE9BQU8sRUFBRTtZQUNQLGNBQWMsRUFBRSxrQkFBa0IsT0FBTyxDQUFDLGVBQWUsTUFBTTtTQUNoRTtRQUNELGFBQWEsRUFBRSxLQUFLO0tBQ3JCLENBQUMsQ0FBQztJQUVILElBQUksUUFBUSxHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxjQUFjLENBQUMsZ0JBQWdCLEVBQUU7UUFDaEUsU0FBUyxFQUFFLFFBQVE7S0FDcEIsQ0FBQyxDQUFDO0lBRUgsTUFBTSxPQUFDLFFBQVEsQ0FBQyxNQUFNLDBDQUFHLENBQUMsRUFBRSxXQUFXLENBQUMsQ0FBQyxPQUFPLENBQUMsaUJBQWlCLENBQUMsQ0FBQztJQUVwRSx5RUFBeUU7SUFDekUsTUFBTSxNQUFNLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxjQUFjLEVBQUU7UUFDN0MsT0FBTyxFQUFFO1lBQ1AsY0FBYyxFQUFFLGtCQUFrQixPQUFPLENBQUMsZUFBZSxNQUFNO1NBQ2hFO1FBQ0QsYUFBYSxFQUFFLEtBQUs7S0FDckIsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO0lBQUEsQ0FBQztJQUUxQyxRQUFRLEdBQUcsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQyxnQkFBZ0IsRUFBRTtRQUM1RCxTQUFTLEVBQUUsUUFBUTtLQUNwQixDQUFDLENBQUM7SUFFSCxNQUFNLE9BQUMsUUFBUSxDQUFDLE1BQU0sMENBQUcsQ0FBQyxFQUFFLFdBQVcsQ0FBQyxDQUFDLE9BQU8sQ0FBQywwQkFBMEIsQ0FBQyxDQUFDO0lBRTdFLE9BQU87SUFDUCxNQUFNLE9BQU8sQ0FBQyxTQUFTLENBQUMsY0FBYyxFQUFFO1FBQ3RDLE9BQU8sRUFBRTtZQUNQLGNBQWMsRUFBRSxrQkFBa0IsT0FBTyxDQUFDLGVBQWUsU0FBUztTQUNuRTtRQUNELGFBQWEsRUFBRSxLQUFLO0tBQ3JCLENBQUMsQ0FBQztJQUVILFFBQVEsR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLGdCQUFnQixFQUFFO1FBQzVELFNBQVMsRUFBRSxRQUFRO0tBQ3BCLENBQUMsQ0FBQztJQUVILE9BQU87SUFDUCxNQUFNLE9BQUMsUUFBUSxDQUFDLE1BQU0sMENBQUcsQ0FBQyxFQUFFLFdBQVcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0lBQ3BFLE1BQU0sT0FBQyxRQUFRLENBQUMsTUFBTSwwQ0FBRyxDQUFDLEVBQUUsVUFBVSxDQUFDLENBQUMsT0FBTyxDQUFDO1FBQzlDO1lBQ0UsWUFBWSxFQUFFLGdCQUFnQjtZQUM5QixjQUFjLEVBQUUsR0FBRyxPQUFPLENBQUMsZUFBZSxTQUFTO1NBQ3BEO0tBQ0YsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUVKLHdCQUFTLENBQUMscUNBQXFDLEVBQUUsd0JBQWtCLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxFQUFFO0lBQ3BGLE1BQU0sT0FBTyxDQUFDLFNBQVMsQ0FBQyxjQUFjLEVBQUU7UUFDdEMsT0FBTyxFQUFFO1lBQ1AsY0FBYyxFQUFFLEdBQUcsT0FBTyxDQUFDLGVBQWUsZ0NBQWdDLE9BQU8sQ0FBQyxlQUFlLFNBQVM7WUFDMUcsY0FBYyxFQUFFLEdBQUcsT0FBTyxDQUFDLGVBQWUscUNBQXFDLE9BQU8sQ0FBQyxlQUFlLGFBQWE7WUFDbkgsY0FBYyxFQUFFLEdBQUcsT0FBTyxDQUFDLGVBQWUsa0NBQWtDLE9BQU8sQ0FBQyxlQUFlLFVBQVU7WUFDN0csY0FBYyxFQUFFLEdBQUcsT0FBTyxDQUFDLGVBQWUsdUNBQXVDLE9BQU8sQ0FBQyxlQUFlLFlBQVk7U0FDckg7S0FDRixDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBRUosd0JBQVMsQ0FBQyw4QkFBOEIsRUFBRSx3QkFBa0IsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7O0lBQzdFLE1BQU0sU0FBUyxHQUFHLEdBQUcsT0FBTyxDQUFDLGVBQWUsU0FBUyxDQUFDO0lBQ3RELE1BQU0sU0FBUyxHQUFHLEdBQUcsT0FBTyxDQUFDLGVBQWUsYUFBYSxDQUFDO0lBRTFELE1BQU0sUUFBUSxHQUFHLE1BQU0sT0FBTyxDQUFDLFNBQVMsQ0FBQyxjQUFjLEVBQUU7UUFDdkQsT0FBTyxFQUFFO1lBQ1AsY0FBYyxFQUFFLG9CQUFvQixTQUFTLEVBQUU7WUFDL0MsY0FBYyxFQUFFLHlCQUF5QixTQUFTLEVBQUU7U0FDckQ7UUFDRCxhQUFhLEVBQUUsS0FBSztLQUNyQixDQUFDLENBQUM7SUFFSCxNQUFNLFFBQVEsR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLGdCQUFnQixFQUFFO1FBQ2xFLFNBQVMsRUFBRSxRQUFRO0tBQ3BCLENBQUMsQ0FBQztJQUVILE1BQU0sT0FBQyxRQUFRLENBQUMsTUFBTSwwQ0FBRyxDQUFDLEVBQUUsVUFBVSxDQUFDLENBQUMsT0FBTyxDQUFDO1FBQzlDO1lBQ0UsWUFBWSxFQUFFLGtCQUFrQjtZQUNoQyxjQUFjLEVBQUUsU0FBUztTQUMxQjtRQUNEO1lBQ0UsWUFBWSxFQUFFLHVCQUF1QjtZQUNyQyxjQUFjLEVBQUUsU0FBUztTQUMxQjtLQUNGLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFFSix3QkFBUyxDQUFDLDhCQUE4QixFQUFFLHdCQUFrQixDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRTs7SUFDN0UsTUFBTSxTQUFTLEdBQUcsR0FBRyxPQUFPLENBQUMsZUFBZSxhQUFhLENBQUM7SUFFMUQsTUFBTSxRQUFRLEdBQUcsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxhQUFhLEVBQUUsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQztJQUMzRSxNQUFNLFFBQVEsR0FBRyxRQUFRLENBQUMsUUFBUyxDQUFDO0lBQ3BDLElBQUk7UUFDRixNQUFNLE9BQU8sQ0FBQyxTQUFTLENBQUMsUUFBUSxFQUFFO1lBQ2hDLE9BQU8sRUFBRSxDQUFDLHFCQUFxQixFQUFFLFFBQVEsQ0FBQztTQUMzQyxDQUFDLENBQUM7UUFFSCw2REFBNkQ7UUFDN0QsTUFBTSxnQkFBZ0IsR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLGdCQUFnQixFQUFFO1lBQzFFLFNBQVMsRUFBRSxPQUFPLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQztTQUMzQyxDQUFDLENBQUM7UUFDSCxNQUFNLE9BQUMsZ0JBQWdCLENBQUMsTUFBTSwwQ0FBRyxDQUFDLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO0tBQzNFO1lBQVM7UUFDUixNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLGFBQWEsRUFBRTtZQUNuQyxRQUFRLEVBQUUsUUFBUTtTQUNuQixDQUFDLENBQUM7S0FDSjtBQUNILENBQUMsQ0FBQyxDQUFDLENBQUM7QUFFSix3QkFBUyxDQUFDLGtCQUFrQixFQUFFLHdCQUFrQixDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRTtJQUNqRSxNQUFNLFFBQVEsR0FBRyxHQUFHLE9BQU8sQ0FBQyxlQUFlLFlBQVksQ0FBQztJQUV4RCxNQUFNLFVBQVUsRUFBRSxDQUFDO0lBRW5CLE1BQU0sY0FBYyxHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsWUFBWSxFQUFFO1FBQ3pELFFBQVEsRUFBRSxRQUFRO1FBQ2xCLHdCQUF3QixFQUFFLElBQUksQ0FBQyxTQUFTLENBQUM7WUFDdkMsT0FBTyxFQUFFLFlBQVk7WUFDckIsU0FBUyxFQUFFLENBQUM7b0JBQ1YsTUFBTSxFQUFFLGdCQUFnQjtvQkFDeEIsU0FBUyxFQUFFLEVBQUUsT0FBTyxFQUFFLDhCQUE4QixFQUFFO29CQUN0RCxNQUFNLEVBQUUsT0FBTztpQkFDaEIsRUFBRTtvQkFDRCxNQUFNLEVBQUUsZ0JBQWdCO29CQUN4QixTQUFTLEVBQUUsRUFBRSxHQUFHLEVBQUUsQ0FBQyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLG1CQUFtQixFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFO29CQUN4RSxNQUFNLEVBQUUsT0FBTztpQkFDaEIsQ0FBQztTQUNILENBQUM7S0FDSCxDQUFDLENBQUM7SUFDSCxNQUFNLE9BQU8sR0FBRyxjQUFjLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQztJQUN4QyxJQUFJO1FBQ0YsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxlQUFlLEVBQUU7WUFDckMsUUFBUSxFQUFFLFFBQVE7WUFDbEIsVUFBVSxFQUFFLGVBQWU7WUFDM0IsY0FBYyxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUM7Z0JBQzdCLE9BQU8sRUFBRSxZQUFZO2dCQUNyQixTQUFTLEVBQUUsQ0FBQzt3QkFDVixNQUFNLEVBQUUsR0FBRzt3QkFDWCxRQUFRLEVBQUUsR0FBRzt3QkFDYixNQUFNLEVBQUUsT0FBTztxQkFDaEIsQ0FBQzthQUNILENBQUM7U0FDSCxDQUFDLENBQUM7UUFFSCxNQUFNLFdBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLDZCQUE2QixFQUFFLFdBQUssQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDM0YsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxZQUFZLEVBQUU7Z0JBQ2xDLE9BQU8sRUFBRSxPQUFPO2dCQUNoQixlQUFlLEVBQUUsU0FBUzthQUMzQixDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztRQUVILG9GQUFvRjtRQUNwRiwrRUFBK0U7UUFDL0UsNEJBQTRCO1FBQzVCLE1BQU0sV0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRWxCLE1BQU0sT0FBTyxDQUFDLFNBQVMsQ0FBQyxRQUFRLEVBQUU7WUFDaEMsT0FBTyxFQUFFLENBQUMsWUFBWSxFQUFFLE9BQU8sQ0FBQztTQUNqQyxDQUFDLENBQUM7UUFFSCxnRUFBZ0U7UUFDaEUsRUFBRTtRQUNGLHlGQUF5RjtRQUN6Rix5RkFBeUY7UUFDekYsTUFBTSxPQUFPLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0tBRXBDO1lBQVM7UUFDUixNQUFNLFVBQVUsRUFBRSxDQUFDO0tBQ3BCO0lBRUQsS0FBSyxVQUFVLFVBQVU7UUFDdkIsSUFBSTtZQUNGLEtBQUssTUFBTSxVQUFVLElBQUksQ0FBQyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLGtCQUFrQixFQUFFLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUMsQ0FBQyxXQUFXLEVBQUU7Z0JBQ3hHLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsa0JBQWtCLEVBQUU7b0JBQ3hDLFFBQVEsRUFBRSxRQUFRO29CQUNsQixVQUFVLEVBQUUsVUFBVTtpQkFDdkIsQ0FBQyxDQUFDO2FBQ0o7WUFDRCxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLFlBQVksRUFBRSxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDO1NBQzdEO1FBQUMsT0FBTyxDQUFDLEVBQUU7WUFDVixJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUU7Z0JBQUUsT0FBTzthQUFFO1lBQzFELE1BQU0sQ0FBQyxDQUFDO1NBQ1Q7SUFDSCxDQUFDO0FBQ0gsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUVKLHdCQUFTLENBQUMsVUFBVSxFQUFFLHdCQUFrQixDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRTtJQUN6RCxNQUFNLEtBQUssR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDM0UsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLFNBQVMsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0lBRTNDLE1BQU0sS0FBSyxHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sRUFBRSxPQUFPLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMzRSxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsU0FBUyxDQUFDLGlCQUFpQixDQUFDLENBQUM7SUFFM0Msd0NBQXdDO0lBQ3hDLE1BQU0sTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsUUFBUSxFQUFFLE9BQU8sQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO1NBQzNFLE9BQU8sQ0FBQyxPQUFPLENBQUMsbUJBQW1CLENBQUMsQ0FBQztBQUMxQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBRUosd0JBQVMsQ0FBQywwRkFBMEYsRUFBRSx3QkFBa0IsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7SUFDekksUUFBUTtJQUNSLE1BQU0sS0FBSyxHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sRUFBRSxPQUFPLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMzRSxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsU0FBUyxDQUFDLGlCQUFpQixDQUFDLENBQUM7SUFFM0MsTUFBTSxPQUFPLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ2xDLE1BQU0sS0FBSyxHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sRUFBRSxPQUFPLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMzRSxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsU0FBUyxDQUFDLDJCQUEyQixDQUFDLENBQUM7SUFFckQsY0FBYztJQUNkLE1BQU0sTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsUUFBUSxFQUFFLE9BQU8sQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLEVBQUUsT0FBTyxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLG1CQUFtQixDQUFDLENBQUM7QUFDdkosQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUVKLHdCQUFTLENBQUMscUZBQXFGLEVBQUUsd0JBQWtCLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxFQUFFO0lBQ3BJLFFBQVE7SUFDUixNQUFNLE9BQU8sQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDbEMsTUFBTSxLQUFLLEdBQUcsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzNFLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxTQUFTLENBQUMsMkJBQTJCLENBQUMsQ0FBQztJQUVyRCxNQUFNLEtBQUssR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDM0UsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLFNBQVMsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0lBRTNDLGNBQWM7SUFDZCxNQUFNLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxFQUFFLFFBQVEsRUFBRSxPQUFPLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO0FBQ3ZKLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFFSix3QkFBUyxDQUFDLHlFQUF5RSxFQUFFLHdCQUFrQixDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRTtJQUN4SCxNQUFNLFNBQVMsR0FBRyxVQUFVLENBQUM7SUFDN0IsTUFBTSxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sRUFBRSxpQkFBaUIsRUFBRSxRQUFRLEVBQUUsT0FBTyxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLG1CQUFtQixDQUFDLENBQUM7QUFDMUksQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUVKLHdCQUFTLENBQUMsZ0NBQWdDLEVBQUUsd0JBQWtCLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxFQUFFO0lBQy9FLE1BQU0sT0FBTyxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsQ0FBQztBQUNwQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBRUosd0JBQVMsQ0FBQyx5Q0FBeUMsRUFBRSx3QkFBa0IsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7O0lBQ3hGLE1BQU0sUUFBUSxHQUFHLE1BQU0sT0FBTyxDQUFDLFNBQVMsQ0FBQyxRQUFRLEVBQUUsRUFBRSxhQUFhLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztJQUU3RSxNQUFNLFFBQVEsR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLGdCQUFnQixFQUFFO1FBQ2xFLFNBQVMsRUFBRSxRQUFRO0tBQ3BCLENBQUMsQ0FBQztJQUNILE1BQU0sU0FBUyxlQUFHLFFBQVEsQ0FBQyxNQUFNLDBDQUFHLENBQUMsRUFBRSxPQUFPLDBDQUFHLENBQUMsRUFBRSxXQUFXLENBQUM7SUFDaEUsSUFBSSxTQUFTLEtBQUssU0FBUyxFQUFFO1FBQzNCLE1BQU0sSUFBSSxLQUFLLENBQUMsK0NBQStDLENBQUMsQ0FBQztLQUNsRTtJQUVELE1BQU0sTUFBTSxHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFO1FBQ2hELFlBQVksRUFBRSxTQUFTO0tBQ3hCLENBQUMsQ0FBQztJQUVILE1BQU0sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxZQUFZLENBQUMsQ0FBQztBQUNqRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBRUosd0JBQVMsQ0FBQyxRQUFRLEVBQUUsd0JBQWtCLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxFQUFFO0lBQ3ZELE1BQU0sT0FBTyxHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUUsYUFBYSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7SUFFcEUsTUFBTSxjQUFjLEdBQUc7UUFDckIsc0JBQXNCO1FBQ3RCLFFBQVE7UUFDUix5QkFBeUI7UUFDekIsUUFBUTtRQUNSLFVBQVU7UUFDVixRQUFRO1FBQ1IsdUJBQXVCO1FBQ3ZCLGlCQUFpQjtRQUNqQixnQkFBZ0I7UUFDaEIsZ0JBQWdCO1FBQ2hCLGNBQWM7UUFDZCxjQUFjO1FBQ2QsY0FBYztRQUNkLHdCQUF3QjtRQUN4QixRQUFRO1FBQ1IsUUFBUTtRQUNSLG1CQUFtQjtRQUNuQixvQ0FBb0M7UUFDcEMsaUJBQWlCO0tBQ2xCLENBQUM7SUFFRixLQUFLLE1BQU0sS0FBSyxJQUFJLGNBQWMsRUFBRTtRQUNsQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztLQUN6RDtBQUNILENBQUMsQ0FBQyxDQUFDLENBQUM7QUFFSix3QkFBUyxDQUFDLCtDQUErQyxFQUFFLHdCQUFrQixDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRTtJQUM5RixNQUFNLE1BQU0sR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsRUFBRTtRQUMxQyxZQUFZLEVBQUUsSUFBSTtRQUNsQixNQUFNLEVBQUU7WUFDTixlQUFlLEVBQUUsbUJBQW1CO1NBQ3JDO0tBQ0YsQ0FBQyxDQUFDO0lBRUgsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLFNBQVMsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0FBQy9DLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFFSix3QkFBUyxDQUFDLGdEQUFnRCxFQUFFLHdCQUFrQixDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRTtJQUMvRixNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsaUJBQWlCLENBQUMsRUFBRTtRQUM5QyxNQUFNLEVBQUU7WUFDTixlQUFlLEVBQUUsbUJBQW1CO1NBQ3JDO0tBQ0YsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUVKLHdCQUFTLENBQUMsK0JBQStCLEVBQUUsd0JBQWtCLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxFQUFFO0lBQzlFLHFDQUFxQztJQUNyQyxNQUFNLE9BQU8sQ0FBQyxTQUFTLENBQUMsc0JBQXNCLEVBQUUsRUFBRSxNQUFNLEVBQUUsRUFBRSxXQUFXLEVBQUUsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBRXJGLHlEQUF5RDtJQUN6RCxNQUFNLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQyxnQkFBZ0IsRUFBRSxFQUFFLFNBQVMsRUFBRSxPQUFPLENBQUMsYUFBYSxDQUFDLHNCQUFzQixDQUFDLEVBQUUsQ0FBQyxDQUFDO1NBQ3JILE9BQU8sQ0FBQyxPQUFPLENBQUMscUNBQXFDLENBQUMsQ0FBQztJQUUxRCxrQ0FBa0M7SUFDbEMsTUFBTSxPQUFPLENBQUMsU0FBUyxDQUFDLHNCQUFzQixDQUFDLENBQUM7SUFFaEQsK0RBQStEO0lBQy9ELE1BQU0sT0FBTyxDQUFDLFNBQVMsQ0FBQyxzQkFBc0IsRUFBRSxFQUFFLE1BQU0sRUFBRSxFQUFFLFdBQVcsRUFBRSxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFFckYsTUFBTSxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxjQUFjLENBQUMsZ0JBQWdCLEVBQUUsRUFBRSxTQUFTLEVBQUUsT0FBTyxDQUFDLGFBQWEsQ0FBQyxzQkFBc0IsQ0FBQyxFQUFFLENBQUMsQ0FBQztTQUNySCxPQUFPLENBQUMsT0FBTyxDQUFDLHFDQUFxQyxDQUFDLENBQUM7QUFDNUQsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUVKLHdCQUFTLENBQUMsVUFBVSxFQUFFLHdCQUFrQixDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRTtJQUN6RCxNQUFNLE1BQU0sR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLGFBQWEsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFOUUsdUNBQXVDO0lBQ3ZDLEVBQUU7SUFDRixnR0FBZ0c7SUFDaEcsZ0dBQWdHO0lBQ2hHLGdHQUFnRztJQUNoRyxnR0FBZ0c7SUFDaEcsZ0dBQWdHO0lBRWhHLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxTQUFTLENBQUMsaUJBQWlCLENBQUMsQ0FBQztJQUM1QyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsU0FBUyxDQUFDLGdCQUFnQixDQUFDLENBQUM7SUFDM0MsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLFNBQVMsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO0FBQ2hELENBQUMsQ0FBQyxDQUFDLENBQUM7QUFFSix3QkFBUyxDQUFDLGFBQWEsRUFBRSx3QkFBa0IsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7SUFDNUQsOEVBQThFO0lBQzlFLGlGQUFpRjtJQUNqRix1Q0FBdUM7SUFDdkMsTUFBTSxRQUFRLEdBQUcsTUFBTSxPQUFPLENBQUMsU0FBUyxDQUFDLG1CQUFtQixFQUFFLEVBQUUsYUFBYSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7SUFDeEYsTUFBTSxVQUFVLEdBQUcsTUFBTSxrQkFBa0IsRUFBRSxDQUFDO0lBRTlDLHlFQUF5RTtJQUN6RSxNQUFNLE9BQU8sQ0FBQyxTQUFTLENBQUMsbUJBQW1CLENBQUMsQ0FBQztJQUM3QyxNQUFNLFVBQVUsR0FBRyxNQUFNLGtCQUFrQixFQUFFLENBQUM7SUFDOUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBRS9ELHdFQUF3RTtJQUN4RSxNQUFNLE9BQU8sQ0FBQyxTQUFTLENBQUMsbUJBQW1CLEVBQUUsRUFBRSxPQUFPLEVBQUUsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDdkUsTUFBTSxVQUFVLEdBQUcsTUFBTSxrQkFBa0IsRUFBRSxDQUFDO0lBQzlDLE1BQU0sQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLENBQUM7SUFFbkUsdUVBQXVFO0lBQ3ZFLDJDQUEyQztJQUMzQyxNQUFNLE9BQU8sQ0FBQyxTQUFTLENBQUMsbUJBQW1CLEVBQUUsRUFBRSxPQUFPLEVBQUUsQ0FBQyxRQUFRLEVBQUUsV0FBVyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ25GLE1BQU0sVUFBVSxHQUFHLE1BQU0sa0JBQWtCLEVBQUUsQ0FBQztJQUM5QyxNQUFNLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBRW5FLEtBQUssVUFBVSxrQkFBa0I7O1FBQy9CLE1BQU0sUUFBUSxHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxjQUFjLENBQUMsZ0JBQWdCLEVBQUUsRUFBRSxTQUFTLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQztRQUM3RixJQUFJLFFBQUMsUUFBUSxDQUFDLE1BQU0sMENBQUcsQ0FBQyxFQUFDLEVBQUU7WUFBRSxNQUFNLElBQUksS0FBSyxDQUFDLGdDQUFnQyxDQUFDLENBQUM7U0FBRTtRQUNqRixPQUFPLENBQUMsR0FBRyxDQUFDLG9CQUFvQixNQUFBLFFBQVEsQ0FBQyxNQUFNLDBDQUFHLENBQUMsRUFBRSxXQUFXLEVBQUUsQ0FBQyxDQUFDO1FBQ3BFLGFBQU8sUUFBUSxDQUFDLE1BQU0sMENBQUcsQ0FBQyxFQUFFO0lBQzlCLENBQUM7QUFDSCxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBRUosd0JBQVMsQ0FBQyw2QkFBNkIsRUFBRSx3QkFBa0IsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7SUFDNUUsbUZBQW1GO0lBQ25GLE1BQU0sTUFBTSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLG1CQUFtQixDQUFDLENBQUM7QUFDakYsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUVKLHdCQUFTLENBQUMsK0JBQStCLEVBQUUsd0JBQWtCLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxFQUFFO0lBQzlFLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxFQUFFLGNBQWMsQ0FBQyxDQUFDO0lBRXhELE1BQU0sdUJBQXVCLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsa0JBQWtCLENBQUMsQ0FBQztJQUN6RSxLQUFLLE1BQU0sTUFBTSxJQUFJLE1BQU0sYUFBYSxDQUFDLHVCQUF1QixDQUFDLEVBQUU7UUFDakUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxZQUFZLE1BQU0sRUFBRSxDQUFDLENBQUM7UUFDbEMsTUFBTSxvQkFBYyxDQUFDLE1BQU0sRUFBRSxRQUFRLENBQUMsQ0FBQztRQUV2QyxnRUFBZ0U7UUFDaEUsNkRBQTZEO1FBQzdELE1BQU0sU0FBUyxHQUFHLE1BQU0sWUFBWSxDQUFDLFFBQVEsRUFBRSxRQUFRLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDdEcsS0FBSyxNQUFNLFFBQVEsSUFBSSxTQUFTLEVBQUU7WUFDaEMsTUFBTSxVQUFVLEdBQUcsUUFBUSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDaEQsTUFBTSxXQUFLLENBQUMsQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFLFFBQVEsRUFBRSxHQUFHLEVBQUUsVUFBVSxDQUFDLEVBQUU7Z0JBQ3pELEdBQUcsRUFBRSxRQUFRO2dCQUNiLE1BQU0sRUFBRSxPQUFPLENBQUMsTUFBTTtnQkFDdEIsTUFBTSxFQUFFO29CQUNOLFlBQVksRUFBRSxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFO29CQUN6QyxXQUFXLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNO2lCQUNoQzthQUNGLENBQUMsQ0FBQztTQUNKO1FBRUQseUNBQXlDO1FBQ3pDLE1BQU0sTUFBTSxHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQztZQUMvQixPQUFPLEVBQUUsUUFBUTtZQUNqQixJQUFJO1lBQ0osT0FBTztTQUNSLENBQUMsQ0FBQztRQUVILHlEQUF5RDtRQUN6RCxxRUFBcUU7UUFDckUsNENBQTRDO1FBQzVDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLGdCQUFnQixDQUFDLENBQUM7S0FDaEQ7QUFDSCxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBRUosd0JBQVMsQ0FBQyxpQ0FBaUMsRUFBRSx3QkFBa0IsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7SUFDaEYsTUFBTSxZQUFZLEdBQUcsR0FBRyxPQUFPLENBQUMsWUFBWSxnQkFBZ0IsQ0FBQztJQUM3RCxNQUFNLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLFlBQVksQ0FBQyxDQUFDLENBQUM7SUFFakQsMEZBQTBGO0lBQzFGLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7SUFDN0IsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxZQUFZLENBQUMsQ0FBQyxDQUFDO0lBRXZELGlGQUFpRjtJQUNqRixNQUFNLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxNQUFNLEVBQUUsU0FBUyxFQUFFLFlBQVksQ0FBQyxDQUFDLENBQUM7SUFFdkQsOENBQThDO0lBQzlDLHVGQUF1RjtJQUN2RixNQUFNLElBQUksR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsWUFBWSxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDcEYscUNBQXFDO0lBQ3JDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxTQUFTLENBQUMsR0FBRyxPQUFPLENBQUMsZUFBZSxTQUFTLENBQUMsQ0FBQztJQUM1RCxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsU0FBUyxDQUFDLEdBQUcsT0FBTyxDQUFDLGVBQWUsU0FBUyxDQUFDLENBQUM7SUFDNUQsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLFNBQVMsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxlQUFlLFNBQVMsQ0FBQyxDQUFDO0lBRTVELDhEQUE4RDtJQUM5RCxNQUFNLGFBQWEsR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxPQUFPLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUU7UUFDaEcsR0FBRyxFQUFFLFlBQVk7S0FDbEIsQ0FBQyxDQUFDO0lBQ0gsTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO0lBRWxELHNDQUFzQztJQUN0QyxNQUFNLE9BQU8sQ0FBQyxTQUFTLENBQUMsUUFBUSxFQUFFLEVBQUUsT0FBTyxFQUFFLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxFQUFFLEdBQUcsRUFBRSxZQUFZLEVBQUUsQ0FBQyxDQUFDO0lBRS9FLDhFQUE4RTtJQUM5RSw2RUFBNkU7SUFDN0UscUNBQXFDO0lBQ3JDLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsWUFBWSxFQUFFLFFBQVEsRUFBRSxtQkFBbUIsQ0FBQyxDQUFDO0lBQ3hGLE1BQU0sYUFBRSxDQUFDLE1BQU0sQ0FBQyxnQkFBZ0IsRUFBRSxHQUFHLGdCQUFnQixHQUFHLENBQUMsQ0FBQztJQUMxRCxJQUFJO1FBRUYscUVBQXFFO1FBQ3JFLE1BQU0sT0FBTyxDQUFDLFNBQVMsQ0FBQyx5QkFBeUIsRUFBRSxFQUFFLE9BQU8sRUFBRSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxHQUFHLEVBQUUsWUFBWSxFQUFFLENBQUMsQ0FBQztLQUVqRztZQUFTO1FBQ1IsbURBQW1EO1FBQ25ELE1BQU0sYUFBRSxDQUFDLE1BQU0sQ0FBQyxHQUFHLGdCQUFnQixHQUFHLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztLQUMzRDtBQUNILENBQUMsQ0FBQyxDQUFDLENBQUM7QUFFSix3QkFBUyxDQUFDLHdFQUF3RSxFQUFFLHdCQUFrQixDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRTtJQUN2SCxnRkFBZ0Y7SUFDaEYsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLDBCQUEwQixDQUFDLENBQUMsQ0FBQztJQUV6RCw2Q0FBNkM7SUFDN0MsTUFBTSxnQkFBZ0IsR0FBRyxNQUFNLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLEVBQUUsZ0NBQWdDLENBQUMsQ0FBQyxDQUFDO0lBRXhGLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLGdCQUFnQixDQUFDLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxDQUFDLFVBQVUsRUFBRSxDQUFDO0lBRXhFLHFDQUFxQztJQUNyQyxNQUFNLHNCQUFzQixHQUFHLE1BQU0sT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLEtBQUssRUFBRSw2REFBNkQsQ0FBQyxDQUFDLENBQUM7SUFFM0gsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsc0JBQXNCLENBQUMsQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUFDLENBQUMsVUFBVSxFQUFFLENBQUM7QUFDaEYsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUVKLEtBQUssVUFBVSxZQUFZLENBQUMsTUFBYyxFQUFFLElBQXFDO0lBQy9FLE1BQU0sR0FBRyxHQUFHLElBQUksS0FBSyxFQUFVLENBQUM7SUFDaEMsS0FBSyxNQUFNLEtBQUssSUFBSSxNQUFNLGFBQUUsQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUU7UUFDbkUsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7UUFDckQsSUFBSSxNQUFNLElBQUksQ0FBQyxRQUFRLENBQUMsRUFBRTtZQUN4QixHQUFHLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1NBQ3BCO0tBQ0Y7SUFDRCxPQUFPLEdBQUcsQ0FBQztBQUNiLENBQUM7QUFFRCxLQUFLLFVBQVUsYUFBYSxDQUFDLE1BQWM7SUFDekMsT0FBTyxZQUFZLENBQUMsTUFBTSxFQUFFLEtBQUssRUFBRSxRQUFnQixFQUFFLEVBQUUsQ0FBQyxDQUFDLE1BQU0sYUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7QUFDbkcsQ0FBQztBQUVELEtBQUssVUFBVSxZQUFZLENBQUMsT0FBb0IsRUFBRSxTQUFpQjtJQUNqRSxNQUFNLGFBQWEsR0FBRyxPQUFPLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ3ZELE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLFlBQVksRUFBRSxTQUFTLEVBQUUsR0FBRyxhQUFhLGdCQUFnQixDQUFDLENBQUM7SUFDbEcsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsTUFBTSxhQUFFLENBQUMsUUFBUSxDQUFDLFlBQVksRUFBRSxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztBQUN6RixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgcHJvbWlzZXMgYXMgZnMgfSBmcm9tICdmcyc7XG5pbXBvcnQgKiBhcyBvcyBmcm9tICdvcyc7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IHsgcmV0cnksIHNsZWVwIH0gZnJvbSAnLi4vaGVscGVycy9hd3MnO1xuaW1wb3J0IHsgY2xvbmVEaXJlY3RvcnksIHNoZWxsLCB3aXRoRGVmYXVsdEZpeHR1cmUsIFRlc3RGaXh0dXJlIH0gZnJvbSAnLi4vaGVscGVycy9jZGsnO1xuaW1wb3J0IHsgaW50ZWdUZXN0IH0gZnJvbSAnLi4vaGVscGVycy90ZXN0LWhlbHBlcnMnO1xuXG5qZXN0LnNldFRpbWVvdXQoNjAwICogMTAwMCk7XG5cbmludGVnVGVzdCgnVlBDIExvb2t1cCcsIHdpdGhEZWZhdWx0Rml4dHVyZShhc3luYyAoZml4dHVyZSkgPT4ge1xuICBmaXh0dXJlLmxvZygnTWFraW5nIHN1cmUgd2UgYXJlIGNsZWFuIGJlZm9yZSBzdGFydGluZy4nKTtcbiAgYXdhaXQgZml4dHVyZS5jZGtEZXN0cm95KCdkZWZpbmUtdnBjJywgeyBtb2RFbnY6IHsgRU5BQkxFX1ZQQ19URVNUSU5HOiAnREVGSU5FJyB9IH0pO1xuXG4gIGZpeHR1cmUubG9nKCdTZXR0aW5nIHVwOiBjcmVhdGluZyBhIFZQQyB3aXRoIGtub3duIHRhZ3MnKTtcbiAgYXdhaXQgZml4dHVyZS5jZGtEZXBsb3koJ2RlZmluZS12cGMnLCB7IG1vZEVudjogeyBFTkFCTEVfVlBDX1RFU1RJTkc6ICdERUZJTkUnIH0gfSk7XG4gIGZpeHR1cmUubG9nKCdTZXR1cCBjb21wbGV0ZSEnKTtcblxuICBmaXh0dXJlLmxvZygnVmVyaWZ5aW5nIHdlIGNhbiBub3cgaW1wb3J0IHRoYXQgVlBDJyk7XG4gIGF3YWl0IGZpeHR1cmUuY2RrRGVwbG95KCdpbXBvcnQtdnBjJywgeyBtb2RFbnY6IHsgRU5BQkxFX1ZQQ19URVNUSU5HOiAnSU1QT1JUJyB9IH0pO1xufSkpO1xuXG5pbnRlZ1Rlc3QoJ1R3byB3YXlzIG9mIHNob2luZyB0aGUgdmVyc2lvbicsIHdpdGhEZWZhdWx0Rml4dHVyZShhc3luYyAoZml4dHVyZSkgPT4ge1xuICBjb25zdCB2ZXJzaW9uMSA9IGF3YWl0IGZpeHR1cmUuY2RrKFsndmVyc2lvbiddLCB7IHZlcmJvc2U6IGZhbHNlIH0pO1xuICBjb25zdCB2ZXJzaW9uMiA9IGF3YWl0IGZpeHR1cmUuY2RrKFsnLS12ZXJzaW9uJ10sIHsgdmVyYm9zZTogZmFsc2UgfSk7XG5cbiAgZXhwZWN0KHZlcnNpb24xKS50b0VxdWFsKHZlcnNpb24yKTtcbn0pKTtcblxuaW50ZWdUZXN0KCdUZXJtaW5hdGlvbiBwcm90ZWN0aW9uJywgd2l0aERlZmF1bHRGaXh0dXJlKGFzeW5jIChmaXh0dXJlKSA9PiB7XG4gIGNvbnN0IHN0YWNrTmFtZSA9ICd0ZXJtaW5hdGlvbi1wcm90ZWN0aW9uJztcbiAgYXdhaXQgZml4dHVyZS5jZGtEZXBsb3koc3RhY2tOYW1lKTtcblxuICAvLyBUcnkgYSBkZXN0cm95IHRoYXQgc2hvdWxkIGZhaWxcbiAgYXdhaXQgZXhwZWN0KGZpeHR1cmUuY2RrRGVzdHJveShzdGFja05hbWUpKS5yZWplY3RzLnRvVGhyb3coJ2V4aXRlZCB3aXRoIGVycm9yJyk7XG5cbiAgLy8gQ2FuIHVwZGF0ZSB0ZXJtaW5hdGlvbiBwcm90ZWN0aW9uIGV2ZW4gdGhvdWdoIHRoZSBjaGFuZ2Ugc2V0IGRvZXNuJ3QgY29udGFpbiBjaGFuZ2VzXG4gIGF3YWl0IGZpeHR1cmUuY2RrRGVwbG95KHN0YWNrTmFtZSwgeyBtb2RFbnY6IHsgVEVSTUlOQVRJT05fUFJPVEVDVElPTjogJ0ZBTFNFJyB9IH0pO1xuICBhd2FpdCBmaXh0dXJlLmNka0Rlc3Ryb3koc3RhY2tOYW1lKTtcbn0pKTtcblxuaW50ZWdUZXN0KCdjZGsgc3ludGgnLCB3aXRoRGVmYXVsdEZpeHR1cmUoYXN5bmMgKGZpeHR1cmUpID0+IHtcbiAgYXdhaXQgZml4dHVyZS5jZGsoWydzeW50aCcsIGZpeHR1cmUuZnVsbFN0YWNrTmFtZSgndGVzdC0xJyldKTtcbiAgY29uc3QgdGVtcGxhdGUxID0gYXdhaXQgcmVhZFRlbXBsYXRlKGZpeHR1cmUsICd0ZXN0LTEnKTtcbiAgZXhwZWN0KHRlbXBsYXRlMSkudG9FcXVhbCh7XG4gICAgUmVzb3VyY2VzOiB7XG4gICAgICB0b3BpYzY5ODMxNDkxOiB7XG4gICAgICAgIFR5cGU6ICdBV1M6OlNOUzo6VG9waWMnLFxuICAgICAgICBNZXRhZGF0YToge1xuICAgICAgICAgICdhd3M6Y2RrOnBhdGgnOiBgJHtmaXh0dXJlLnN0YWNrTmFtZVByZWZpeH0tdGVzdC0xL3RvcGljL1Jlc291cmNlYCxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSxcbiAgfSk7XG5cbiAgYXdhaXQgZml4dHVyZS5jZGsoWydzeW50aCcsIGZpeHR1cmUuZnVsbFN0YWNrTmFtZSgndGVzdC0yJyldLCB7IHZlcmJvc2U6IGZhbHNlIH0pO1xuICBjb25zdCB0ZW1wbGF0ZTIgPSBhd2FpdCByZWFkVGVtcGxhdGUoZml4dHVyZSwgJ3Rlc3QtMicpO1xuICBleHBlY3QodGVtcGxhdGUyKS50b0VxdWFsKHtcbiAgICBSZXNvdXJjZXM6IHtcbiAgICAgIHRvcGljMTUyRDg0QTM3OiB7XG4gICAgICAgIFR5cGU6ICdBV1M6OlNOUzo6VG9waWMnLFxuICAgICAgICBNZXRhZGF0YToge1xuICAgICAgICAgICdhd3M6Y2RrOnBhdGgnOiBgJHtmaXh0dXJlLnN0YWNrTmFtZVByZWZpeH0tdGVzdC0yL3RvcGljMS9SZXNvdXJjZWAsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgdG9waWMyQTRGQjU0N0Y6IHtcbiAgICAgICAgVHlwZTogJ0FXUzo6U05TOjpUb3BpYycsXG4gICAgICAgIE1ldGFkYXRhOiB7XG4gICAgICAgICAgJ2F3czpjZGs6cGF0aCc6IGAke2ZpeHR1cmUuc3RhY2tOYW1lUHJlZml4fS10ZXN0LTIvdG9waWMyL1Jlc291cmNlYCxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSxcbiAgfSk7XG5cbn0pKTtcblxuaW50ZWdUZXN0KCdzc20gcGFyYW1ldGVyIHByb3ZpZGVyIGVycm9yJywgd2l0aERlZmF1bHRGaXh0dXJlKGFzeW5jIChmaXh0dXJlKSA9PiB7XG4gIGF3YWl0IGV4cGVjdChmaXh0dXJlLmNkayhbJ3N5bnRoJyxcbiAgICBmaXh0dXJlLmZ1bGxTdGFja05hbWUoJ21pc3Npbmctc3NtLXBhcmFtZXRlcicpLFxuICAgICctYycsICd0ZXN0OnNzbS1wYXJhbWV0ZXItbmFtZT0vZG9lcy9ub3QvZXhpc3QnXSwge1xuICAgIGFsbG93RXJyRXhpdDogdHJ1ZSxcbiAgfSkpLnJlc29sdmVzLnRvQ29udGFpbignU1NNIHBhcmFtZXRlciBub3QgYXZhaWxhYmxlIGluIGFjY291bnQnKTtcbn0pKTtcblxuaW50ZWdUZXN0KCdhdXRvbWF0aWMgb3JkZXJpbmcnLCB3aXRoRGVmYXVsdEZpeHR1cmUoYXN5bmMgKGZpeHR1cmUpID0+IHtcbiAgLy8gRGVwbG95IHRoZSBjb25zdW1pbmcgc3RhY2sgd2hpY2ggd2lsbCBpbmNsdWRlIHRoZSBwcm9kdWNpbmcgc3RhY2tcbiAgYXdhaXQgZml4dHVyZS5jZGtEZXBsb3koJ29yZGVyLWNvbnN1bWluZycpO1xuXG4gIC8vIERlc3Ryb3kgdGhlIHByb3ZpZGluZyBzdGFjayB3aGljaCB3aWxsIGluY2x1ZGUgdGhlIGNvbnN1bWluZyBzdGFja1xuICBhd2FpdCBmaXh0dXJlLmNka0Rlc3Ryb3koJ29yZGVyLXByb3ZpZGluZycpO1xufSkpO1xuXG5pbnRlZ1Rlc3QoJ2NvbnRleHQgc2V0dGluZycsIHdpdGhEZWZhdWx0Rml4dHVyZShhc3luYyAoZml4dHVyZSkgPT4ge1xuICBhd2FpdCBmcy53cml0ZUZpbGUocGF0aC5qb2luKGZpeHR1cmUuaW50ZWdUZXN0RGlyLCAnY2RrLmNvbnRleHQuanNvbicpLCBKU09OLnN0cmluZ2lmeSh7XG4gICAgY29udGV4dGtleTogJ3RoaXMgaXMgdGhlIGNvbnRleHQgdmFsdWUnLFxuICB9KSk7XG4gIHRyeSB7XG4gICAgYXdhaXQgZXhwZWN0KGZpeHR1cmUuY2RrKFsnY29udGV4dCddKSkucmVzb2x2ZXMudG9Db250YWluKCd0aGlzIGlzIHRoZSBjb250ZXh0IHZhbHVlJyk7XG5cbiAgICAvLyBUZXN0IHRoYXQgZGVsZXRpbmcgdGhlIGNvbnRleHRrZXkgd29ya3NcbiAgICBhd2FpdCBmaXh0dXJlLmNkayhbJ2NvbnRleHQnLCAnLS1yZXNldCcsICdjb250ZXh0a2V5J10pO1xuICAgIGF3YWl0IGV4cGVjdChmaXh0dXJlLmNkayhbJ2NvbnRleHQnXSkpLnJlc29sdmVzLm5vdC50b0NvbnRhaW4oJ3RoaXMgaXMgdGhlIGNvbnRleHQgdmFsdWUnKTtcblxuICAgIC8vIFRlc3QgdGhhdCBmb3JjZWQgZGVsZXRlIG9mIHRoZSBjb250ZXh0IGtleSBkb2VzIG5vdCB0aHJvd1xuICAgIGF3YWl0IGZpeHR1cmUuY2RrKFsnY29udGV4dCcsICctZicsICctLXJlc2V0JywgJ2NvbnRleHRrZXknXSk7XG5cbiAgfSBmaW5hbGx5IHtcbiAgICBhd2FpdCBmcy51bmxpbmsocGF0aC5qb2luKGZpeHR1cmUuaW50ZWdUZXN0RGlyLCAnY2RrLmNvbnRleHQuanNvbicpKTtcbiAgfVxufSkpO1xuXG5pbnRlZ1Rlc3QoJ2NvbnRleHQgaW4gc3RhZ2UgcHJvcGFnYXRlcyB0byB0b3AnLCB3aXRoRGVmYXVsdEZpeHR1cmUoYXN5bmMgKGZpeHR1cmUpID0+IHtcbiAgYXdhaXQgZXhwZWN0KGZpeHR1cmUuY2RrU3ludGgoe1xuICAgIC8vIFRoaXMgd2lsbCBtYWtlIGl0IGVycm9yIHRvIHByb3ZlIHRoYXQgdGhlIGNvbnRleHQgYnViYmxlcyB1cCwgYW5kIGFsc28gdGhhdCB3ZSBjYW4gZmFpbCBvbiBjb21tYW5kXG4gICAgb3B0aW9uczogWyctLW5vLWxvb2t1cHMnXSxcbiAgICBtb2RFbnY6IHtcbiAgICAgIElOVEVHX1NUQUNLX1NFVDogJ3N0YWdlLXVzaW5nLWNvbnRleHQnLFxuICAgIH0sXG4gICAgYWxsb3dFcnJFeGl0OiB0cnVlLFxuICB9KSkucmVzb2x2ZXMudG9Db250YWluKCdDb250ZXh0IGxvb2t1cHMgaGF2ZSBiZWVuIGRpc2FibGVkJyk7XG59KSk7XG5cbmludGVnVGVzdCgnZGVwbG95Jywgd2l0aERlZmF1bHRGaXh0dXJlKGFzeW5jIChmaXh0dXJlKSA9PiB7XG4gIGNvbnN0IHN0YWNrQXJuID0gYXdhaXQgZml4dHVyZS5jZGtEZXBsb3koJ3Rlc3QtMicsIHsgY2FwdHVyZVN0ZGVycjogZmFsc2UgfSk7XG5cbiAgLy8gdmVyaWZ5IHRoZSBudW1iZXIgb2YgcmVzb3VyY2VzIGluIHRoZSBzdGFja1xuICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZpeHR1cmUuYXdzLmNsb3VkRm9ybWF0aW9uKCdkZXNjcmliZVN0YWNrUmVzb3VyY2VzJywge1xuICAgIFN0YWNrTmFtZTogc3RhY2tBcm4sXG4gIH0pO1xuICBleHBlY3QocmVzcG9uc2UuU3RhY2tSZXNvdXJjZXM/Lmxlbmd0aCkudG9FcXVhbCgyKTtcbn0pKTtcblxuaW50ZWdUZXN0KCdkZXBsb3kgYWxsJywgd2l0aERlZmF1bHRGaXh0dXJlKGFzeW5jIChmaXh0dXJlKSA9PiB7XG4gIGNvbnN0IGFybnMgPSBhd2FpdCBmaXh0dXJlLmNka0RlcGxveSgndGVzdC0qJywgeyBjYXB0dXJlU3RkZXJyOiBmYWxzZSB9KTtcblxuICAvLyB2ZXJpZnkgdGhhdCB3ZSBvbmx5IGRlcGxveWVkIGEgc2luZ2xlIHN0YWNrICh0aGVyZSdzIGEgc2luZ2xlIEFSTiBpbiB0aGUgb3V0cHV0KVxuICBleHBlY3QoYXJucy5zcGxpdCgnXFxuJykubGVuZ3RoKS50b0VxdWFsKDIpO1xufSkpO1xuXG5pbnRlZ1Rlc3QoJ25lc3RlZCBzdGFjayB3aXRoIHBhcmFtZXRlcnMnLCB3aXRoRGVmYXVsdEZpeHR1cmUoYXN5bmMgKGZpeHR1cmUpID0+IHtcbiAgLy8gU1RBQ0tfTkFNRV9QUkVGSVggaXMgdXNlZCBpbiBNeVRvcGljUGFyYW0gdG8gYWxsb3cgbXVsdGlwbGUgaW5zdGFuY2VzXG4gIC8vIG9mIHRoaXMgdGVzdCB0byBydW4gaW4gcGFyYWxsZWwsIG90aGV3aXNlIHRoZXkgd2lsbCBhdHRlbXB0IHRvIGNyZWF0ZSB0aGUgc2FtZSBTTlMgdG9waWMuXG4gIGNvbnN0IHN0YWNrQXJuID0gYXdhaXQgZml4dHVyZS5jZGtEZXBsb3koJ3dpdGgtbmVzdGVkLXN0YWNrLXVzaW5nLXBhcmFtZXRlcnMnLCB7XG4gICAgb3B0aW9uczogWyctLXBhcmFtZXRlcnMnLCBgTXlUb3BpY1BhcmFtPSR7Zml4dHVyZS5zdGFja05hbWVQcmVmaXh9VGhlcmVJc05vU3Bvb25gXSxcbiAgICBjYXB0dXJlU3RkZXJyOiBmYWxzZSxcbiAgfSk7XG5cbiAgLy8gdmVyaWZ5IHRoYXQgd2Ugb25seSBkZXBsb3llZCBhIHNpbmdsZSBzdGFjayAodGhlcmUncyBhIHNpbmdsZSBBUk4gaW4gdGhlIG91dHB1dClcbiAgZXhwZWN0KHN0YWNrQXJuLnNwbGl0KCdcXG4nKS5sZW5ndGgpLnRvRXF1YWwoMSk7XG5cbiAgLy8gdmVyaWZ5IHRoZSBudW1iZXIgb2YgcmVzb3VyY2VzIGluIHRoZSBzdGFja1xuICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZpeHR1cmUuYXdzLmNsb3VkRm9ybWF0aW9uKCdkZXNjcmliZVN0YWNrUmVzb3VyY2VzJywge1xuICAgIFN0YWNrTmFtZTogc3RhY2tBcm4sXG4gIH0pO1xuICBleHBlY3QocmVzcG9uc2UuU3RhY2tSZXNvdXJjZXM/Lmxlbmd0aCkudG9FcXVhbCgxKTtcbn0pKTtcblxuaW50ZWdUZXN0KCdkZXBsb3kgd2l0aG91dCBleGVjdXRlIGEgbmFtZWQgY2hhbmdlIHNldCcsIHdpdGhEZWZhdWx0Rml4dHVyZShhc3luYyAoZml4dHVyZSkgPT4ge1xuICBjb25zdCBjaGFuZ2VTZXROYW1lID0gJ2N1c3RvbS1jaGFuZ2Utc2V0LW5hbWUnO1xuICBjb25zdCBzdGFja0FybiA9IGF3YWl0IGZpeHR1cmUuY2RrRGVwbG95KCd0ZXN0LTInLCB7XG4gICAgb3B0aW9uczogWyctLW5vLWV4ZWN1dGUnLCAnLS1jaGFuZ2Utc2V0LW5hbWUnLCBjaGFuZ2VTZXROYW1lXSxcbiAgICBjYXB0dXJlU3RkZXJyOiBmYWxzZSxcbiAgfSk7XG4gIC8vIHZlcmlmeSB0aGF0IHdlIG9ubHkgZGVwbG95ZWQgYSBzaW5nbGUgc3RhY2sgKHRoZXJlJ3MgYSBzaW5nbGUgQVJOIGluIHRoZSBvdXRwdXQpXG4gIGV4cGVjdChzdGFja0Fybi5zcGxpdCgnXFxuJykubGVuZ3RoKS50b0VxdWFsKDEpO1xuXG4gIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZml4dHVyZS5hd3MuY2xvdWRGb3JtYXRpb24oJ2Rlc2NyaWJlU3RhY2tzJywge1xuICAgIFN0YWNrTmFtZTogc3RhY2tBcm4sXG4gIH0pO1xuICBleHBlY3QocmVzcG9uc2UuU3RhY2tzPy5bMF0uU3RhY2tTdGF0dXMpLnRvRXF1YWwoJ1JFVklFV19JTl9QUk9HUkVTUycpO1xuXG4gIC8vdmVyaWZ5IGEgY2hhbmdlIHNldCB3YXMgY3JlYXRlZCB3aXRoIHRoZSBwcm92aWRlZCBuYW1lXG4gIGNvbnN0IGNoYW5nZVNldFJlc3BvbnNlID0gYXdhaXQgZml4dHVyZS5hd3MuY2xvdWRGb3JtYXRpb24oJ2xpc3RDaGFuZ2VTZXRzJywge1xuICAgIFN0YWNrTmFtZTogc3RhY2tBcm4sXG4gIH0pO1xuICBjb25zdCBjaGFuZ2VTZXRzID0gY2hhbmdlU2V0UmVzcG9uc2UuU3VtbWFyaWVzIHx8IFtdO1xuICBleHBlY3QoY2hhbmdlU2V0cy5sZW5ndGgpLnRvRXF1YWwoMSk7XG4gIGV4cGVjdChjaGFuZ2VTZXRzWzBdLkNoYW5nZVNldE5hbWUpLnRvRXF1YWwoY2hhbmdlU2V0TmFtZSk7XG4gIGV4cGVjdChjaGFuZ2VTZXRzWzBdLlN0YXR1cykudG9FcXVhbCgnQ1JFQVRFX0NPTVBMRVRFJyk7XG59KSk7XG5cbmludGVnVGVzdCgnc2VjdXJpdHkgcmVsYXRlZCBjaGFuZ2VzIHdpdGhvdXQgYSBDTEkgYXJlIGV4cGVjdGVkIHRvIGZhaWwnLCB3aXRoRGVmYXVsdEZpeHR1cmUoYXN5bmMgKGZpeHR1cmUpID0+IHtcbiAgLy8gcmVkaXJlY3QgL2Rldi9udWxsIHRvIHN0ZGluLCB3aGljaCBtZWFucyB0aGVyZSB3aWxsIG5vdCBiZSB0dHkgYXR0YWNoZWRcbiAgLy8gc2luY2UgdGhpcyBzdGFjayBpbmNsdWRlcyBzZWN1cml0eS1yZWxhdGVkIGNoYW5nZXMsIHRoZSBkZXBsb3ltZW50IHNob3VsZFxuICAvLyBpbW1lZGlhdGVseSBmYWlsIGJlY2F1c2Ugd2UgY2FuJ3QgY29uZmlybSB0aGUgY2hhbmdlc1xuICBjb25zdCBzdGFja05hbWUgPSAnaWFtLXRlc3QnO1xuICBhd2FpdCBleHBlY3QoZml4dHVyZS5jZGtEZXBsb3koc3RhY2tOYW1lLCB7XG4gICAgb3B0aW9uczogWyc8JywgJy9kZXYvbnVsbCddLCAvLyBINHgsIHRoaXMgb25seSB3b3JrcyBiZWNhdXNlIEkgaGFwcGVuIHRvIGtub3cgd2UgcGFzcyBzaGVsbDogdHJ1ZS5cbiAgICBuZXZlclJlcXVpcmVBcHByb3ZhbDogZmFsc2UsXG4gIH0pKS5yZWplY3RzLnRvVGhyb3coJ2V4aXRlZCB3aXRoIGVycm9yJyk7XG5cbiAgLy8gRW5zdXJlIHN0YWNrIHdhcyBub3QgZGVwbG95ZWRcbiAgYXdhaXQgZXhwZWN0KGZpeHR1cmUuYXdzLmNsb3VkRm9ybWF0aW9uKCdkZXNjcmliZVN0YWNrcycsIHtcbiAgICBTdGFja05hbWU6IGZpeHR1cmUuZnVsbFN0YWNrTmFtZShzdGFja05hbWUpLFxuICB9KSkucmVqZWN0cy50b1Rocm93KCdkb2VzIG5vdCBleGlzdCcpO1xufSkpO1xuXG5pbnRlZ1Rlc3QoJ2RlcGxveSB3aWxkY2FyZCB3aXRoIG91dHB1dHMnLCB3aXRoRGVmYXVsdEZpeHR1cmUoYXN5bmMgKGZpeHR1cmUpID0+IHtcbiAgY29uc3Qgb3V0cHV0c0ZpbGUgPSBwYXRoLmpvaW4oZml4dHVyZS5pbnRlZ1Rlc3REaXIsICdvdXRwdXRzJywgJ291dHB1dHMuanNvbicpO1xuICBhd2FpdCBmcy5ta2RpcihwYXRoLmRpcm5hbWUob3V0cHV0c0ZpbGUpLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcblxuICBhd2FpdCBmaXh0dXJlLmNka0RlcGxveShbJ291dHB1dHMtdGVzdC0qJ10sIHtcbiAgICBvcHRpb25zOiBbJy0tb3V0cHV0cy1maWxlJywgb3V0cHV0c0ZpbGVdLFxuICB9KTtcblxuICBjb25zdCBvdXRwdXRzID0gSlNPTi5wYXJzZSgoYXdhaXQgZnMucmVhZEZpbGUob3V0cHV0c0ZpbGUsIHsgZW5jb2Rpbmc6ICd1dGYtOCcgfSkpLnRvU3RyaW5nKCkpO1xuICBleHBlY3Qob3V0cHV0cykudG9FcXVhbCh7XG4gICAgW2Ake2ZpeHR1cmUuc3RhY2tOYW1lUHJlZml4fS1vdXRwdXRzLXRlc3QtMWBdOiB7XG4gICAgICBUb3BpY05hbWU6IGAke2ZpeHR1cmUuc3RhY2tOYW1lUHJlZml4fS1vdXRwdXRzLXRlc3QtMU15VG9waWNgLFxuICAgIH0sXG4gICAgW2Ake2ZpeHR1cmUuc3RhY2tOYW1lUHJlZml4fS1vdXRwdXRzLXRlc3QtMmBdOiB7XG4gICAgICBUb3BpY05hbWU6IGAke2ZpeHR1cmUuc3RhY2tOYW1lUHJlZml4fS1vdXRwdXRzLXRlc3QtMk15T3RoZXJUb3BpY2AsXG4gICAgfSxcbiAgfSk7XG59KSk7XG5cbmludGVnVGVzdCgnZGVwbG95IHdpdGggcGFyYW1ldGVycycsIHdpdGhEZWZhdWx0Rml4dHVyZShhc3luYyAoZml4dHVyZSkgPT4ge1xuICBjb25zdCBzdGFja0FybiA9IGF3YWl0IGZpeHR1cmUuY2RrRGVwbG95KCdwYXJhbS10ZXN0LTEnLCB7XG4gICAgb3B0aW9uczogW1xuICAgICAgJy0tcGFyYW1ldGVycycsIGBUb3BpY05hbWVQYXJhbT0ke2ZpeHR1cmUuc3RhY2tOYW1lUHJlZml4fWJhemluZ2FgLFxuICAgIF0sXG4gICAgY2FwdHVyZVN0ZGVycjogZmFsc2UsXG4gIH0pO1xuXG4gIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZml4dHVyZS5hd3MuY2xvdWRGb3JtYXRpb24oJ2Rlc2NyaWJlU3RhY2tzJywge1xuICAgIFN0YWNrTmFtZTogc3RhY2tBcm4sXG4gIH0pO1xuXG4gIGV4cGVjdChyZXNwb25zZS5TdGFja3M/LlswXS5QYXJhbWV0ZXJzKS50b0VxdWFsKFtcbiAgICB7XG4gICAgICBQYXJhbWV0ZXJLZXk6ICdUb3BpY05hbWVQYXJhbScsXG4gICAgICBQYXJhbWV0ZXJWYWx1ZTogYCR7Zml4dHVyZS5zdGFja05hbWVQcmVmaXh9YmF6aW5nYWAsXG4gICAgfSxcbiAgXSk7XG59KSk7XG5cbmludGVnVGVzdCgndXBkYXRlIHRvIHN0YWNrIGluIFJPTExCQUNLX0NPTVBMRVRFIHN0YXRlIHdpbGwgZGVsZXRlIHN0YWNrIGFuZCBjcmVhdGUgYSBuZXcgb25lJywgd2l0aERlZmF1bHRGaXh0dXJlKGFzeW5jIChmaXh0dXJlKSA9PiB7XG4gIC8vIEdJVkVOXG4gIGF3YWl0IGV4cGVjdChmaXh0dXJlLmNka0RlcGxveSgncGFyYW0tdGVzdC0xJywge1xuICAgIG9wdGlvbnM6IFtcbiAgICAgICctLXBhcmFtZXRlcnMnLCBgVG9waWNOYW1lUGFyYW09JHtmaXh0dXJlLnN0YWNrTmFtZVByZWZpeH1AYXd3YCxcbiAgICBdLFxuICAgIGNhcHR1cmVTdGRlcnI6IGZhbHNlLFxuICB9KSkucmVqZWN0cy50b1Rocm93KCdleGl0ZWQgd2l0aCBlcnJvcicpO1xuXG4gIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZml4dHVyZS5hd3MuY2xvdWRGb3JtYXRpb24oJ2Rlc2NyaWJlU3RhY2tzJywge1xuICAgIFN0YWNrTmFtZTogZml4dHVyZS5mdWxsU3RhY2tOYW1lKCdwYXJhbS10ZXN0LTEnKSxcbiAgfSk7XG5cbiAgY29uc3Qgc3RhY2tBcm4gPSByZXNwb25zZS5TdGFja3M/LlswXS5TdGFja0lkO1xuICBleHBlY3QocmVzcG9uc2UuU3RhY2tzPy5bMF0uU3RhY2tTdGF0dXMpLnRvRXF1YWwoJ1JPTExCQUNLX0NPTVBMRVRFJyk7XG5cbiAgLy8gV0hFTlxuICBjb25zdCBuZXdTdGFja0FybiA9IGF3YWl0IGZpeHR1cmUuY2RrRGVwbG95KCdwYXJhbS10ZXN0LTEnLCB7XG4gICAgb3B0aW9uczogW1xuICAgICAgJy0tcGFyYW1ldGVycycsIGBUb3BpY05hbWVQYXJhbT0ke2ZpeHR1cmUuc3RhY2tOYW1lUHJlZml4fWFsbGdvb2RgLFxuICAgIF0sXG4gICAgY2FwdHVyZVN0ZGVycjogZmFsc2UsXG4gIH0pO1xuXG4gIGNvbnN0IG5ld1N0YWNrUmVzcG9uc2UgPSBhd2FpdCBmaXh0dXJlLmF3cy5jbG91ZEZvcm1hdGlvbignZGVzY3JpYmVTdGFja3MnLCB7XG4gICAgU3RhY2tOYW1lOiBuZXdTdGFja0FybixcbiAgfSk7XG5cbiAgLy8gVEhFTlxuICBleHBlY3QgKHN0YWNrQXJuKS5ub3QudG9FcXVhbChuZXdTdGFja0Fybik7IC8vIG5ldyBzdGFjayB3YXMgY3JlYXRlZFxuICBleHBlY3QobmV3U3RhY2tSZXNwb25zZS5TdGFja3M/LlswXS5TdGFja1N0YXR1cykudG9FcXVhbCgnQ1JFQVRFX0NPTVBMRVRFJyk7XG4gIGV4cGVjdChuZXdTdGFja1Jlc3BvbnNlLlN0YWNrcz8uWzBdLlBhcmFtZXRlcnMpLnRvRXF1YWwoW1xuICAgIHtcbiAgICAgIFBhcmFtZXRlcktleTogJ1RvcGljTmFtZVBhcmFtJyxcbiAgICAgIFBhcmFtZXRlclZhbHVlOiBgJHtmaXh0dXJlLnN0YWNrTmFtZVByZWZpeH1hbGxnb29kYCxcbiAgICB9LFxuICBdKTtcbn0pKTtcblxuaW50ZWdUZXN0KCdzdGFjayBpbiBVUERBVEVfUk9MTEJBQ0tfQ09NUExFVEUgc3RhdGUgY2FuIGJlIHVwZGF0ZWQnLCB3aXRoRGVmYXVsdEZpeHR1cmUoYXN5bmMgKGZpeHR1cmUpID0+IHtcbiAgLy8gR0lWRU5cbiAgY29uc3Qgc3RhY2tBcm4gPSBhd2FpdCBmaXh0dXJlLmNka0RlcGxveSgncGFyYW0tdGVzdC0xJywge1xuICAgIG9wdGlvbnM6IFtcbiAgICAgICctLXBhcmFtZXRlcnMnLCBgVG9waWNOYW1lUGFyYW09JHtmaXh0dXJlLnN0YWNrTmFtZVByZWZpeH1uaWNlYCxcbiAgICBdLFxuICAgIGNhcHR1cmVTdGRlcnI6IGZhbHNlLFxuICB9KTtcblxuICBsZXQgcmVzcG9uc2UgPSBhd2FpdCBmaXh0dXJlLmF3cy5jbG91ZEZvcm1hdGlvbignZGVzY3JpYmVTdGFja3MnLCB7XG4gICAgU3RhY2tOYW1lOiBzdGFja0FybixcbiAgfSk7XG5cbiAgZXhwZWN0KHJlc3BvbnNlLlN0YWNrcz8uWzBdLlN0YWNrU3RhdHVzKS50b0VxdWFsKCdDUkVBVEVfQ09NUExFVEUnKTtcblxuICAvLyBiYWQgcGFyYW1ldGVyIG5hbWUgd2l0aCBAIHdpbGwgcHV0IHN0YWNrIGludG8gVVBEQVRFX1JPTExCQUNLX0NPTVBMRVRFXG4gIGF3YWl0IGV4cGVjdChmaXh0dXJlLmNka0RlcGxveSgncGFyYW0tdGVzdC0xJywge1xuICAgIG9wdGlvbnM6IFtcbiAgICAgICctLXBhcmFtZXRlcnMnLCBgVG9waWNOYW1lUGFyYW09JHtmaXh0dXJlLnN0YWNrTmFtZVByZWZpeH1AYXd3YCxcbiAgICBdLFxuICAgIGNhcHR1cmVTdGRlcnI6IGZhbHNlLFxuICB9KSkucmVqZWN0cy50b1Rocm93KCdleGl0ZWQgd2l0aCBlcnJvcicpOztcblxuICByZXNwb25zZSA9IGF3YWl0IGZpeHR1cmUuYXdzLmNsb3VkRm9ybWF0aW9uKCdkZXNjcmliZVN0YWNrcycsIHtcbiAgICBTdGFja05hbWU6IHN0YWNrQXJuLFxuICB9KTtcblxuICBleHBlY3QocmVzcG9uc2UuU3RhY2tzPy5bMF0uU3RhY2tTdGF0dXMpLnRvRXF1YWwoJ1VQREFURV9ST0xMQkFDS19DT01QTEVURScpO1xuXG4gIC8vIFdIRU5cbiAgYXdhaXQgZml4dHVyZS5jZGtEZXBsb3koJ3BhcmFtLXRlc3QtMScsIHtcbiAgICBvcHRpb25zOiBbXG4gICAgICAnLS1wYXJhbWV0ZXJzJywgYFRvcGljTmFtZVBhcmFtPSR7Zml4dHVyZS5zdGFja05hbWVQcmVmaXh9YWxsZ29vZGAsXG4gICAgXSxcbiAgICBjYXB0dXJlU3RkZXJyOiBmYWxzZSxcbiAgfSk7XG5cbiAgcmVzcG9uc2UgPSBhd2FpdCBmaXh0dXJlLmF3cy5jbG91ZEZvcm1hdGlvbignZGVzY3JpYmVTdGFja3MnLCB7XG4gICAgU3RhY2tOYW1lOiBzdGFja0FybixcbiAgfSk7XG5cbiAgLy8gVEhFTlxuICBleHBlY3QocmVzcG9uc2UuU3RhY2tzPy5bMF0uU3RhY2tTdGF0dXMpLnRvRXF1YWwoJ1VQREFURV9DT01QTEVURScpO1xuICBleHBlY3QocmVzcG9uc2UuU3RhY2tzPy5bMF0uUGFyYW1ldGVycykudG9FcXVhbChbXG4gICAge1xuICAgICAgUGFyYW1ldGVyS2V5OiAnVG9waWNOYW1lUGFyYW0nLFxuICAgICAgUGFyYW1ldGVyVmFsdWU6IGAke2ZpeHR1cmUuc3RhY2tOYW1lUHJlZml4fWFsbGdvb2RgLFxuICAgIH0sXG4gIF0pO1xufSkpO1xuXG5pbnRlZ1Rlc3QoJ2RlcGxveSB3aXRoIHdpbGRjYXJkIGFuZCBwYXJhbWV0ZXJzJywgd2l0aERlZmF1bHRGaXh0dXJlKGFzeW5jIChmaXh0dXJlKSA9PiB7XG4gIGF3YWl0IGZpeHR1cmUuY2RrRGVwbG95KCdwYXJhbS10ZXN0LSonLCB7XG4gICAgb3B0aW9uczogW1xuICAgICAgJy0tcGFyYW1ldGVycycsIGAke2ZpeHR1cmUuc3RhY2tOYW1lUHJlZml4fS1wYXJhbS10ZXN0LTE6VG9waWNOYW1lUGFyYW09JHtmaXh0dXJlLnN0YWNrTmFtZVByZWZpeH1iYXppbmdhYCxcbiAgICAgICctLXBhcmFtZXRlcnMnLCBgJHtmaXh0dXJlLnN0YWNrTmFtZVByZWZpeH0tcGFyYW0tdGVzdC0yOk90aGVyVG9waWNOYW1lUGFyYW09JHtmaXh0dXJlLnN0YWNrTmFtZVByZWZpeH1UaGF0c015U3BvdGAsXG4gICAgICAnLS1wYXJhbWV0ZXJzJywgYCR7Zml4dHVyZS5zdGFja05hbWVQcmVmaXh9LXBhcmFtLXRlc3QtMzpEaXNwbGF5TmFtZVBhcmFtPSR7Zml4dHVyZS5zdGFja05hbWVQcmVmaXh9SGV5VGhlcmVgLFxuICAgICAgJy0tcGFyYW1ldGVycycsIGAke2ZpeHR1cmUuc3RhY2tOYW1lUHJlZml4fS1wYXJhbS10ZXN0LTM6T3RoZXJEaXNwbGF5TmFtZVBhcmFtPSR7Zml4dHVyZS5zdGFja05hbWVQcmVmaXh9QW5vdGhlck9uZWAsXG4gICAgXSxcbiAgfSk7XG59KSk7XG5cbmludGVnVGVzdCgnZGVwbG95IHdpdGggcGFyYW1ldGVycyBtdWx0aScsIHdpdGhEZWZhdWx0Rml4dHVyZShhc3luYyAoZml4dHVyZSkgPT4ge1xuICBjb25zdCBwYXJhbVZhbDEgPSBgJHtmaXh0dXJlLnN0YWNrTmFtZVByZWZpeH1iYXppbmdhYDtcbiAgY29uc3QgcGFyYW1WYWwyID0gYCR7Zml4dHVyZS5zdGFja05hbWVQcmVmaXh9PWphZ3NoZW1hc2hgO1xuXG4gIGNvbnN0IHN0YWNrQXJuID0gYXdhaXQgZml4dHVyZS5jZGtEZXBsb3koJ3BhcmFtLXRlc3QtMycsIHtcbiAgICBvcHRpb25zOiBbXG4gICAgICAnLS1wYXJhbWV0ZXJzJywgYERpc3BsYXlOYW1lUGFyYW09JHtwYXJhbVZhbDF9YCxcbiAgICAgICctLXBhcmFtZXRlcnMnLCBgT3RoZXJEaXNwbGF5TmFtZVBhcmFtPSR7cGFyYW1WYWwyfWAsXG4gICAgXSxcbiAgICBjYXB0dXJlU3RkZXJyOiBmYWxzZSxcbiAgfSk7XG5cbiAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmaXh0dXJlLmF3cy5jbG91ZEZvcm1hdGlvbignZGVzY3JpYmVTdGFja3MnLCB7XG4gICAgU3RhY2tOYW1lOiBzdGFja0FybixcbiAgfSk7XG5cbiAgZXhwZWN0KHJlc3BvbnNlLlN0YWNrcz8uWzBdLlBhcmFtZXRlcnMpLnRvRXF1YWwoW1xuICAgIHtcbiAgICAgIFBhcmFtZXRlcktleTogJ0Rpc3BsYXlOYW1lUGFyYW0nLFxuICAgICAgUGFyYW1ldGVyVmFsdWU6IHBhcmFtVmFsMSxcbiAgICB9LFxuICAgIHtcbiAgICAgIFBhcmFtZXRlcktleTogJ090aGVyRGlzcGxheU5hbWVQYXJhbScsXG4gICAgICBQYXJhbWV0ZXJWYWx1ZTogcGFyYW1WYWwyLFxuICAgIH0sXG4gIF0pO1xufSkpO1xuXG5pbnRlZ1Rlc3QoJ2RlcGxveSB3aXRoIG5vdGlmaWNhdGlvbiBBUk4nLCB3aXRoRGVmYXVsdEZpeHR1cmUoYXN5bmMgKGZpeHR1cmUpID0+IHtcbiAgY29uc3QgdG9waWNOYW1lID0gYCR7Zml4dHVyZS5zdGFja05hbWVQcmVmaXh9LXRlc3QtdG9waWNgO1xuXG4gIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZml4dHVyZS5hd3Muc25zKCdjcmVhdGVUb3BpYycsIHsgTmFtZTogdG9waWNOYW1lIH0pO1xuICBjb25zdCB0b3BpY0FybiA9IHJlc3BvbnNlLlRvcGljQXJuITtcbiAgdHJ5IHtcbiAgICBhd2FpdCBmaXh0dXJlLmNka0RlcGxveSgndGVzdC0yJywge1xuICAgICAgb3B0aW9uczogWyctLW5vdGlmaWNhdGlvbi1hcm5zJywgdG9waWNBcm5dLFxuICAgIH0pO1xuXG4gICAgLy8gdmVyaWZ5IHRoYXQgdGhlIHN0YWNrIHdlIGRlcGxveWVkIGhhcyBvdXIgbm90aWZpY2F0aW9uIEFSTlxuICAgIGNvbnN0IGRlc2NyaWJlUmVzcG9uc2UgPSBhd2FpdCBmaXh0dXJlLmF3cy5jbG91ZEZvcm1hdGlvbignZGVzY3JpYmVTdGFja3MnLCB7XG4gICAgICBTdGFja05hbWU6IGZpeHR1cmUuZnVsbFN0YWNrTmFtZSgndGVzdC0yJyksXG4gICAgfSk7XG4gICAgZXhwZWN0KGRlc2NyaWJlUmVzcG9uc2UuU3RhY2tzPy5bMF0uTm90aWZpY2F0aW9uQVJOcykudG9FcXVhbChbdG9waWNBcm5dKTtcbiAgfSBmaW5hbGx5IHtcbiAgICBhd2FpdCBmaXh0dXJlLmF3cy5zbnMoJ2RlbGV0ZVRvcGljJywge1xuICAgICAgVG9waWNBcm46IHRvcGljQXJuLFxuICAgIH0pO1xuICB9XG59KSk7XG5cbmludGVnVGVzdCgnZGVwbG95IHdpdGggcm9sZScsIHdpdGhEZWZhdWx0Rml4dHVyZShhc3luYyAoZml4dHVyZSkgPT4ge1xuICBjb25zdCByb2xlTmFtZSA9IGAke2ZpeHR1cmUuc3RhY2tOYW1lUHJlZml4fS10ZXN0LXJvbGVgO1xuXG4gIGF3YWl0IGRlbGV0ZVJvbGUoKTtcblxuICBjb25zdCBjcmVhdGVSZXNwb25zZSA9IGF3YWl0IGZpeHR1cmUuYXdzLmlhbSgnY3JlYXRlUm9sZScsIHtcbiAgICBSb2xlTmFtZTogcm9sZU5hbWUsXG4gICAgQXNzdW1lUm9sZVBvbGljeURvY3VtZW50OiBKU09OLnN0cmluZ2lmeSh7XG4gICAgICBWZXJzaW9uOiAnMjAxMi0xMC0xNycsXG4gICAgICBTdGF0ZW1lbnQ6IFt7XG4gICAgICAgIEFjdGlvbjogJ3N0czpBc3N1bWVSb2xlJyxcbiAgICAgICAgUHJpbmNpcGFsOiB7IFNlcnZpY2U6ICdjbG91ZGZvcm1hdGlvbi5hbWF6b25hd3MuY29tJyB9LFxuICAgICAgICBFZmZlY3Q6ICdBbGxvdycsXG4gICAgICB9LCB7XG4gICAgICAgIEFjdGlvbjogJ3N0czpBc3N1bWVSb2xlJyxcbiAgICAgICAgUHJpbmNpcGFsOiB7IEFXUzogKGF3YWl0IGZpeHR1cmUuYXdzLnN0cygnZ2V0Q2FsbGVySWRlbnRpdHknLCB7fSkpLkFybiB9LFxuICAgICAgICBFZmZlY3Q6ICdBbGxvdycsXG4gICAgICB9XSxcbiAgICB9KSxcbiAgfSk7XG4gIGNvbnN0IHJvbGVBcm4gPSBjcmVhdGVSZXNwb25zZS5Sb2xlLkFybjtcbiAgdHJ5IHtcbiAgICBhd2FpdCBmaXh0dXJlLmF3cy5pYW0oJ3B1dFJvbGVQb2xpY3knLCB7XG4gICAgICBSb2xlTmFtZTogcm9sZU5hbWUsXG4gICAgICBQb2xpY3lOYW1lOiAnRGVmYXVsdFBvbGljeScsXG4gICAgICBQb2xpY3lEb2N1bWVudDogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICBWZXJzaW9uOiAnMjAxMi0xMC0xNycsXG4gICAgICAgIFN0YXRlbWVudDogW3tcbiAgICAgICAgICBBY3Rpb246ICcqJyxcbiAgICAgICAgICBSZXNvdXJjZTogJyonLFxuICAgICAgICAgIEVmZmVjdDogJ0FsbG93JyxcbiAgICAgICAgfV0sXG4gICAgICB9KSxcbiAgICB9KTtcblxuICAgIGF3YWl0IHJldHJ5KGZpeHR1cmUub3V0cHV0LCAnVHJ5aW5nIHRvIGFzc3VtZSBmcmVzaCByb2xlJywgcmV0cnkuZm9yU2Vjb25kcygzMDApLCBhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCBmaXh0dXJlLmF3cy5zdHMoJ2Fzc3VtZVJvbGUnLCB7XG4gICAgICAgIFJvbGVBcm46IHJvbGVBcm4sXG4gICAgICAgIFJvbGVTZXNzaW9uTmFtZTogJ3Rlc3RpbmcnLFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAvLyBJbiBwcmluY2lwbGUsIHRoZSByb2xlIGhhcyByZXBsaWNhdGVkIGZyb20gJ3VzLWVhc3QtMScgdG8gd2hlcmV2ZXIgd2UncmUgdGVzdGluZy5cbiAgICAvLyBHaXZlIGl0IGEgbGl0dGxlIG1vcmUgc2xlZXAgdG8gbWFrZSBzdXJlIENsb3VkRm9ybWF0aW9uIGlzIG5vdCBoaXR0aW5nIGEgYm94XG4gICAgLy8gdGhhdCBkb2Vzbid0IGhhdmUgaXQgeWV0LlxuICAgIGF3YWl0IHNsZWVwKDUwMDApO1xuXG4gICAgYXdhaXQgZml4dHVyZS5jZGtEZXBsb3koJ3Rlc3QtMicsIHtcbiAgICAgIG9wdGlvbnM6IFsnLS1yb2xlLWFybicsIHJvbGVBcm5dLFxuICAgIH0pO1xuXG4gICAgLy8gSW1tZWRpYXRlbHkgZGVsZXRlIHRoZSBzdGFjayBhZ2FpbiBiZWZvcmUgd2UgZGVsZXRlIHRoZSByb2xlLlxuICAgIC8vXG4gICAgLy8gU2luY2Ugcm9sZXMgYXJlIHN0aWNreSwgaWYgd2UgZGVsZXRlIHRoZSByb2xlIGJlZm9yZSB0aGUgc3RhY2ssIHN1YnNlcXVlbnQgRGVsZXRlU3RhY2tcbiAgICAvLyBvcGVyYXRpb25zIHdpbGwgZmFpbCB3aGVuIENsb3VkRm9ybWF0aW9uIHRyaWVzIHRvIGFzc3VtZSB0aGUgcm9sZSB0aGF0J3MgYWxyZWFkeSBnb25lLlxuICAgIGF3YWl0IGZpeHR1cmUuY2RrRGVzdHJveSgndGVzdC0yJyk7XG5cbiAgfSBmaW5hbGx5IHtcbiAgICBhd2FpdCBkZWxldGVSb2xlKCk7XG4gIH1cblxuICBhc3luYyBmdW5jdGlvbiBkZWxldGVSb2xlKCkge1xuICAgIHRyeSB7XG4gICAgICBmb3IgKGNvbnN0IHBvbGljeU5hbWUgb2YgKGF3YWl0IGZpeHR1cmUuYXdzLmlhbSgnbGlzdFJvbGVQb2xpY2llcycsIHsgUm9sZU5hbWU6IHJvbGVOYW1lIH0pKS5Qb2xpY3lOYW1lcykge1xuICAgICAgICBhd2FpdCBmaXh0dXJlLmF3cy5pYW0oJ2RlbGV0ZVJvbGVQb2xpY3knLCB7XG4gICAgICAgICAgUm9sZU5hbWU6IHJvbGVOYW1lLFxuICAgICAgICAgIFBvbGljeU5hbWU6IHBvbGljeU5hbWUsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgYXdhaXQgZml4dHVyZS5hd3MuaWFtKCdkZWxldGVSb2xlJywgeyBSb2xlTmFtZTogcm9sZU5hbWUgfSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKGUubWVzc2FnZS5pbmRleE9mKCdjYW5ub3QgYmUgZm91bmQnKSA+IC0xKSB7IHJldHVybjsgfVxuICAgICAgdGhyb3cgZTtcbiAgICB9XG4gIH1cbn0pKTtcblxuaW50ZWdUZXN0KCdjZGsgZGlmZicsIHdpdGhEZWZhdWx0Rml4dHVyZShhc3luYyAoZml4dHVyZSkgPT4ge1xuICBjb25zdCBkaWZmMSA9IGF3YWl0IGZpeHR1cmUuY2RrKFsnZGlmZicsIGZpeHR1cmUuZnVsbFN0YWNrTmFtZSgndGVzdC0xJyldKTtcbiAgZXhwZWN0KGRpZmYxKS50b0NvbnRhaW4oJ0FXUzo6U05TOjpUb3BpYycpO1xuXG4gIGNvbnN0IGRpZmYyID0gYXdhaXQgZml4dHVyZS5jZGsoWydkaWZmJywgZml4dHVyZS5mdWxsU3RhY2tOYW1lKCd0ZXN0LTInKV0pO1xuICBleHBlY3QoZGlmZjIpLnRvQ29udGFpbignQVdTOjpTTlM6OlRvcGljJyk7XG5cbiAgLy8gV2UgY2FuIG1ha2UgaXQgZmFpbCBieSBwYXNzaW5nIC0tZmFpbFxuICBhd2FpdCBleHBlY3QoZml4dHVyZS5jZGsoWydkaWZmJywgJy0tZmFpbCcsIGZpeHR1cmUuZnVsbFN0YWNrTmFtZSgndGVzdC0xJyldKSlcbiAgICAucmVqZWN0cy50b1Rocm93KCdleGl0ZWQgd2l0aCBlcnJvcicpO1xufSkpO1xuXG5pbnRlZ1Rlc3QoJ2NkayBkaWZmIC0tZmFpbCBvbiBtdWx0aXBsZSBzdGFja3MgZXhpdHMgd2l0aCBlcnJvciBpZiBhbnkgb2YgdGhlIHN0YWNrcyBjb250YWlucyBhIGRpZmYnLCB3aXRoRGVmYXVsdEZpeHR1cmUoYXN5bmMgKGZpeHR1cmUpID0+IHtcbiAgLy8gR0lWRU5cbiAgY29uc3QgZGlmZjEgPSBhd2FpdCBmaXh0dXJlLmNkayhbJ2RpZmYnLCBmaXh0dXJlLmZ1bGxTdGFja05hbWUoJ3Rlc3QtMScpXSk7XG4gIGV4cGVjdChkaWZmMSkudG9Db250YWluKCdBV1M6OlNOUzo6VG9waWMnKTtcblxuICBhd2FpdCBmaXh0dXJlLmNka0RlcGxveSgndGVzdC0yJyk7XG4gIGNvbnN0IGRpZmYyID0gYXdhaXQgZml4dHVyZS5jZGsoWydkaWZmJywgZml4dHVyZS5mdWxsU3RhY2tOYW1lKCd0ZXN0LTInKV0pO1xuICBleHBlY3QoZGlmZjIpLnRvQ29udGFpbignVGhlcmUgd2VyZSBubyBkaWZmZXJlbmNlcycpO1xuXG4gIC8vIFdIRU4gLyBUSEVOXG4gIGF3YWl0IGV4cGVjdChmaXh0dXJlLmNkayhbJ2RpZmYnLCAnLS1mYWlsJywgZml4dHVyZS5mdWxsU3RhY2tOYW1lKCd0ZXN0LTEnKSwgZml4dHVyZS5mdWxsU3RhY2tOYW1lKCd0ZXN0LTInKV0pKS5yZWplY3RzLnRvVGhyb3coJ2V4aXRlZCB3aXRoIGVycm9yJyk7XG59KSk7XG5cbmludGVnVGVzdCgnY2RrIGRpZmYgLS1mYWlsIHdpdGggbXVsdGlwbGUgc3RhY2sgZXhpdHMgd2l0aCBpZiBhbnkgb2YgdGhlIHN0YWNrcyBjb250YWlucyBhIGRpZmYnLCB3aXRoRGVmYXVsdEZpeHR1cmUoYXN5bmMgKGZpeHR1cmUpID0+IHtcbiAgLy8gR0lWRU5cbiAgYXdhaXQgZml4dHVyZS5jZGtEZXBsb3koJ3Rlc3QtMScpO1xuICBjb25zdCBkaWZmMSA9IGF3YWl0IGZpeHR1cmUuY2RrKFsnZGlmZicsIGZpeHR1cmUuZnVsbFN0YWNrTmFtZSgndGVzdC0xJyldKTtcbiAgZXhwZWN0KGRpZmYxKS50b0NvbnRhaW4oJ1RoZXJlIHdlcmUgbm8gZGlmZmVyZW5jZXMnKTtcblxuICBjb25zdCBkaWZmMiA9IGF3YWl0IGZpeHR1cmUuY2RrKFsnZGlmZicsIGZpeHR1cmUuZnVsbFN0YWNrTmFtZSgndGVzdC0yJyldKTtcbiAgZXhwZWN0KGRpZmYyKS50b0NvbnRhaW4oJ0FXUzo6U05TOjpUb3BpYycpO1xuXG4gIC8vIFdIRU4gLyBUSEVOXG4gIGF3YWl0IGV4cGVjdChmaXh0dXJlLmNkayhbJ2RpZmYnLCAnLS1mYWlsJywgZml4dHVyZS5mdWxsU3RhY2tOYW1lKCd0ZXN0LTEnKSwgZml4dHVyZS5mdWxsU3RhY2tOYW1lKCd0ZXN0LTInKV0pKS5yZWplY3RzLnRvVGhyb3coJ2V4aXRlZCB3aXRoIGVycm9yJyk7XG59KSk7XG5cbmludGVnVGVzdCgnY2RrIGRpZmYgLS1zZWN1cml0eS1vbmx5IC0tZmFpbCBleGl0cyB3aGVuIHNlY3VyaXR5IGNoYW5nZXMgYXJlIHByZXNlbnQnLCB3aXRoRGVmYXVsdEZpeHR1cmUoYXN5bmMgKGZpeHR1cmUpID0+IHtcbiAgY29uc3Qgc3RhY2tOYW1lID0gJ2lhbS10ZXN0JztcbiAgYXdhaXQgZXhwZWN0KGZpeHR1cmUuY2RrKFsnZGlmZicsICctLXNlY3VyaXR5LW9ubHknLCAnLS1mYWlsJywgZml4dHVyZS5mdWxsU3RhY2tOYW1lKHN0YWNrTmFtZSldKSkucmVqZWN0cy50b1Rocm93KCdleGl0ZWQgd2l0aCBlcnJvcicpO1xufSkpO1xuXG5pbnRlZ1Rlc3QoJ2RlcGxveSBzdGFjayB3aXRoIGRvY2tlciBhc3NldCcsIHdpdGhEZWZhdWx0Rml4dHVyZShhc3luYyAoZml4dHVyZSkgPT4ge1xuICBhd2FpdCBmaXh0dXJlLmNka0RlcGxveSgnZG9ja2VyJyk7XG59KSk7XG5cbmludGVnVGVzdCgnZGVwbG95IGFuZCB0ZXN0IHN0YWNrIHdpdGggbGFtYmRhIGFzc2V0Jywgd2l0aERlZmF1bHRGaXh0dXJlKGFzeW5jIChmaXh0dXJlKSA9PiB7XG4gIGNvbnN0IHN0YWNrQXJuID0gYXdhaXQgZml4dHVyZS5jZGtEZXBsb3koJ2xhbWJkYScsIHsgY2FwdHVyZVN0ZGVycjogZmFsc2UgfSk7XG5cbiAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmaXh0dXJlLmF3cy5jbG91ZEZvcm1hdGlvbignZGVzY3JpYmVTdGFja3MnLCB7XG4gICAgU3RhY2tOYW1lOiBzdGFja0FybixcbiAgfSk7XG4gIGNvbnN0IGxhbWJkYUFybiA9IHJlc3BvbnNlLlN0YWNrcz8uWzBdLk91dHB1dHM/LlswXS5PdXRwdXRWYWx1ZTtcbiAgaWYgKGxhbWJkYUFybiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdTdGFjayBkaWQgbm90IGhhdmUgZXhwZWN0ZWQgTGFtYmRhIEFSTiBvdXRwdXQnKTtcbiAgfVxuXG4gIGNvbnN0IG91dHB1dCA9IGF3YWl0IGZpeHR1cmUuYXdzLmxhbWJkYSgnaW52b2tlJywge1xuICAgIEZ1bmN0aW9uTmFtZTogbGFtYmRhQXJuLFxuICB9KTtcblxuICBleHBlY3QoSlNPTi5zdHJpbmdpZnkob3V0cHV0LlBheWxvYWQpKS50b0NvbnRhaW4oJ2RlYXIgYXNzZXQnKTtcbn0pKTtcblxuaW50ZWdUZXN0KCdjZGsgbHMnLCB3aXRoRGVmYXVsdEZpeHR1cmUoYXN5bmMgKGZpeHR1cmUpID0+IHtcbiAgY29uc3QgbGlzdGluZyA9IGF3YWl0IGZpeHR1cmUuY2RrKFsnbHMnXSwgeyBjYXB0dXJlU3RkZXJyOiBmYWxzZSB9KTtcblxuICBjb25zdCBleHBlY3RlZFN0YWNrcyA9IFtcbiAgICAnY29uZGl0aW9uYWwtcmVzb3VyY2UnLFxuICAgICdkb2NrZXInLFxuICAgICdkb2NrZXItd2l0aC1jdXN0b20tZmlsZScsXG4gICAgJ2ZhaWxlZCcsXG4gICAgJ2lhbS10ZXN0JyxcbiAgICAnbGFtYmRhJyxcbiAgICAnbWlzc2luZy1zc20tcGFyYW1ldGVyJyxcbiAgICAnb3JkZXItcHJvdmlkaW5nJyxcbiAgICAnb3V0cHV0cy10ZXN0LTEnLFxuICAgICdvdXRwdXRzLXRlc3QtMicsXG4gICAgJ3BhcmFtLXRlc3QtMScsXG4gICAgJ3BhcmFtLXRlc3QtMicsXG4gICAgJ3BhcmFtLXRlc3QtMycsXG4gICAgJ3Rlcm1pbmF0aW9uLXByb3RlY3Rpb24nLFxuICAgICd0ZXN0LTEnLFxuICAgICd0ZXN0LTInLFxuICAgICd3aXRoLW5lc3RlZC1zdGFjaycsXG4gICAgJ3dpdGgtbmVzdGVkLXN0YWNrLXVzaW5nLXBhcmFtZXRlcnMnLFxuICAgICdvcmRlci1jb25zdW1pbmcnLFxuICBdO1xuXG4gIGZvciAoY29uc3Qgc3RhY2sgb2YgZXhwZWN0ZWRTdGFja3MpIHtcbiAgICBleHBlY3QobGlzdGluZykudG9Db250YWluKGZpeHR1cmUuZnVsbFN0YWNrTmFtZShzdGFjaykpO1xuICB9XG59KSk7XG5cbmludGVnVGVzdCgnc3ludGhpbmcgYSBzdGFnZSB3aXRoIGVycm9ycyBsZWFkcyB0byBmYWlsdXJlJywgd2l0aERlZmF1bHRGaXh0dXJlKGFzeW5jIChmaXh0dXJlKSA9PiB7XG4gIGNvbnN0IG91dHB1dCA9IGF3YWl0IGZpeHR1cmUuY2RrKFsnc3ludGgnXSwge1xuICAgIGFsbG93RXJyRXhpdDogdHJ1ZSxcbiAgICBtb2RFbnY6IHtcbiAgICAgIElOVEVHX1NUQUNLX1NFVDogJ3N0YWdlLXdpdGgtZXJyb3JzJyxcbiAgICB9LFxuICB9KTtcblxuICBleHBlY3Qob3V0cHV0KS50b0NvbnRhaW4oJ1RoaXMgaXMgYW4gZXJyb3InKTtcbn0pKTtcblxuaW50ZWdUZXN0KCdzeW50aGluZyBhIHN0YWdlIHdpdGggZXJyb3JzIGNhbiBiZSBzdXBwcmVzc2VkJywgd2l0aERlZmF1bHRGaXh0dXJlKGFzeW5jIChmaXh0dXJlKSA9PiB7XG4gIGF3YWl0IGZpeHR1cmUuY2RrKFsnc3ludGgnLCAnLS1uby12YWxpZGF0aW9uJ10sIHtcbiAgICBtb2RFbnY6IHtcbiAgICAgIElOVEVHX1NUQUNLX1NFVDogJ3N0YWdlLXdpdGgtZXJyb3JzJyxcbiAgICB9LFxuICB9KTtcbn0pKTtcblxuaW50ZWdUZXN0KCdkZXBsb3kgc3RhY2sgd2l0aG91dCByZXNvdXJjZScsIHdpdGhEZWZhdWx0Rml4dHVyZShhc3luYyAoZml4dHVyZSkgPT4ge1xuICAvLyBEZXBsb3kgdGhlIHN0YWNrIHdpdGhvdXQgcmVzb3VyY2VzXG4gIGF3YWl0IGZpeHR1cmUuY2RrRGVwbG95KCdjb25kaXRpb25hbC1yZXNvdXJjZScsIHsgbW9kRW52OiB7IE5PX1JFU09VUkNFOiAnVFJVRScgfSB9KTtcblxuICAvLyBUaGlzIHNob3VsZCBoYXZlIHN1Y2NlZWRlZCBidXQgbm90IGRlcGxveWVkIHRoZSBzdGFjay5cbiAgYXdhaXQgZXhwZWN0KGZpeHR1cmUuYXdzLmNsb3VkRm9ybWF0aW9uKCdkZXNjcmliZVN0YWNrcycsIHsgU3RhY2tOYW1lOiBmaXh0dXJlLmZ1bGxTdGFja05hbWUoJ2NvbmRpdGlvbmFsLXJlc291cmNlJykgfSkpXG4gICAgLnJlamVjdHMudG9UaHJvdygnY29uZGl0aW9uYWwtcmVzb3VyY2UgZG9lcyBub3QgZXhpc3QnKTtcblxuICAvLyBEZXBsb3kgdGhlIHN0YWNrIHdpdGggcmVzb3VyY2VzXG4gIGF3YWl0IGZpeHR1cmUuY2RrRGVwbG95KCdjb25kaXRpb25hbC1yZXNvdXJjZScpO1xuXG4gIC8vIFRoZW4gYWdhaW4gV0lUSE9VVCByZXNvdXJjZXMgKHRoaXMgc2hvdWxkIGRlc3Ryb3kgdGhlIHN0YWNrKVxuICBhd2FpdCBmaXh0dXJlLmNka0RlcGxveSgnY29uZGl0aW9uYWwtcmVzb3VyY2UnLCB7IG1vZEVudjogeyBOT19SRVNPVVJDRTogJ1RSVUUnIH0gfSk7XG5cbiAgYXdhaXQgZXhwZWN0KGZpeHR1cmUuYXdzLmNsb3VkRm9ybWF0aW9uKCdkZXNjcmliZVN0YWNrcycsIHsgU3RhY2tOYW1lOiBmaXh0dXJlLmZ1bGxTdGFja05hbWUoJ2NvbmRpdGlvbmFsLXJlc291cmNlJykgfSkpXG4gICAgLnJlamVjdHMudG9UaHJvdygnY29uZGl0aW9uYWwtcmVzb3VyY2UgZG9lcyBub3QgZXhpc3QnKTtcbn0pKTtcblxuaW50ZWdUZXN0KCdJQU0gZGlmZicsIHdpdGhEZWZhdWx0Rml4dHVyZShhc3luYyAoZml4dHVyZSkgPT4ge1xuICBjb25zdCBvdXRwdXQgPSBhd2FpdCBmaXh0dXJlLmNkayhbJ2RpZmYnLCBmaXh0dXJlLmZ1bGxTdGFja05hbWUoJ2lhbS10ZXN0JyldKTtcblxuICAvLyBSb3VnaGx5IGNoZWNrIGZvciBhIHRhYmxlIGxpa2UgdGhpczpcbiAgLy9cbiAgLy8g4pSM4pSA4pSA4pSA4pSs4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSs4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSs4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSs4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSALeKUgOKUgOKUrOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUkFxuICAvLyDilIIgICDilIIgUmVzb3VyY2UgICAgICAgIOKUgiBFZmZlY3Qg4pSCIEFjdGlvbiAgICAgICAgIOKUgiBQcmluY2lwYWwgICAgICAgICAgICAgICAgICAgICDilIIgQ29uZGl0aW9uIOKUglxuICAvLyDilJzilIDilIDilIDilLzilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilLzilIDilIDilIDilIDilIDilIDilIDilIDilLzilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilLzilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilLzilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilKRcbiAgLy8g4pSCICsg4pSCICR7U29tZVJvbGUuQXJufSDilIIgQWxsb3cgIOKUgiBzdHM6QXNzdW1lUm9sZSDilIIgU2VydmljZTplYzIuYW1hem9uYXdzLmNvbSAgICAg4pSCICAgICAgICAgICDilIJcbiAgLy8g4pSU4pSA4pSA4pSA4pS04pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pS04pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pS04pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pS04pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pS04pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSYXG5cbiAgZXhwZWN0KG91dHB1dCkudG9Db250YWluKCcke1NvbWVSb2xlLkFybn0nKTtcbiAgZXhwZWN0KG91dHB1dCkudG9Db250YWluKCdzdHM6QXNzdW1lUm9sZScpO1xuICBleHBlY3Qob3V0cHV0KS50b0NvbnRhaW4oJ2VjMi5hbWF6b25hd3MuY29tJyk7XG59KSk7XG5cbmludGVnVGVzdCgnZmFzdCBkZXBsb3knLCB3aXRoRGVmYXVsdEZpeHR1cmUoYXN5bmMgKGZpeHR1cmUpID0+IHtcbiAgLy8gd2UgYXJlIHVzaW5nIGEgc3RhY2sgd2l0aCBhIG5lc3RlZCBzdGFjayBiZWNhdXNlIENGTiB3aWxsIGFsd2F5cyBhdHRlbXB0IHRvXG4gIC8vIHVwZGF0ZSBhIG5lc3RlZCBzdGFjaywgd2hpY2ggd2lsbCBhbGxvdyB1cyB0byB2ZXJpZnkgdGhhdCB1cGRhdGVzIGFyZSBhY3R1YWxseVxuICAvLyBza2lwcGVkIHVubGVzcyAtLWZvcmNlIGlzIHNwZWNpZmllZC5cbiAgY29uc3Qgc3RhY2tBcm4gPSBhd2FpdCBmaXh0dXJlLmNka0RlcGxveSgnd2l0aC1uZXN0ZWQtc3RhY2snLCB7IGNhcHR1cmVTdGRlcnI6IGZhbHNlIH0pO1xuICBjb25zdCBjaGFuZ2VTZXQxID0gYXdhaXQgZ2V0TGF0ZXN0Q2hhbmdlU2V0KCk7XG5cbiAgLy8gRGVwbG95IHRoZSBzYW1lIHN0YWNrIGFnYWluLCB0aGVyZSBzaG91bGQgYmUgbm8gbmV3IGNoYW5nZSBzZXQgY3JlYXRlZFxuICBhd2FpdCBmaXh0dXJlLmNka0RlcGxveSgnd2l0aC1uZXN0ZWQtc3RhY2snKTtcbiAgY29uc3QgY2hhbmdlU2V0MiA9IGF3YWl0IGdldExhdGVzdENoYW5nZVNldCgpO1xuICBleHBlY3QoY2hhbmdlU2V0Mi5DaGFuZ2VTZXRJZCkudG9FcXVhbChjaGFuZ2VTZXQxLkNoYW5nZVNldElkKTtcblxuICAvLyBEZXBsb3kgdGhlIHN0YWNrIGFnYWluIHdpdGggLS1mb3JjZSwgbm93IHdlIHNob3VsZCBjcmVhdGUgYSBjaGFuZ2VzZXRcbiAgYXdhaXQgZml4dHVyZS5jZGtEZXBsb3koJ3dpdGgtbmVzdGVkLXN0YWNrJywgeyBvcHRpb25zOiBbJy0tZm9yY2UnXSB9KTtcbiAgY29uc3QgY2hhbmdlU2V0MyA9IGF3YWl0IGdldExhdGVzdENoYW5nZVNldCgpO1xuICBleHBlY3QoY2hhbmdlU2V0My5DaGFuZ2VTZXRJZCkubm90LnRvRXF1YWwoY2hhbmdlU2V0Mi5DaGFuZ2VTZXRJZCk7XG5cbiAgLy8gRGVwbG95IHRoZSBzdGFjayBhZ2FpbiB3aXRoIHRhZ3MsIGV4cGVjdGVkIHRvIGNyZWF0ZSBhIG5ldyBjaGFuZ2VzZXRcbiAgLy8gZXZlbiB0aG91Z2ggdGhlIHJlc291cmNlcyBkaWRuJ3QgY2hhbmdlLlxuICBhd2FpdCBmaXh0dXJlLmNka0RlcGxveSgnd2l0aC1uZXN0ZWQtc3RhY2snLCB7IG9wdGlvbnM6IFsnLS10YWdzJywgJ2tleT12YWx1ZSddIH0pO1xuICBjb25zdCBjaGFuZ2VTZXQ0ID0gYXdhaXQgZ2V0TGF0ZXN0Q2hhbmdlU2V0KCk7XG4gIGV4cGVjdChjaGFuZ2VTZXQ0LkNoYW5nZVNldElkKS5ub3QudG9FcXVhbChjaGFuZ2VTZXQzLkNoYW5nZVNldElkKTtcblxuICBhc3luYyBmdW5jdGlvbiBnZXRMYXRlc3RDaGFuZ2VTZXQoKSB7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmaXh0dXJlLmF3cy5jbG91ZEZvcm1hdGlvbignZGVzY3JpYmVTdGFja3MnLCB7IFN0YWNrTmFtZTogc3RhY2tBcm4gfSk7XG4gICAgaWYgKCFyZXNwb25zZS5TdGFja3M/LlswXSkgeyB0aHJvdyBuZXcgRXJyb3IoJ0RpZCBub3QgZ2V0IGEgQ2hhbmdlU2V0IGF0IGFsbCcpOyB9XG4gICAgZml4dHVyZS5sb2coYEZvdW5kIENoYW5nZSBTZXQgJHtyZXNwb25zZS5TdGFja3M/LlswXS5DaGFuZ2VTZXRJZH1gKTtcbiAgICByZXR1cm4gcmVzcG9uc2UuU3RhY2tzPy5bMF07XG4gIH1cbn0pKTtcblxuaW50ZWdUZXN0KCdmYWlsZWQgZGVwbG95IGRvZXMgbm90IGhhbmcnLCB3aXRoRGVmYXVsdEZpeHR1cmUoYXN5bmMgKGZpeHR1cmUpID0+IHtcbiAgLy8gdGhpcyB3aWxsIGhhbmcgaWYgd2UgaW50cm9kdWNlIGh0dHBzOi8vZ2l0aHViLmNvbS9hd3MvYXdzLWNkay9pc3N1ZXMvNjQwMyBhZ2Fpbi5cbiAgYXdhaXQgZXhwZWN0KGZpeHR1cmUuY2RrRGVwbG95KCdmYWlsZWQnKSkucmVqZWN0cy50b1Rocm93KCdleGl0ZWQgd2l0aCBlcnJvcicpO1xufSkpO1xuXG5pbnRlZ1Rlc3QoJ2NhbiBzdGlsbCBsb2FkIG9sZCBhc3NlbWJsaWVzJywgd2l0aERlZmF1bHRGaXh0dXJlKGFzeW5jIChmaXh0dXJlKSA9PiB7XG4gIGNvbnN0IGN4QXNtRGlyID0gcGF0aC5qb2luKG9zLnRtcGRpcigpLCAnY2RrLWludGVnLWN4Jyk7XG5cbiAgY29uc3QgdGVzdEFzc2VtYmxpZXNEaXJlY3RvcnkgPSBwYXRoLmpvaW4oX19kaXJuYW1lLCAnY2xvdWQtYXNzZW1ibGllcycpO1xuICBmb3IgKGNvbnN0IGFzbWRpciBvZiBhd2FpdCBsaXN0Q2hpbGREaXJzKHRlc3RBc3NlbWJsaWVzRGlyZWN0b3J5KSkge1xuICAgIGZpeHR1cmUubG9nKGBBU1NFTUJMWSAke2FzbWRpcn1gKTtcbiAgICBhd2FpdCBjbG9uZURpcmVjdG9yeShhc21kaXIsIGN4QXNtRGlyKTtcblxuICAgIC8vIFNvbWUgZmlsZXMgaW4gdGhlIGFzbSBkaXJlY3RvcnkgdGhhdCBoYXZlIGEgLmpzIGV4dGVuc2lvbiBhcmVcbiAgICAvLyBhY3R1YWxseSB0cmVhdGVkIGFzIHRlbXBsYXRlcy4gRXZhbHVhdGUgdGhlbSB1c2luZyBOb2RlSlMuXG4gICAgY29uc3QgdGVtcGxhdGVzID0gYXdhaXQgbGlzdENoaWxkcmVuKGN4QXNtRGlyLCBmdWxsUGF0aCA9PiBQcm9taXNlLnJlc29sdmUoZnVsbFBhdGguZW5kc1dpdGgoJy5qcycpKSk7XG4gICAgZm9yIChjb25zdCB0ZW1wbGF0ZSBvZiB0ZW1wbGF0ZXMpIHtcbiAgICAgIGNvbnN0IHRhcmdldE5hbWUgPSB0ZW1wbGF0ZS5yZXBsYWNlKC8uanMkLywgJycpO1xuICAgICAgYXdhaXQgc2hlbGwoW3Byb2Nlc3MuZXhlY1BhdGgsIHRlbXBsYXRlLCAnPicsIHRhcmdldE5hbWVdLCB7XG4gICAgICAgIGN3ZDogY3hBc21EaXIsXG4gICAgICAgIG91dHB1dDogZml4dHVyZS5vdXRwdXQsXG4gICAgICAgIG1vZEVudjoge1xuICAgICAgICAgIFRFU1RfQUNDT1VOVDogYXdhaXQgZml4dHVyZS5hd3MuYWNjb3VudCgpLFxuICAgICAgICAgIFRFU1RfUkVHSU9OOiBmaXh0dXJlLmF3cy5yZWdpb24sXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBVc2UgdGhpcyBkaXJlY3RvcnkgYXMgYSBDbG91ZCBBc3NlbWJseVxuICAgIGNvbnN0IG91dHB1dCA9IGF3YWl0IGZpeHR1cmUuY2RrKFtcbiAgICAgICctLWFwcCcsIGN4QXNtRGlyLFxuICAgICAgJy12JyxcbiAgICAgICdzeW50aCcsXG4gICAgXSk7XG5cbiAgICAvLyBBc3NlcnQgdGhhdCB0aGVyZSB3YXMgbm8gcHJvdmlkZXJFcnJvciBpbiBDREsncyBzdGRlcnJcbiAgICAvLyBCZWNhdXNlIHdlIHJlbHkgb24gdGhlIGFwcC9mcmFtZXdvcmsgdG8gYWN0dWFsbHkgZXJyb3IgaW4gY2FzZSB0aGVcbiAgICAvLyBwcm92aWRlciBmYWlscywgd2UgaW5zcGVjdCB0aGUgbG9ncyBoZXJlLlxuICAgIGV4cGVjdChvdXRwdXQpLm5vdC50b0NvbnRhaW4oJyRwcm92aWRlckVycm9yJyk7XG4gIH1cbn0pKTtcblxuaW50ZWdUZXN0KCdnZW5lcmF0aW5nIGFuZCBsb2FkaW5nIGFzc2VtYmx5Jywgd2l0aERlZmF1bHRGaXh0dXJlKGFzeW5jIChmaXh0dXJlKSA9PiB7XG4gIGNvbnN0IGFzbU91dHB1dERpciA9IGAke2ZpeHR1cmUuaW50ZWdUZXN0RGlyfS1jZGstaW50ZWctYXNtYDtcbiAgYXdhaXQgZml4dHVyZS5zaGVsbChbJ3JtJywgJy1yZicsIGFzbU91dHB1dERpcl0pO1xuXG4gIC8vIFN5bnRoZXNpemUgYSBDbG91ZCBBc3NlbWJseSB0b3RoZSBkZWZhdWx0IGRpcmVjdG9yeSAoY2RrLm91dCkgYW5kIGEgc3BlY2lmaWMgZGlyZWN0b3J5LlxuICBhd2FpdCBmaXh0dXJlLmNkayhbJ3N5bnRoJ10pO1xuICBhd2FpdCBmaXh0dXJlLmNkayhbJ3N5bnRoJywgJy0tb3V0cHV0JywgYXNtT3V0cHV0RGlyXSk7XG5cbiAgLy8gY2RrLm91dCBpbiB0aGUgY3VycmVudCBkaXJlY3RvcnkgYW5kIHRoZSBpbmRpY2F0ZWQgLS1vdXRwdXQgc2hvdWxkIGJlIHRoZSBzYW1lXG4gIGF3YWl0IGZpeHR1cmUuc2hlbGwoWydkaWZmJywgJ2Nkay5vdXQnLCBhc21PdXRwdXREaXJdKTtcblxuICAvLyBDaGVjayB0aGF0IHdlIGNhbiAnbHMnIHRoZSBzeW50aGVzaXplZCBhc20uXG4gIC8vIENoYW5nZSB0byBzb21lIHJhbmRvbSBkaXJlY3RvcnkgdG8gbWFrZSBzdXJlIHdlJ3JlIG5vdCBhY2NpZGVudGFsbHkgbG9hZGluZyBjZGsuanNvblxuICBjb25zdCBsaXN0ID0gYXdhaXQgZml4dHVyZS5jZGsoWyctLWFwcCcsIGFzbU91dHB1dERpciwgJ2xzJ10sIHsgY3dkOiBvcy50bXBkaXIoKSB9KTtcbiAgLy8gU2FtZSBzdGFja3Mgd2Uga25vdyBhcmUgaW4gdGhlIGFwcFxuICBleHBlY3QobGlzdCkudG9Db250YWluKGAke2ZpeHR1cmUuc3RhY2tOYW1lUHJlZml4fS1sYW1iZGFgKTtcbiAgZXhwZWN0KGxpc3QpLnRvQ29udGFpbihgJHtmaXh0dXJlLnN0YWNrTmFtZVByZWZpeH0tdGVzdC0xYCk7XG4gIGV4cGVjdChsaXN0KS50b0NvbnRhaW4oYCR7Zml4dHVyZS5zdGFja05hbWVQcmVmaXh9LXRlc3QtMmApO1xuXG4gIC8vIENoZWNrIHRoYXQgd2UgY2FuIHVzZSAnLicgYW5kIGp1c3Qgc3ludGggLHRoZSBnZW5lcmF0ZWQgYXNtXG4gIGNvbnN0IHN0YWNrVGVtcGxhdGUgPSBhd2FpdCBmaXh0dXJlLmNkayhbJy0tYXBwJywgJy4nLCAnc3ludGgnLCBmaXh0dXJlLmZ1bGxTdGFja05hbWUoJ3Rlc3QtMicpXSwge1xuICAgIGN3ZDogYXNtT3V0cHV0RGlyLFxuICB9KTtcbiAgZXhwZWN0KHN0YWNrVGVtcGxhdGUpLnRvQ29udGFpbigndG9waWMxNTJEODRBMzcnKTtcblxuICAvLyBEZXBsb3kgYSBMYW1iZGEgZnJvbSB0aGUgY29waWVkIGFzbVxuICBhd2FpdCBmaXh0dXJlLmNka0RlcGxveSgnbGFtYmRhJywgeyBvcHRpb25zOiBbJy1hJywgJy4nXSwgY3dkOiBhc21PdXRwdXREaXIgfSk7XG5cbiAgLy8gUmVtb3ZlIChyZW5hbWUpIHRoZSBvcmlnaW5hbCBjdXN0b20gZG9ja2VyIGZpbGUgdGhhdCB3YXMgdXNlZCBkdXJpbmcgc3ludGguXG4gIC8vIHRoaXMgdmVyaWZpZXMgdGhhdCB0aGUgYXNzZW1seSBoYXMgYSBjb3B5IG9mIGl0IGFuZCB0aGF0IHRoZSBtYW5pZmVzdCB1c2VzXG4gIC8vIHJlbGF0aXZlIHBhdGhzIHRvIHJlZmVyZW5jZSB0byBpdC5cbiAgY29uc3QgY3VzdG9tRG9ja2VyRmlsZSA9IHBhdGguam9pbihmaXh0dXJlLmludGVnVGVzdERpciwgJ2RvY2tlcicsICdEb2NrZXJmaWxlLkN1c3RvbScpO1xuICBhd2FpdCBmcy5yZW5hbWUoY3VzdG9tRG9ja2VyRmlsZSwgYCR7Y3VzdG9tRG9ja2VyRmlsZX1+YCk7XG4gIHRyeSB7XG5cbiAgICAvLyBkZXBsb3kgYSBkb2NrZXIgaW1hZ2Ugd2l0aCBjdXN0b20gZmlsZSB3aXRob3V0IHN5bnRoICh1c2VzIGFzc2V0cylcbiAgICBhd2FpdCBmaXh0dXJlLmNka0RlcGxveSgnZG9ja2VyLXdpdGgtY3VzdG9tLWZpbGUnLCB7IG9wdGlvbnM6IFsnLWEnLCAnLiddLCBjd2Q6IGFzbU91dHB1dERpciB9KTtcblxuICB9IGZpbmFsbHkge1xuICAgIC8vIFJlbmFtZSBiYWNrIHRvIHJlc3RvcmUgZml4dHVyZSB0byBvcmlnaW5hbCBzdGF0ZVxuICAgIGF3YWl0IGZzLnJlbmFtZShgJHtjdXN0b21Eb2NrZXJGaWxlfX5gLCBjdXN0b21Eb2NrZXJGaWxlKTtcbiAgfVxufSkpO1xuXG5pbnRlZ1Rlc3QoJ3RlbXBsYXRlcyBvbiBkaXNrIGNvbnRhaW4gbWV0YWRhdGEgcmVzb3VyY2UsIGFsc28gaW4gbmVzdGVkIGFzc2VtYmxpZXMnLCB3aXRoRGVmYXVsdEZpeHR1cmUoYXN5bmMgKGZpeHR1cmUpID0+IHtcbiAgLy8gU3ludGggZmlyc3QsIGFuZCBzd2l0Y2ggb24gdmVyc2lvbiByZXBvcnRpbmcgYmVjYXVzZSBjZGsuanNvbiBpcyBkaXNhYmxpbmcgaXRcbiAgYXdhaXQgZml4dHVyZS5jZGsoWydzeW50aCcsICctLXZlcnNpb24tcmVwb3J0aW5nPXRydWUnXSk7XG5cbiAgLy8gTG9hZCB0ZW1wbGF0ZSBmcm9tIGRpc2sgZnJvbSByb290IGFzc2VtYmx5XG4gIGNvbnN0IHRlbXBsYXRlQ29udGVudHMgPSBhd2FpdCBmaXh0dXJlLnNoZWxsKFsnY2F0JywgJ2Nkay5vdXQvKi1sYW1iZGEudGVtcGxhdGUuanNvbiddKTtcblxuICBleHBlY3QoSlNPTi5wYXJzZSh0ZW1wbGF0ZUNvbnRlbnRzKS5SZXNvdXJjZXMuQ0RLTWV0YWRhdGEpLnRvQmVUcnV0aHkoKTtcblxuICAvLyBMb2FkIHRlbXBsYXRlIGZyb20gbmVzdGVkIGFzc2VtYmx5XG4gIGNvbnN0IG5lc3RlZFRlbXBsYXRlQ29udGVudHMgPSBhd2FpdCBmaXh0dXJlLnNoZWxsKFsnY2F0JywgJ2Nkay5vdXQvYXNzZW1ibHktKi1zdGFnZS8qLXN0YWdlLVN0YWNrSW5TdGFnZS50ZW1wbGF0ZS5qc29uJ10pO1xuXG4gIGV4cGVjdChKU09OLnBhcnNlKG5lc3RlZFRlbXBsYXRlQ29udGVudHMpLlJlc291cmNlcy5DREtNZXRhZGF0YSkudG9CZVRydXRoeSgpO1xufSkpO1xuXG5hc3luYyBmdW5jdGlvbiBsaXN0Q2hpbGRyZW4ocGFyZW50OiBzdHJpbmcsIHByZWQ6ICh4OiBzdHJpbmcpID0+IFByb21pc2U8Ym9vbGVhbj4pIHtcbiAgY29uc3QgcmV0ID0gbmV3IEFycmF5PHN0cmluZz4oKTtcbiAgZm9yIChjb25zdCBjaGlsZCBvZiBhd2FpdCBmcy5yZWFkZGlyKHBhcmVudCwgeyBlbmNvZGluZzogJ3V0Zi04JyB9KSkge1xuICAgIGNvbnN0IGZ1bGxQYXRoID0gcGF0aC5qb2luKHBhcmVudCwgY2hpbGQudG9TdHJpbmcoKSk7XG4gICAgaWYgKGF3YWl0IHByZWQoZnVsbFBhdGgpKSB7XG4gICAgICByZXQucHVzaChmdWxsUGF0aCk7XG4gICAgfVxuICB9XG4gIHJldHVybiByZXQ7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGxpc3RDaGlsZERpcnMocGFyZW50OiBzdHJpbmcpIHtcbiAgcmV0dXJuIGxpc3RDaGlsZHJlbihwYXJlbnQsIGFzeW5jIChmdWxsUGF0aDogc3RyaW5nKSA9PiAoYXdhaXQgZnMuc3RhdChmdWxsUGF0aCkpLmlzRGlyZWN0b3J5KCkpO1xufVxuXG5hc3luYyBmdW5jdGlvbiByZWFkVGVtcGxhdGUoZml4dHVyZTogVGVzdEZpeHR1cmUsIHN0YWNrTmFtZTogc3RyaW5nKTogUHJvbWlzZTxhbnk+IHtcbiAgY29uc3QgZnVsbFN0YWNrTmFtZSA9IGZpeHR1cmUuZnVsbFN0YWNrTmFtZShzdGFja05hbWUpO1xuICBjb25zdCB0ZW1wbGF0ZVBhdGggPSBwYXRoLmpvaW4oZml4dHVyZS5pbnRlZ1Rlc3REaXIsICdjZGsub3V0JywgYCR7ZnVsbFN0YWNrTmFtZX0udGVtcGxhdGUuanNvbmApO1xuICByZXR1cm4gSlNPTi5wYXJzZSgoYXdhaXQgZnMucmVhZEZpbGUodGVtcGxhdGVQYXRoLCB7IGVuY29kaW5nOiAndXRmLTgnIH0pKS50b1N0cmluZygpKTtcbn1cbiJdfQ== \ No newline at end of file