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 01/11] 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 02/11] 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 03/11] 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 04/11] 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 05/11] 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 06/11] 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 07/11] 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 08/11] 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 09/11] 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 10/11] 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 11/11] 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