From 84f69af90bbf54b82d9f18a8ffb46488f2f38bb5 Mon Sep 17 00:00:00 2001 From: Leonardo Gama <51037424+Leo10Gama@users.noreply.github.com> Date: Tue, 10 Sep 2024 11:37:23 -0700 Subject: [PATCH 1/4] chore: fix CHANGELOG.v2.md (#31383) The CHANGELOG was not formatted correctly in the release. This change removes some of the unnecessary links included in the release notes. --- CHANGELOG.v2.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.v2.md b/CHANGELOG.v2.md index 36531fa7924f1..598e29dc63723 100644 --- a/CHANGELOG.v2.md +++ b/CHANGELOG.v2.md @@ -9,7 +9,7 @@ All notable changes to this project will be documented in this file. See [standa * update L1 CloudFormation resource definitions ([#31361](https://github.com/aws/aws-cdk/issues/31361)) ([bc4dbfd](https://github.com/aws/aws-cdk/commit/bc4dbfdb05a1fe02d30c4724958d09f239a3656f)) * **appsync:** support DEBUG and INFO logging levels for AppSync GraphQL APIs ([#31326](https://github.com/aws/aws-cdk/issues/31326)) ([4b9643f](https://github.com/aws/aws-cdk/commit/4b9643f28edc2c530809931ccd7a17a811891af2)) -* **lambda:** added new property allowAllIpv6Outbound to FunctionOptions ([#31013](https://github.com/aws/aws-cdk/issues/31013)) ([fa55194](https://github.com/aws/aws-cdk/commit/fa55194698960b9161590e05cf1138a813315615)), closes [#30994](https://github.com/aws/aws-cdk/issues/30994) [/github.com/aws/aws-cdk/blob/9295a85a8fb893d7f5eae06108b68df864096c4c/packages/aws-cdk-lib/aws-ec2/lib/security-group.ts#L272](https://github.com/aws//github.com/aws/aws-cdk/blob/9295a85a8fb893d7f5eae06108b68df864096c4c/packages/aws-cdk-lib/aws-ec2/lib/security-group.ts/issues/L272) [/github.com/aws/aws-cdk/blob/9295a85a8fb893d7f5eae06108b68df864096c4c/packages/aws-cdk-lib/aws-lambda/lib/function.ts#L146C18-L146C33](https://github.com/aws//github.com/aws/aws-cdk/blob/9295a85a8fb893d7f5eae06108b68df864096c4c/packages/aws-cdk-lib/aws-lambda/lib/function.ts/issues/L146C18-L146C33) [/github.com/aws/aws-cdk/blob/9295a85a8fb893d7f5eae06108b68df864096c4c/packages/aws-cdk-lib/aws-lambda/lib/function.ts#L296C12-L296C28](https://github.com/aws//github.com/aws/aws-cdk/blob/9295a85a8fb893d7f5eae06108b68df864096c4c/packages/aws-cdk-lib/aws-lambda/lib/function.ts/issues/L296C12-L296C28) [/github.com/aws/aws-cdk/blob/9295a85a8fb893d7f5eae06108b68df864096c4c/packages/aws-cdk-lib/aws-lambda/lib/function.ts#L1464C11-L1464C23](https://github.com/aws//github.com/aws/aws-cdk/blob/9295a85a8fb893d7f5eae06108b68df864096c4c/packages/aws-cdk-lib/aws-lambda/lib/function.ts/issues/L1464C11-L1464C23) [/github.com/aws/aws-cdk/blob/9295a85a8fb893d7f5eae06108b68df864096c4c/packages/aws-cdk-lib/aws-lambda/lib/function.ts#L1503](https://github.com/aws//github.com/aws/aws-cdk/blob/9295a85a8fb893d7f5eae06108b68df864096c4c/packages/aws-cdk-lib/aws-lambda/lib/function.ts/issues/L1503) +* **lambda:** added new property allowAllIpv6Outbound to FunctionOptions ([#31013](https://github.com/aws/aws-cdk/issues/31013)) ([fa55194](https://github.com/aws/aws-cdk/commit/fa55194698960b9161590e05cf1138a813315615)), closes [#30994](https://github.com/aws/aws-cdk/issues/30994) ### Bug Fixes From b7bd0416dc1f809eac22b9dbc49a1947e1cfc262 Mon Sep 17 00:00:00 2001 From: mazyu36 Date: Wed, 11 Sep 2024 06:14:25 +0900 Subject: [PATCH 2/4] feat(amplify): support cache configuration for app (#31381) ### Issue # (if applicable) N/A ### Reason for this change On August 13, 2024, Amplify released improvements to caching efficiency for applications. Ref: https://aws.amazon.com/jp/blogs/mobile/cdn-caching-improvements-for-better-app-performance-with-aws-amplify-hosting/ To support this feature, add cache configuration for app ### Description of changes Add `cacheConfigType` property to `App` class ### Description of how you validated changes Add unit tests and integ test. ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/@aws-cdk/aws-amplify-alpha/README.md | 14 ++ .../@aws-cdk/aws-amplify-alpha/lib/app.ts | 27 ++- .../aws-amplify-alpha/test/app.test.ts | 14 ++ ...efaultTestDeployAssert14075C62.assets.json | 19 ++ ...aultTestDeployAssert14075C62.template.json | 36 +++ .../cdk-amplify-app-cache-config.assets.json | 19 ++ ...cdk-amplify-app-cache-config.template.json | 88 ++++++++ .../cdk.out | 1 + .../integ.json | 14 ++ .../manifest.json | 125 ++++++++++ .../tree.json | 213 ++++++++++++++++++ .../test/integ.app-cache-config.ts | 25 ++ 12 files changed, 594 insertions(+), 1 deletion(-) create mode 100644 packages/@aws-cdk/aws-amplify-alpha/test/integ.app-cache-config.js.snapshot/amplifyappcachecofigintegDefaultTestDeployAssert14075C62.assets.json create mode 100644 packages/@aws-cdk/aws-amplify-alpha/test/integ.app-cache-config.js.snapshot/amplifyappcachecofigintegDefaultTestDeployAssert14075C62.template.json create mode 100644 packages/@aws-cdk/aws-amplify-alpha/test/integ.app-cache-config.js.snapshot/cdk-amplify-app-cache-config.assets.json create mode 100644 packages/@aws-cdk/aws-amplify-alpha/test/integ.app-cache-config.js.snapshot/cdk-amplify-app-cache-config.template.json create mode 100644 packages/@aws-cdk/aws-amplify-alpha/test/integ.app-cache-config.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk/aws-amplify-alpha/test/integ.app-cache-config.js.snapshot/integ.json create mode 100644 packages/@aws-cdk/aws-amplify-alpha/test/integ.app-cache-config.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk/aws-amplify-alpha/test/integ.app-cache-config.js.snapshot/tree.json create mode 100644 packages/@aws-cdk/aws-amplify-alpha/test/integ.app-cache-config.ts diff --git a/packages/@aws-cdk/aws-amplify-alpha/README.md b/packages/@aws-cdk/aws-amplify-alpha/README.md index d543b4090faff..eaeed3c8b9c33 100644 --- a/packages/@aws-cdk/aws-amplify-alpha/README.md +++ b/packages/@aws-cdk/aws-amplify-alpha/README.md @@ -246,6 +246,20 @@ const amplifyApp = new amplify.App(this, 'MyApp', { }); ``` +## Cache Config + +Amplify uses Amazon CloudFront to manage the caching configuration for your hosted applications. A cache configuration is applied to each app to optimize for the best performance. + +Setting the `cacheConfigType` field on the Amplify `App` construct can be used to control cache configguration. By default, the value is set to `AMPLIFY_MANAGED`. If you want to exclude all cookies from the cache key, set `AMPLIFY_MANAGED_NO_COOKIES`. + +For more information, see [Managing the cache configuration for an app](https://docs.aws.amazon.com/amplify/latest/userguide/caching.html). + +```ts +const amplifyApp = new amplify.App(this, 'MyApp', { + cacheConfigType: amplify.CacheConfigType.AMPLIFY_MANAGED_NO_COOKIES, +}); +``` + ## Deploying Assets `sourceCodeProvider` is optional; when this is not specified the Amplify app can be deployed to using `.zip` packages. The `asset` property can be used to deploy S3 assets to Amplify as part of the CDK: diff --git a/packages/@aws-cdk/aws-amplify-alpha/lib/app.ts b/packages/@aws-cdk/aws-amplify-alpha/lib/app.ts index db9dfae461c80..803ce4ae8f9a2 100644 --- a/packages/@aws-cdk/aws-amplify-alpha/lib/app.ts +++ b/packages/@aws-cdk/aws-amplify-alpha/lib/app.ts @@ -167,6 +167,13 @@ export interface AppProps { * @default Platform.WEB */ readonly platform?: Platform; + + /** + * The type of cache configuration to use for an Amplify app. + * + * @default CacheConfigType.AMPLIFY_MANAGED + */ + readonly cacheConfigType?: CacheConfigType; } /** @@ -239,7 +246,7 @@ export class App extends Resource implements IApp, iam.IGrantable { buildSpec: props.autoBranchCreation.buildSpec && props.autoBranchCreation.buildSpec.toBuildSpec(), enableAutoBranchCreation: true, enableAutoBuild: props.autoBranchCreation.autoBuild ?? true, - environmentVariables: Lazy.any({ produce: () => renderEnvironmentVariables(this.autoBranchEnvironmentVariables ) }, { omitEmptyArray: true }), // eslint-disable-line max-len + environmentVariables: Lazy.any({ produce: () => renderEnvironmentVariables(this.autoBranchEnvironmentVariables) }, { omitEmptyArray: true }), // eslint-disable-line max-len enablePullRequestPreview: props.autoBranchCreation.pullRequestPreview ?? true, pullRequestEnvironmentName: props.autoBranchCreation.pullRequestEnvironmentName, stage: props.autoBranchCreation.stage, @@ -249,6 +256,7 @@ export class App extends Resource implements IApp, iam.IGrantable { ? props.basicAuth.bind(this, 'AppBasicAuth') : { enableBasicAuth: false }, buildSpec: props.buildSpec && props.buildSpec.toBuildSpec(), + cacheConfig: props.cacheConfigType ? { type: props.cacheConfigType } : undefined, customRules: Lazy.any({ produce: () => this.customRules }, { omitEmptyArray: true }), description: props.description, environmentVariables: Lazy.any({ produce: () => renderEnvironmentVariables(this.environmentVariables) }, { omitEmptyArray: true }), @@ -554,3 +562,20 @@ export enum Platform { */ WEB_COMPUTE = 'WEB_COMPUTE', } + +/** + * The type of cache configuration to use for an Amplify app. + */ +export enum CacheConfigType { + /** + * AMPLIFY_MANAGED - Automatically applies an optimized cache configuration + * for your app based on its platform, routing rules, and rewrite rules. + */ + AMPLIFY_MANAGED = 'AMPLIFY_MANAGED', + + /** + * AMPLIFY_MANAGED_NO_COOKIES - The same as AMPLIFY_MANAGED, + * except that it excludes all cookies from the cache key. + */ + AMPLIFY_MANAGED_NO_COOKIES = 'AMPLIFY_MANAGED_NO_COOKIES', +} diff --git a/packages/@aws-cdk/aws-amplify-alpha/test/app.test.ts b/packages/@aws-cdk/aws-amplify-alpha/test/app.test.ts index b5c800bf387d6..1e097547c8215 100644 --- a/packages/@aws-cdk/aws-amplify-alpha/test/app.test.ts +++ b/packages/@aws-cdk/aws-amplify-alpha/test/app.test.ts @@ -464,3 +464,17 @@ test('create a dynamically rendered app when the platform is set to WEB_COMPUTE' Platform: amplify.Platform.WEB_COMPUTE, }); }); + +test.each([amplify.CacheConfigType.AMPLIFY_MANAGED, amplify.CacheConfigType.AMPLIFY_MANAGED_NO_COOKIES])('create a app with cacheConfigType is set to %s', (cacheConfigType) => { + // WHEN + new amplify.App(stack, 'App', { + cacheConfigType, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Amplify::App', { + CacheConfig: { + Type: cacheConfigType, + }, + }); +}); diff --git a/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-cache-config.js.snapshot/amplifyappcachecofigintegDefaultTestDeployAssert14075C62.assets.json b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-cache-config.js.snapshot/amplifyappcachecofigintegDefaultTestDeployAssert14075C62.assets.json new file mode 100644 index 0000000000000..08cc0d277255b --- /dev/null +++ b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-cache-config.js.snapshot/amplifyappcachecofigintegDefaultTestDeployAssert14075C62.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.5", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "amplifyappcachecofigintegDefaultTestDeployAssert14075C62.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-cache-config.js.snapshot/amplifyappcachecofigintegDefaultTestDeployAssert14075C62.template.json b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-cache-config.js.snapshot/amplifyappcachecofigintegDefaultTestDeployAssert14075C62.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-cache-config.js.snapshot/amplifyappcachecofigintegDefaultTestDeployAssert14075C62.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-cache-config.js.snapshot/cdk-amplify-app-cache-config.assets.json b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-cache-config.js.snapshot/cdk-amplify-app-cache-config.assets.json new file mode 100644 index 0000000000000..fed9ce3ee5b8a --- /dev/null +++ b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-cache-config.js.snapshot/cdk-amplify-app-cache-config.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.5", + "files": { + "3239e363f9e8e5a4ef7c700724f38f69548a563607e006187dc64b4027f36839": { + "source": { + "path": "cdk-amplify-app-cache-config.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "3239e363f9e8e5a4ef7c700724f38f69548a563607e006187dc64b4027f36839.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-cache-config.js.snapshot/cdk-amplify-app-cache-config.template.json b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-cache-config.js.snapshot/cdk-amplify-app-cache-config.template.json new file mode 100644 index 0000000000000..bc7e9cd8edbda --- /dev/null +++ b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-cache-config.js.snapshot/cdk-amplify-app-cache-config.template.json @@ -0,0 +1,88 @@ +{ + "Resources": { + "AppRole1AF9B530": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "amplify.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "AppF1B96344": { + "Type": "AWS::Amplify::App", + "Properties": { + "BasicAuthConfig": { + "EnableBasicAuth": false + }, + "CacheConfig": { + "Type": "AMPLIFY_MANAGED_NO_COOKIES" + }, + "IAMServiceRole": { + "Fn::GetAtt": [ + "AppRole1AF9B530", + "Arn" + ] + }, + "Name": "App", + "Platform": "WEB" + } + }, + "AppmainF505BAED": { + "Type": "AWS::Amplify::Branch", + "Properties": { + "AppId": { + "Fn::GetAtt": [ + "AppF1B96344", + "AppId" + ] + }, + "BranchName": "main", + "EnableAutoBuild": true, + "EnablePullRequestPreview": true + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-cache-config.js.snapshot/cdk.out b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-cache-config.js.snapshot/cdk.out new file mode 100644 index 0000000000000..bd5311dc372de --- /dev/null +++ b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-cache-config.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"36.0.5"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-cache-config.js.snapshot/integ.json b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-cache-config.js.snapshot/integ.json new file mode 100644 index 0000000000000..1ebbff2484eae --- /dev/null +++ b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-cache-config.js.snapshot/integ.json @@ -0,0 +1,14 @@ +{ + "enableLookups": true, + "version": "36.0.5", + "testCases": { + "amplify-app-cache-cofig-integ/DefaultTest": { + "stacks": [ + "cdk-amplify-app-cache-config" + ], + "stackUpdateWorkflow": false, + "assertionStack": "amplify-app-cache-cofig-integ/DefaultTest/DeployAssert", + "assertionStackName": "amplifyappcachecofigintegDefaultTestDeployAssert14075C62" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-cache-config.js.snapshot/manifest.json b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-cache-config.js.snapshot/manifest.json new file mode 100644 index 0000000000000..d82bda55c99dc --- /dev/null +++ b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-cache-config.js.snapshot/manifest.json @@ -0,0 +1,125 @@ +{ + "version": "36.0.5", + "artifacts": { + "cdk-amplify-app-cache-config.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "cdk-amplify-app-cache-config.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "cdk-amplify-app-cache-config": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "cdk-amplify-app-cache-config.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/3239e363f9e8e5a4ef7c700724f38f69548a563607e006187dc64b4027f36839.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "cdk-amplify-app-cache-config.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "cdk-amplify-app-cache-config.assets" + ], + "metadata": { + "/cdk-amplify-app-cache-config/App/Role/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "AppRole1AF9B530" + } + ], + "/cdk-amplify-app-cache-config/App/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "AppF1B96344" + } + ], + "/cdk-amplify-app-cache-config/App/main/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "AppmainF505BAED" + } + ], + "/cdk-amplify-app-cache-config/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/cdk-amplify-app-cache-config/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "cdk-amplify-app-cache-config" + }, + "amplifyappcachecofigintegDefaultTestDeployAssert14075C62.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "amplifyappcachecofigintegDefaultTestDeployAssert14075C62.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "amplifyappcachecofigintegDefaultTestDeployAssert14075C62": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "amplifyappcachecofigintegDefaultTestDeployAssert14075C62.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "amplifyappcachecofigintegDefaultTestDeployAssert14075C62.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "amplifyappcachecofigintegDefaultTestDeployAssert14075C62.assets" + ], + "metadata": { + "/amplify-app-cache-cofig-integ/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/amplify-app-cache-cofig-integ/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "amplify-app-cache-cofig-integ/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-cache-config.js.snapshot/tree.json b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-cache-config.js.snapshot/tree.json new file mode 100644 index 0000000000000..f390075480891 --- /dev/null +++ b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-cache-config.js.snapshot/tree.json @@ -0,0 +1,213 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "cdk-amplify-app-cache-config": { + "id": "cdk-amplify-app-cache-config", + "path": "cdk-amplify-app-cache-config", + "children": { + "App": { + "id": "App", + "path": "cdk-amplify-app-cache-config/App", + "children": { + "Role": { + "id": "Role", + "path": "cdk-amplify-app-cache-config/App/Role", + "children": { + "ImportRole": { + "id": "ImportRole", + "path": "cdk-amplify-app-cache-config/App/Role/ImportRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "cdk-amplify-app-cache-config/App/Role/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "amplify.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "cdk-amplify-app-cache-config/App/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Amplify::App", + "aws:cdk:cloudformation:props": { + "basicAuthConfig": { + "enableBasicAuth": false + }, + "cacheConfig": { + "type": "AMPLIFY_MANAGED_NO_COOKIES" + }, + "iamServiceRole": { + "Fn::GetAtt": [ + "AppRole1AF9B530", + "Arn" + ] + }, + "name": "App", + "platform": "WEB" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_amplify.CfnApp", + "version": "0.0.0" + } + }, + "main": { + "id": "main", + "path": "cdk-amplify-app-cache-config/App/main", + "children": { + "Resource": { + "id": "Resource", + "path": "cdk-amplify-app-cache-config/App/main/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Amplify::Branch", + "aws:cdk:cloudformation:props": { + "appId": { + "Fn::GetAtt": [ + "AppF1B96344", + "AppId" + ] + }, + "branchName": "main", + "enableAutoBuild": true, + "enablePullRequestPreview": true + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_amplify.CfnBranch", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "cdk-amplify-app-cache-config/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "cdk-amplify-app-cache-config/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "amplify-app-cache-cofig-integ": { + "id": "amplify-app-cache-cofig-integ", + "path": "amplify-app-cache-cofig-integ", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "amplify-app-cache-cofig-integ/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "amplify-app-cache-cofig-integ/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "amplify-app-cache-cofig-integ/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "amplify-app-cache-cofig-integ/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "amplify-app-cache-cofig-integ/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-cache-config.ts b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-cache-config.ts new file mode 100644 index 0000000000000..78c5b9544ed4a --- /dev/null +++ b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-cache-config.ts @@ -0,0 +1,25 @@ +import { App, Stack, StackProps } from 'aws-cdk-lib'; +import { Construct } from 'constructs'; +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; +import * as amplify from '../lib'; + +class TestStack extends Stack { + constructor(scope: Construct, id: string, props?: StackProps) { + super(scope, id, props); + + const amplifyApp = new amplify.App(this, 'App', { + cacheConfigType: amplify.CacheConfigType.AMPLIFY_MANAGED_NO_COOKIES, + }); + + amplifyApp.addBranch('main'); + } +} + +const app = new App(); +const stack = new TestStack(app, 'cdk-amplify-app-cache-config'); + +new IntegTest(app, 'amplify-app-cache-cofig-integ', { + testCases: [stack], + enableLookups: true, + stackUpdateWorkflow: false, +}); From af9e6bae94c0c303364c2c4f2033eb3823fb59c9 Mon Sep 17 00:00:00 2001 From: Calvin Combs <66279577+comcalvi@users.noreply.github.com> Date: Tue, 10 Sep 2024 15:15:47 -0700 Subject: [PATCH 3/4] fix(cloudformation-include): can't use CFN intrinsics in Tags (#30515) ### Issue # (if applicable) Closes #27594. ### Reason for this change Templates that use intrinsics in resource Tags cannot be used with CFN Include. ### Description of changes Modifed the CFN Parser to not choke on Intrinsics found in resource Tags. ### Description of how you validated changes Unit tests. ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- ...efaultTestDeployAssert069A8F1A.assets.json | 19 ++ ...aultTestDeployAssert069A8F1A.template.json | 36 ++++ .../Stack.assets.json | 19 ++ .../Stack.template.json | 77 +++++++ .../cdk.out | 1 + .../integ.json | 12 ++ .../manifest.json | 131 +++++++++++ .../tree.json | 204 ++++++++++++++++++ .../integ.resource-tags-wtih-intrinsics.ts | 15 ++ .../test-templates/tags-with-intrinsics.json | 42 ++++ .../test-templates/tags-with-intrinsics.json | 46 ++++ .../tags-with-invalid-intrinsics.json | 46 ++++ .../test/valid-templates.test.ts | 14 ++ .../core/lib/helpers-internal/cfn-parse.ts | 3 +- packages/aws-cdk-lib/core/lib/runtime.ts | 1 + 15 files changed, 665 insertions(+), 1 deletion(-) create mode 100644 packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/integ.resource-tags-wtih-intrinsics.js.snapshot/ResourceTagIntrinsicStackDefaultTestDeployAssert069A8F1A.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/integ.resource-tags-wtih-intrinsics.js.snapshot/ResourceTagIntrinsicStackDefaultTestDeployAssert069A8F1A.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/integ.resource-tags-wtih-intrinsics.js.snapshot/Stack.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/integ.resource-tags-wtih-intrinsics.js.snapshot/Stack.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/integ.resource-tags-wtih-intrinsics.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/integ.resource-tags-wtih-intrinsics.js.snapshot/integ.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/integ.resource-tags-wtih-intrinsics.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/integ.resource-tags-wtih-intrinsics.js.snapshot/tree.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/integ.resource-tags-wtih-intrinsics.ts create mode 100644 packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/test-templates/tags-with-intrinsics.json create mode 100644 packages/aws-cdk-lib/cloudformation-include/test/test-templates/tags-with-intrinsics.json create mode 100644 packages/aws-cdk-lib/cloudformation-include/test/test-templates/tags-with-invalid-intrinsics.json diff --git a/packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/integ.resource-tags-wtih-intrinsics.js.snapshot/ResourceTagIntrinsicStackDefaultTestDeployAssert069A8F1A.assets.json b/packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/integ.resource-tags-wtih-intrinsics.js.snapshot/ResourceTagIntrinsicStackDefaultTestDeployAssert069A8F1A.assets.json new file mode 100644 index 0000000000000..ee152a8b62fae --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/integ.resource-tags-wtih-intrinsics.js.snapshot/ResourceTagIntrinsicStackDefaultTestDeployAssert069A8F1A.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "ResourceTagIntrinsicStackDefaultTestDeployAssert069A8F1A.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/integ.resource-tags-wtih-intrinsics.js.snapshot/ResourceTagIntrinsicStackDefaultTestDeployAssert069A8F1A.template.json b/packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/integ.resource-tags-wtih-intrinsics.js.snapshot/ResourceTagIntrinsicStackDefaultTestDeployAssert069A8F1A.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/integ.resource-tags-wtih-intrinsics.js.snapshot/ResourceTagIntrinsicStackDefaultTestDeployAssert069A8F1A.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/integ.resource-tags-wtih-intrinsics.js.snapshot/Stack.assets.json b/packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/integ.resource-tags-wtih-intrinsics.js.snapshot/Stack.assets.json new file mode 100644 index 0000000000000..c4ebf26bf97cd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/integ.resource-tags-wtih-intrinsics.js.snapshot/Stack.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "65183510cc1fe133ea25e9f8b474aa5adca1ac83c5e18072e74a62c2bb570cc2": { + "source": { + "path": "Stack.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "65183510cc1fe133ea25e9f8b474aa5adca1ac83c5e18072e74a62c2bb570cc2.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/integ.resource-tags-wtih-intrinsics.js.snapshot/Stack.template.json b/packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/integ.resource-tags-wtih-intrinsics.js.snapshot/Stack.template.json new file mode 100644 index 0000000000000..fee4da18ca069 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/integ.resource-tags-wtih-intrinsics.js.snapshot/Stack.template.json @@ -0,0 +1,77 @@ +{ + "Parameters": { + "Param": { + "Type": "CommaDelimitedList", + "Default": "key,value" + }, + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Conditions": { + "ShouldIncludeTag": { + "Fn::Equals": [ + 2, + 2 + ] + } + }, + "Resources": { + "Bucket": { + "Type": "AWS::S3::Bucket", + "Properties": { + "BucketName": "cdk-integ-cfn-include-bucket2", + "Tags": [ + { + "Fn::If": [ + "ShouldIncludeTag", + { + "Key": { + "Fn::Select": [ + 0, + { + "Ref": "Param" + } + ] + }, + "Value": "TagValue" + }, + { + "Ref": "AWS::NoValue" + } + ] + } + ] + } + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/integ.resource-tags-wtih-intrinsics.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/integ.resource-tags-wtih-intrinsics.js.snapshot/cdk.out new file mode 100644 index 0000000000000..1f0068d32659a --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/integ.resource-tags-wtih-intrinsics.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"36.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/integ.resource-tags-wtih-intrinsics.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/integ.resource-tags-wtih-intrinsics.js.snapshot/integ.json new file mode 100644 index 0000000000000..d6e49c7d11c4b --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/integ.resource-tags-wtih-intrinsics.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "36.0.0", + "testCases": { + "ResourceTagIntrinsicStack/DefaultTest": { + "stacks": [ + "Stack" + ], + "assertionStack": "ResourceTagIntrinsicStack/DefaultTest/DeployAssert", + "assertionStackName": "ResourceTagIntrinsicStackDefaultTestDeployAssert069A8F1A" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/integ.resource-tags-wtih-intrinsics.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/integ.resource-tags-wtih-intrinsics.js.snapshot/manifest.json new file mode 100644 index 0000000000000..e640cbfd06fcc --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/integ.resource-tags-wtih-intrinsics.js.snapshot/manifest.json @@ -0,0 +1,131 @@ +{ + "version": "36.0.0", + "artifacts": { + "Stack.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "Stack.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "Stack": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "Stack.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/65183510cc1fe133ea25e9f8b474aa5adca1ac83c5e18072e74a62c2bb570cc2.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "Stack.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "Stack.assets" + ], + "metadata": { + "/Stack/Stack": [ + { + "type": "aws:cdk:logicalId", + "data": "Stack" + } + ], + "/Stack/Stack/Param": [ + { + "type": "aws:cdk:logicalId", + "data": "Param" + } + ], + "/Stack/Stack/$Conditions/ShouldIncludeTag": [ + { + "type": "aws:cdk:logicalId", + "data": "ShouldIncludeTag" + } + ], + "/Stack/Stack/Bucket": [ + { + "type": "aws:cdk:logicalId", + "data": "Bucket" + } + ], + "/Stack/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/Stack/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "Stack" + }, + "ResourceTagIntrinsicStackDefaultTestDeployAssert069A8F1A.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "ResourceTagIntrinsicStackDefaultTestDeployAssert069A8F1A.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "ResourceTagIntrinsicStackDefaultTestDeployAssert069A8F1A": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "ResourceTagIntrinsicStackDefaultTestDeployAssert069A8F1A.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "ResourceTagIntrinsicStackDefaultTestDeployAssert069A8F1A.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "ResourceTagIntrinsicStackDefaultTestDeployAssert069A8F1A.assets" + ], + "metadata": { + "/ResourceTagIntrinsicStack/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/ResourceTagIntrinsicStack/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "ResourceTagIntrinsicStack/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/integ.resource-tags-wtih-intrinsics.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/integ.resource-tags-wtih-intrinsics.js.snapshot/tree.json new file mode 100644 index 0000000000000..7b8ecf8423488 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/integ.resource-tags-wtih-intrinsics.js.snapshot/tree.json @@ -0,0 +1,204 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "Stack": { + "id": "Stack", + "path": "Stack", + "children": { + "Stack": { + "id": "Stack", + "path": "Stack/Stack", + "children": { + "$Mappings": { + "id": "$Mappings", + "path": "Stack/Stack/$Mappings", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "Param": { + "id": "Param", + "path": "Stack/Stack/Param", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "$Conditions": { + "id": "$Conditions", + "path": "Stack/Stack/$Conditions", + "children": { + "ShouldIncludeTag": { + "id": "ShouldIncludeTag", + "path": "Stack/Stack/$Conditions/ShouldIncludeTag", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "$Rules": { + "id": "$Rules", + "path": "Stack/Stack/$Rules", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "Bucket": { + "id": "Bucket", + "path": "Stack/Stack/Bucket", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::S3::Bucket", + "aws:cdk:cloudformation:props": { + "bucketName": "cdk-integ-cfn-include-bucket2", + "tags": [ + { + "Fn::If": [ + "ShouldIncludeTag", + { + "Key": { + "Fn::Select": [ + 0, + { + "Ref": "Param" + } + ] + }, + "Value": "TagValue" + }, + { + "Ref": "AWS::NoValue" + } + ] + } + ] + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "$Hooks": { + "id": "$Hooks", + "path": "Stack/Stack/$Hooks", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "$Outputs": { + "id": "$Outputs", + "path": "Stack/Stack/$Outputs", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "Stack/BootstrapVersion", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "Stack/CheckBootstrapVersion", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "ResourceTagIntrinsicStack": { + "id": "ResourceTagIntrinsicStack", + "path": "ResourceTagIntrinsicStack", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "ResourceTagIntrinsicStack/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "ResourceTagIntrinsicStack/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "ResourceTagIntrinsicStack/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "ResourceTagIntrinsicStack/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "ResourceTagIntrinsicStack/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/integ.resource-tags-wtih-intrinsics.ts b/packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/integ.resource-tags-wtih-intrinsics.ts new file mode 100644 index 0000000000000..62e697ad5d0d4 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/integ.resource-tags-wtih-intrinsics.ts @@ -0,0 +1,15 @@ +import * as core from 'aws-cdk-lib'; +import * as inc from 'aws-cdk-lib/cloudformation-include'; +import * as integ from '@aws-cdk/integ-tests-alpha'; + +const app = new core.App(); + +const stack = new core.Stack(app, 'Stack'); + +new inc.CfnInclude(stack, 'Stack', { + templateFile: 'test-templates/tags-with-intrinsics.json', +}); + +new integ.IntegTest(app, 'ResourceTagIntrinsicStack', { + testCases: [stack], +}); diff --git a/packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/test-templates/tags-with-intrinsics.json b/packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/test-templates/tags-with-intrinsics.json new file mode 100644 index 0000000000000..886560576e751 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/cloudformation-include/test/test-templates/tags-with-intrinsics.json @@ -0,0 +1,42 @@ +{ + "Parameters": { + "Param": { + "Type": "CommaDelimitedList", + "Default": "key,value" + } + }, + "Conditions": { + "ShouldIncludeTag": { + "Fn::Equals": [2, 2] + } + }, + "Resources": { + "Bucket": { + "Type": "AWS::S3::Bucket", + "Properties": { + "BucketName": "cdk-integ-cfn-include-bucket2", + "Tags": [ + { + "Fn::If": [ + "ShouldIncludeTag", + { + "Key": { + "Fn::Select": [ + 0, + { + "Ref": "Param" + } + ] + }, + "Value": "TagValue" + }, + { + "Ref": "AWS::NoValue" + } + ] + } + ] + } + } + } +} \ No newline at end of file diff --git a/packages/aws-cdk-lib/cloudformation-include/test/test-templates/tags-with-intrinsics.json b/packages/aws-cdk-lib/cloudformation-include/test/test-templates/tags-with-intrinsics.json new file mode 100644 index 0000000000000..3ba70c35443de --- /dev/null +++ b/packages/aws-cdk-lib/cloudformation-include/test/test-templates/tags-with-intrinsics.json @@ -0,0 +1,46 @@ +{ + "Parameters": { + "Param": { + "Type": "CommaDelimitedList", + "Default": "key,value" + } + }, + "Conditions": { + "ShouldIncludeTag": { + "Fn::Equals": [2, 2] + } + }, + "Resources": { + "Bucket": { + "Type": "AWS::S3::Bucket", + "Properties": { + "BucketName": "cdk-integ-cfn-include-bucket2", + "Tags": [ + { + "Key": "Key1", + "Value": "Value1" + }, + { + "Fn::If": [ + "ShouldIncludeTag", + { + "Key": { + "Fn::Select": [ + 0, + { + "Ref": "Param" + } + ] + }, + "Value": "TagValue" + }, + { + "Ref": "AWS::NoValue" + } + ] + } + ] + } + } + } +} \ No newline at end of file diff --git a/packages/aws-cdk-lib/cloudformation-include/test/test-templates/tags-with-invalid-intrinsics.json b/packages/aws-cdk-lib/cloudformation-include/test/test-templates/tags-with-invalid-intrinsics.json new file mode 100644 index 0000000000000..81c8368f88521 --- /dev/null +++ b/packages/aws-cdk-lib/cloudformation-include/test/test-templates/tags-with-invalid-intrinsics.json @@ -0,0 +1,46 @@ +{ + "Parameters": { + "Param": { + "Type": "CommaDelimitedList", + "Default": "key,value" + } + }, + "Conditions": { + "ShouldIncludeTag": { + "Fn::Equals": [2, 2] + } + }, + "Resources": { + "Bucket": { + "Type": "AWS::S3::Bucket", + "Properties": { + "BucketName": "cdk-integ-cfn-include-bucket2", + "Tags": [ + { + "Key": "Key1", + "Value": "Value1" + }, + { + "Fn::If": [ + "NonExistentCondition", + { + "Key": { + "Fn::Select": [ + 0, + { + "Ref": "Param" + } + ] + }, + "Value": "TagValue" + }, + { + "Ref": "AWS::NoValue" + } + ] + } + ] + } + } + } +} \ No newline at end of file diff --git a/packages/aws-cdk-lib/cloudformation-include/test/valid-templates.test.ts b/packages/aws-cdk-lib/cloudformation-include/test/valid-templates.test.ts index 70a26179415d0..8876e5c3fe50a 100644 --- a/packages/aws-cdk-lib/cloudformation-include/test/valid-templates.test.ts +++ b/packages/aws-cdk-lib/cloudformation-include/test/valid-templates.test.ts @@ -1121,6 +1121,20 @@ describe('CDK Include', () => { loadTestFileToJsObject('fn-select-with-novalue.json'), ); }); + + test('Fn::If can be used in Tags', () => { + includeTestTemplate(stack, 'tags-with-intrinsics.json'); + + Template.fromStack(stack).templateMatches( + loadTestFileToJsObject('tags-with-intrinsics.json'), + ); + }); + + test('throws an exception if Tags contains invalid intrinsics', () => { + expect(() => { + includeTestTemplate(stack, 'tags-with-invalid-intrinsics.json'); + }).toThrow(/expression does not exist in the template/); + }); }); interface IncludeTestTemplateProps { diff --git a/packages/aws-cdk-lib/core/lib/helpers-internal/cfn-parse.ts b/packages/aws-cdk-lib/core/lib/helpers-internal/cfn-parse.ts index 2dce8dad956e9..fbbb26c0c566e 100644 --- a/packages/aws-cdk-lib/core/lib/helpers-internal/cfn-parse.ts +++ b/packages/aws-cdk-lib/core/lib/helpers-internal/cfn-parse.ts @@ -216,7 +216,8 @@ export class FromCloudFormation { }; } - public static getCfnTag(tag: any): FromCloudFormationResult { + public static getCfnTag(tag: any): FromCloudFormationResult { + if (isResolvableObject(tag)) { return new FromCloudFormationResult(tag); } return tag == null ? new FromCloudFormationResult({ } as any) // break the type system - this should be detected at runtime by a tag validator : new FromCloudFormationResult({ diff --git a/packages/aws-cdk-lib/core/lib/runtime.ts b/packages/aws-cdk-lib/core/lib/runtime.ts index 2da488d6805c2..11c067d319cd3 100644 --- a/packages/aws-cdk-lib/core/lib/runtime.ts +++ b/packages/aws-cdk-lib/core/lib/runtime.ts @@ -49,6 +49,7 @@ function pad(x: number) { * Turn a tag object into the proper CloudFormation representation */ export function cfnTagToCloudFormation(x: any): any { + if (!canInspect(x)) { return x; } return { Key: x.key, Value: x.value, From 1794dc46c3f48c39f6a499a72cdaaeacb4e5b1f3 Mon Sep 17 00:00:00 2001 From: Calvin Combs <66279577+comcalvi@users.noreply.github.com> Date: Tue, 10 Sep 2024 16:21:17 -0700 Subject: [PATCH 4/4] chore(diff): fomatter unit test fails locally (#31396) ### Issue # (if applicable) N/A ### Reason for this change `format value can handle partial json strings` fails the repo build on my machine. This doesn't happen at the package level, for some reason. ### Description of changes Made it pass the repo build. ### Description of how you validated changes N/A ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/@aws-cdk/cloudformation-diff/test/format.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/cloudformation-diff/test/format.test.ts b/packages/@aws-cdk/cloudformation-diff/test/format.test.ts index 6cd6d23d38b5f..6c6a8c30aeb08 100644 --- a/packages/@aws-cdk/cloudformation-diff/test/format.test.ts +++ b/packages/@aws-cdk/cloudformation-diff/test/format.test.ts @@ -5,5 +5,5 @@ const formatter = new Formatter(process.stdout, {}); test('format value can handle partial json strings', () => { const output = formatter.formatValue({ nice: 'great', partialJson: '{"wow": "great' }, chalk.red); - expect(output).toEqual('{\"nice\":\"great\",\"partialJson\":\"{\\\"wow\\\": \\\"great\"}'); -}); \ No newline at end of file + expect(output).toEqual(chalk.red('{\"nice\":\"great\",\"partialJson\":\"{\\\"wow\\\": \\\"great\"}')); +});