From db60c27a772d485cc1a9e2099b201700c983da3a Mon Sep 17 00:00:00 2001 From: Calvin Combs Date: Thu, 4 Jun 2020 17:44:41 -0400 Subject: [PATCH 01/22] doc: added slack link to readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ba7a422bb528f..286f7a917ec73 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,7 @@ for tracking bugs and feature requests. * Ask a question on [Stack Overflow](https://stackoverflow.com/questions/tagged/aws-cdk) and tag it with `aws-cdk` * Come join the AWS CDK community on [Gitter](https://gitter.im/awslabs/aws-cdk) +* You'll need an invite to join the [Slack](https://awsdevelopers.slack.com) community * Open a support ticket with [AWS Support](https://console.aws.amazon.com/support/home#/) * If it turns out that you may have found a bug, please open an [issue](https://github.com/aws/aws-cdk/issues/new) From f0c85a36146bdf813638f926f61184661b3683f4 Mon Sep 17 00:00:00 2001 From: comcalvi <66279577+comcalvi@users.noreply.github.com> Date: Fri, 5 Jun 2020 12:49:05 -0400 Subject: [PATCH 02/22] Update README.md Co-authored-by: Adam Ruka --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 286f7a917ec73..9b51cbaba4118 100644 --- a/README.md +++ b/README.md @@ -118,7 +118,7 @@ for tracking bugs and feature requests. * Ask a question on [Stack Overflow](https://stackoverflow.com/questions/tagged/aws-cdk) and tag it with `aws-cdk` * Come join the AWS CDK community on [Gitter](https://gitter.im/awslabs/aws-cdk) -* You'll need an invite to join the [Slack](https://awsdevelopers.slack.com) community +* Talk in the CDK channel of the [AWS Developers Slack workspace](https://awsdevelopers.slack.com) (invite required) * Open a support ticket with [AWS Support](https://console.aws.amazon.com/support/home#/) * If it turns out that you may have found a bug, please open an [issue](https://github.com/aws/aws-cdk/issues/new) From c6664af7ca1ab35c62782527c5d2a7b8137de5ec Mon Sep 17 00:00:00 2001 From: Calvin Combs Date: Mon, 15 Jun 2020 19:08:00 -0400 Subject: [PATCH 03/22] added support for Fn::Select, Fn::FindInMap, Fn::Cidr, Fn::GetAZs, Fn::And, Fn::Not, and Fn::Or, including unit tests. --- .../test/test-templates/conditions.json | 48 ++++++++++++ .../test/test-templates/functions.json | 75 +++++++++++++++++++ .../test/valid-templates.test.ts | 16 ++++ packages/@aws-cdk/core/lib/cfn-parse.ts | 31 ++++++++ 4 files changed, 170 insertions(+) create mode 100644 packages/@aws-cdk/cloudformation-include/test/test-templates/conditions.json create mode 100644 packages/@aws-cdk/cloudformation-include/test/test-templates/functions.json diff --git a/packages/@aws-cdk/cloudformation-include/test/test-templates/conditions.json b/packages/@aws-cdk/cloudformation-include/test/test-templates/conditions.json new file mode 100644 index 0000000000000..5b23794ea3a14 --- /dev/null +++ b/packages/@aws-cdk/cloudformation-include/test/test-templates/conditions.json @@ -0,0 +1,48 @@ +{ + "Conditions": { + "AndCond": { + "Fn::And": [ + {"Condition": "AlwaysTrueCond"}, + {"Condition": "AlwaysFalseCond"} + ] + }, + "OrCond": { + "Fn::Or": [ + {"Condition": "AlwaysTrueCond"}, + {"Condition": "AlwaysFalseCond"} + ] + }, + "AlwaysTrueCond": { + "Fn::Not": [{ + "Fn::Equals": [ + { + "Ref": "AWS::Region" + }, + "completely-made-up-region" + ] + }] + }, + "AlwaysFalseCond": { + "Fn::Equals": [ + { + "Ref": "AWS::Region" + }, + "completely-made-up-region" + ] + } + }, + "Resources": { + "Bucket": { + "Type": "AWS::S3::Bucket", + "Properties": { + "BucketName": { + "Fn::If": [ + "AlwaysTrueCond", + "Name1", + "Name2" + ] + } + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/cloudformation-include/test/test-templates/functions.json b/packages/@aws-cdk/cloudformation-include/test/test-templates/functions.json new file mode 100644 index 0000000000000..6360df54104fd --- /dev/null +++ b/packages/@aws-cdk/cloudformation-include/test/test-templates/functions.json @@ -0,0 +1,75 @@ +{ + "Mappings" : { + "RegionMap" : { + "region-1" : { + "HVM64" : "name1", "HVMG2" : "name2" + } + } + }, + "Resources": { + + "Vpc": { + "Type" : "AWS::EC2::VPC", + "Properties" : { + "CidrBlock" : { + "Fn::Cidr": [ "10.0.0.0/24", "6", "5"] + } + } + }, + "2ArgVpc": { + "Type" : "AWS::EC2::VPC", + "Properties" : { + "CidrBlock" : { + "Fn::Cidr": [ "10.0.0.0/24", "6"] + } + } + }, + "Bucket": { + "Type": "AWS::S3::Bucket", + "Properties": { + "BucketName": { + "Fn::FindInMap": [ + "RegionMap", + "region-1", + "HVM64" + ] + } + } + }, + "subnet1" : { + "Type" : "AWS::EC2::Subnet", + "Properties" : { + "VpcId" : { + "Ref" : "VPC" + }, + "CidrBlock" : "10.0.0.0/24", + "AvailabilityZone" : { + "Fn::Select" : [ + "0", + { + "Fn::GetAZs" : "" + } + ] + } + } + }, + + "subnet2" : { + "Type" : "AWS::EC2::Subnet", + "Properties" : { + "VpcId" : { + "Fn::Select" : ["3", ["foo", "aValidVPCID", "foo2"]] + }, + "CidrBlock" : "10.0.0.0/24", + "AvailabilityZone" : { + "Fn::Select" : [ + "0", + { + "Fn::GetAZs" : "eu-west-2" + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts b/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts index 0291de98eba95..0b9042c77ae36 100644 --- a/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts +++ b/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts @@ -184,6 +184,22 @@ describe('CDK Include', () => { ); }); + test('can ingest a template with many conditions, and output it unchanged', () => { + includeTestTemplate(stack, 'conditions.json'); + + expect(stack).toMatchTemplate( + loadTestFileToJsObject('conditions.json'), + ); + }); + + test('can ingest a template with multiple cloudformation intrinsic functions, and output it unchanged', () => { + includeTestTemplate(stack, 'functions.json'); + + expect(stack).toMatchTemplate( + loadTestFileToJsObject('functions.json'), + ); + }); + test('can ingest a template with a Ref expression for an array value, and output it unchanged', () => { includeTestTemplate(stack, 'ref-array-property.json'); diff --git a/packages/@aws-cdk/core/lib/cfn-parse.ts b/packages/@aws-cdk/core/lib/cfn-parse.ts index 67e2d2390ef62..f8fcfd15c49ed 100644 --- a/packages/@aws-cdk/core/lib/cfn-parse.ts +++ b/packages/@aws-cdk/core/lib/cfn-parse.ts @@ -179,6 +179,25 @@ function parseIfCfnIntrinsic(object: any): any { const value = parseCfnValueToCdkValue(object[key]); return Fn.join(value[0], value[1]); } + case 'Fn::Cidr': { + const value = parseCfnValueToCdkValue(object[key]); + + if (value.length == 2) + return Fn.cidr(value[0], value[1]); + return Fn.cidr(value[0], value[1], value[2]); + } + case 'Fn::FindInMap': { + const value = parseCfnValueToCdkValue(object[key]); + return Fn.findInMap(value[0], value[1], value[2]); + } + case 'Fn::Select': { + const value = parseCfnValueToCdkValue(object[key]); + return Fn.select(value[0], value[1]); + } + case 'Fn::GetAZs': { + const value = parseCfnValueToCdkValue(object[key]); + return Fn.getAzs(value); + } case 'Fn::If': { // Fn::If takes a 3-element list as its argument // ToDo the first argument is the name of the condition, @@ -191,6 +210,18 @@ function parseIfCfnIntrinsic(object: any): any { const value = parseCfnValueToCdkValue(object[key]); return Fn.conditionEquals(value[0], value[1]); } + case 'Fn::And': { + const value = parseCfnValueToCdkValue(object[key]); + return Fn.conditionAnd(...value); + } + case 'Fn::Not': { + const value = parseCfnValueToCdkValue(object[key]); + return Fn.conditionNot(value[0]); + } + case 'Fn::Or': { + const value = parseCfnValueToCdkValue(object[key]); + return Fn.conditionOr(...value); + } default: throw new Error(`Unsupported CloudFormation function '${key}'`); } From d0f64d2cdedf75e440c31948164fee1257b3302f Mon Sep 17 00:00:00 2001 From: Calvin Combs Date: Tue, 16 Jun 2020 14:11:24 -0400 Subject: [PATCH 04/22] added support for the 'Fn::Transform' cloudformation intrinsic function. --- .../test/test-templates/functions.json | 18 ++++++++++++++- packages/@aws-cdk/core/lib/cfn-fn.ts | 22 +++++++++++++++++++ packages/@aws-cdk/core/lib/cfn-parse.ts | 12 ++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/packages/@aws-cdk/cloudformation-include/test/test-templates/functions.json b/packages/@aws-cdk/cloudformation-include/test/test-templates/functions.json index 6360df54104fd..9ee7fed30f3e1 100644 --- a/packages/@aws-cdk/cloudformation-include/test/test-templates/functions.json +++ b/packages/@aws-cdk/cloudformation-include/test/test-templates/functions.json @@ -40,7 +40,10 @@ "Type" : "AWS::EC2::Subnet", "Properties" : { "VpcId" : { - "Ref" : "VPC" + "Fn::Split": [ + ",", + { "Fn::ImportValue" : "ImportedVpcId" } + ] }, "CidrBlock" : "10.0.0.0/24", "AvailabilityZone" : { @@ -70,6 +73,19 @@ ] } } + }, + "transformBucket": { + "Type": "AWS::S3::Bucket", + "Properties": { + "BucketName": { + "Fn::Transform": { + "Name": "AWS::Include", + "Parameters": { + "Location": "location" + } + } + } + } } } } \ No newline at end of file diff --git a/packages/@aws-cdk/core/lib/cfn-fn.ts b/packages/@aws-cdk/core/lib/cfn-fn.ts index 30fb6cf435bec..f6e5d02923fa3 100644 --- a/packages/@aws-cdk/core/lib/cfn-fn.ts +++ b/packages/@aws-cdk/core/lib/cfn-fn.ts @@ -172,6 +172,15 @@ export class Fn { return new FnFindInMap(mapName, topLevelKey, secondLevelKey).toString(); } + /** + * + * @param macroNameParameters The name of the macro to perform the processing, and the Parameters to pass to it + * @returns a token represented as a string + */ + public static transform(macroNameParameters: string): string { + return new FnTransform(macroNameParameters).toString(); + } + /** * Returns true if all the specified conditions evaluate to true, or returns * false if any one of the conditions evaluates to false. ``Fn::And`` acts as @@ -356,6 +365,19 @@ class FnFindInMap extends FnBase { } } +/** + * The intrinsic function ``Fn::Transform`` specifies a macro to perform custom processing on part of a stack template. + */ +class FnTransform extends FnBase { + /** + * + * @param macroNameParameters The name of the macro to be invoked, and the parameters to pass to it + */ + constructor(macroNameParameters: string) { + super('Fn::Transform', macroNameParameters); + } +} + /** * The ``Fn::GetAtt`` intrinsic function returns the value of an attribute from a resource in the template. */ diff --git a/packages/@aws-cdk/core/lib/cfn-parse.ts b/packages/@aws-cdk/core/lib/cfn-parse.ts index f8fcfd15c49ed..78249ec1d5f8a 100644 --- a/packages/@aws-cdk/core/lib/cfn-parse.ts +++ b/packages/@aws-cdk/core/lib/cfn-parse.ts @@ -198,6 +198,18 @@ function parseIfCfnIntrinsic(object: any): any { const value = parseCfnValueToCdkValue(object[key]); return Fn.getAzs(value); } + case 'Fn::ImportValue': { + const value = parseCfnValueToCdkValue(object[key]); + return Fn.importValue(value); + } + case 'Fn::Split': { + const value = parseCfnValueToCdkValue(object[key]); + return Fn.split(value[0], value[1]); + } + case 'Fn::Transform': { + const value = parseCfnValueToCdkValue(object[key]); + return Fn.transform(value); + } case 'Fn::If': { // Fn::If takes a 3-element list as its argument // ToDo the first argument is the name of the condition, From d69e46dce96360149a7f06be64894912e63a8d10 Mon Sep 17 00:00:00 2001 From: Calvin Combs Date: Tue, 16 Jun 2020 14:24:45 -0400 Subject: [PATCH 05/22] added support for the Fn::Base64 Intrinsic Function --- .../test/test-templates/functions.json | 5 ++++- .../only-codecommit-repo-using-cfn-functions.json | 2 +- .../cloudformation-include/test/valid-templates.test.ts | 2 +- packages/@aws-cdk/core/lib/cfn-parse.ts | 4 ++++ 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk/cloudformation-include/test/test-templates/functions.json b/packages/@aws-cdk/cloudformation-include/test/test-templates/functions.json index 9ee7fed30f3e1..fa57eab81ed29 100644 --- a/packages/@aws-cdk/cloudformation-include/test/test-templates/functions.json +++ b/packages/@aws-cdk/cloudformation-include/test/test-templates/functions.json @@ -81,7 +81,10 @@ "Fn::Transform": { "Name": "AWS::Include", "Parameters": { - "Location": "location" + "Location": "location", + "AnotherParameter": { + "Fn:Base64": "AnotherValue" + } } } } diff --git a/packages/@aws-cdk/cloudformation-include/test/test-templates/only-codecommit-repo-using-cfn-functions.json b/packages/@aws-cdk/cloudformation-include/test/test-templates/only-codecommit-repo-using-cfn-functions.json index a1037dbf2402a..10e907c0ea753 100644 --- a/packages/@aws-cdk/cloudformation-include/test/test-templates/only-codecommit-repo-using-cfn-functions.json +++ b/packages/@aws-cdk/cloudformation-include/test/test-templates/only-codecommit-repo-using-cfn-functions.json @@ -5,7 +5,7 @@ "Properties": { "RepositoryName": "my-repository", "RepositoryDescription": { - "Fn::Base64": "my description, in base-64!" + "Fn::DoesNotExist": "my description, in base-64!" } } } diff --git a/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts b/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts index 0b9042c77ae36..16b45ec30f03e 100644 --- a/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts +++ b/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts @@ -289,7 +289,7 @@ describe('CDK Include', () => { test("throws an exception when encountering a CFN function it doesn't support", () => { expect(() => { includeTestTemplate(stack, 'only-codecommit-repo-using-cfn-functions.json'); - }).toThrow(/Unsupported CloudFormation function 'Fn::Base64'/); + }).toThrow(/Unsupported CloudFormation function 'Fn::DoesNotExist'/); }); test('throws an exception when encountering the CreationPolicy attribute in a resource', () => { diff --git a/packages/@aws-cdk/core/lib/cfn-parse.ts b/packages/@aws-cdk/core/lib/cfn-parse.ts index 78249ec1d5f8a..816902b97b3f4 100644 --- a/packages/@aws-cdk/core/lib/cfn-parse.ts +++ b/packages/@aws-cdk/core/lib/cfn-parse.ts @@ -210,6 +210,10 @@ function parseIfCfnIntrinsic(object: any): any { const value = parseCfnValueToCdkValue(object[key]); return Fn.transform(value); } + case 'Fn::Base64': { + const value = parseCfnValueToCdkValue(object[key]); + return Fn.base64(value); + } case 'Fn::If': { // Fn::If takes a 3-element list as its argument // ToDo the first argument is the name of the condition, From df1446a8db9e404341ddd8b584b2d68bbe299a43 Mon Sep 17 00:00:00 2001 From: Calvin Combs Date: Tue, 16 Jun 2020 16:11:19 -0400 Subject: [PATCH 06/22] tested more complex combinations of conditional and non-conditional intrinsic functions --- .../functions-and-conditions.json | 104 ++++++++++++++++++ .../test/valid-templates.test.ts | 9 ++ 2 files changed, 113 insertions(+) create mode 100644 packages/@aws-cdk/cloudformation-include/test/test-templates/functions-and-conditions.json diff --git a/packages/@aws-cdk/cloudformation-include/test/test-templates/functions-and-conditions.json b/packages/@aws-cdk/cloudformation-include/test/test-templates/functions-and-conditions.json new file mode 100644 index 0000000000000..17ccd663564ca --- /dev/null +++ b/packages/@aws-cdk/cloudformation-include/test/test-templates/functions-and-conditions.json @@ -0,0 +1,104 @@ +{ + "Mappings" : { + "RegionMap" : { + "region-1" : { + "HVM64" : "name1", "HVMG2" : "name2" + } + } + }, + "Conditions": { + "AlwaysTrueCond": { + "Fn::Not": [{ + "Fn::Equals": [ + { + "Ref": "AWS::Region" + }, + "completely-made-up-region" + ] + }] + }, + "AlwaysFalseCond": { + "Fn::Equals": [ + { + "Ref": "AWS::Region" + }, + "completely-made-up-region" + ] + } + }, + "Resources": { + "Vpc": { + "Type" : "AWS::EC2::VPC", + "Properties" : { + "CidrBlock" : { + "Fn::If": [ + "AlwaysTrueCond", + { "Fn::Cidr": [ "192.168.1.1/24", "2"] }, + { "Fn::Cidr": [ "10.0.0.0/24", "6", "5"] } + ] + } + } + }, + "Bucket": { + "Type": "AWS::S3::Bucket", + "Properties": { + "BucketName": { + "Fn::If": [ + {"Fn::Or": ["AlwaysFalseCond", "AlwaysFalseCond"]}, + "Unreachable", + {"Fn::FindInMap": [ + "RegionMap", + "region-1", + "HVM64" + ]} + ] + } + } + }, + "subnet1" : { + "Type" : "AWS::EC2::Subnet", + "Properties" : { + "VpcId" : { + "Fn::If": [ + {"Fn::And": ["AlwaysTrueCond", "AlwaysTrueCond"]}, + { + "Fn::Split": [ + ",", + { "Fn::ImportValue" : "ImportedVpcId" } + ]}, + "Unreachable" + ] + }, + "CidrBlock" : "10.0.0.0/24", + "AvailabilityZone" : { + "Fn::Select" : [ + "0", + { + "Fn::GetAZs" : "" + } + ] + } + } + }, + "transformBucket": { + "Type": "AWS::S3::Bucket", + "Properties": { + "BucketName": { + "Fn::If": [ + { "Fn::Or": ["AlwaysFalseCond", "AlwaysTrueCond"]}, { + "Fn::Transform": { + "Name": "AWS::Include", + "Parameters": { + "Location": "location", + "AnotherParameter": { + "Fn:Base64": "AnotherValue" + } + } + } + } + ] + } + } + } + } + } \ No newline at end of file diff --git a/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts b/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts index 16b45ec30f03e..738d3c1187d2f 100644 --- a/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts +++ b/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts @@ -200,6 +200,15 @@ describe('CDK Include', () => { ); }); + test('can ingest a template with intrinsic functions and conditions, and output it unchanged', () => { + includeTestTemplate(stack, 'functions-and-conditions.json'); + + expect(stack).toMatchTemplate( + loadTestFileToJsObject('functions-and-conditions.json'), + ); + }); + + test('can ingest a template with a Ref expression for an array value, and output it unchanged', () => { includeTestTemplate(stack, 'ref-array-property.json'); From 132cb4d87a39ab64b9438107b8ffabef2f8156fe Mon Sep 17 00:00:00 2001 From: Calvin Combs Date: Tue, 16 Jun 2020 18:03:01 -0400 Subject: [PATCH 07/22] fixed linter issues --- packages/@aws-cdk/core/lib/cfn-fn.ts | 7 ++++--- packages/@aws-cdk/core/lib/cfn-parse.ts | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/@aws-cdk/core/lib/cfn-fn.ts b/packages/@aws-cdk/core/lib/cfn-fn.ts index f6e5d02923fa3..88c27bb538e29 100644 --- a/packages/@aws-cdk/core/lib/cfn-fn.ts +++ b/packages/@aws-cdk/core/lib/cfn-fn.ts @@ -173,8 +173,10 @@ export class Fn { } /** - * - * @param macroNameParameters The name of the macro to perform the processing, and the Parameters to pass to it + * The intrinsic function Fn::Transform specifies a macro to perform custom processing on part of a stack template. + * Macros enable you to perform custom processing on templates, from simple actions like find-and-replace operations + * to extensive transformations of entire templates. + * @param macroNameParameters The name of the macro to perform the processing, and the Parameters to pass to it. * @returns a token represented as a string */ public static transform(macroNameParameters: string): string { @@ -370,7 +372,6 @@ class FnFindInMap extends FnBase { */ class FnTransform extends FnBase { /** - * * @param macroNameParameters The name of the macro to be invoked, and the parameters to pass to it */ constructor(macroNameParameters: string) { diff --git a/packages/@aws-cdk/core/lib/cfn-parse.ts b/packages/@aws-cdk/core/lib/cfn-parse.ts index 816902b97b3f4..d386c5f512e55 100644 --- a/packages/@aws-cdk/core/lib/cfn-parse.ts +++ b/packages/@aws-cdk/core/lib/cfn-parse.ts @@ -181,9 +181,10 @@ function parseIfCfnIntrinsic(object: any): any { } case 'Fn::Cidr': { const value = parseCfnValueToCdkValue(object[key]); - - if (value.length == 2) + + if (value.length === 2) { return Fn.cidr(value[0], value[1]); + } return Fn.cidr(value[0], value[1], value[2]); } case 'Fn::FindInMap': { From ae7c5707c74526cb7f67b71f479ed34f029446ca Mon Sep 17 00:00:00 2001 From: Calvin Combs Date: Tue, 16 Jun 2020 20:36:53 -0400 Subject: [PATCH 08/22] implmented Adam's requests and fixed additional linter issues --- .../test/invalid-templates.test.ts | 6 ++ .../test/test-templates/conditions.json | 48 ---------- .../functions-and-conditions.json | 52 ++++++---- .../test/test-templates/functions.json | 94 ------------------- ...y-codecommit-repo-using-cfn-functions.json | 0 .../test/valid-templates.test.ts | 23 ----- packages/@aws-cdk/core/lib/cfn-fn.ts | 15 +-- packages/@aws-cdk/core/lib/cfn-parse.ts | 2 +- 8 files changed, 51 insertions(+), 189 deletions(-) delete mode 100644 packages/@aws-cdk/cloudformation-include/test/test-templates/conditions.json delete mode 100644 packages/@aws-cdk/cloudformation-include/test/test-templates/functions.json rename packages/@aws-cdk/cloudformation-include/test/test-templates/{ => invalid}/only-codecommit-repo-using-cfn-functions.json (100%) diff --git a/packages/@aws-cdk/cloudformation-include/test/invalid-templates.test.ts b/packages/@aws-cdk/cloudformation-include/test/invalid-templates.test.ts index 038ea1e9e6dde..9fb6f91131329 100644 --- a/packages/@aws-cdk/cloudformation-include/test/invalid-templates.test.ts +++ b/packages/@aws-cdk/cloudformation-include/test/invalid-templates.test.ts @@ -52,6 +52,12 @@ describe('CDK Include', () => { includeTestTemplate(stack, 'non-existent-condition.json'); }).toThrow(/Resource 'Bucket' uses Condition 'AlwaysFalseCond' that doesn't exist/); }); + + test("throws an exception when encountering a CFN function it doesn't support", () => { + expect(() => { + includeTestTemplate(stack, 'only-codecommit-repo-using-cfn-functions.json'); + }).toThrow(/Unsupported CloudFormation function 'Fn::DoesNotExist'/); + }); }); function includeTestTemplate(scope: core.Construct, testTemplate: string): inc.CfnInclude { diff --git a/packages/@aws-cdk/cloudformation-include/test/test-templates/conditions.json b/packages/@aws-cdk/cloudformation-include/test/test-templates/conditions.json deleted file mode 100644 index 5b23794ea3a14..0000000000000 --- a/packages/@aws-cdk/cloudformation-include/test/test-templates/conditions.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "Conditions": { - "AndCond": { - "Fn::And": [ - {"Condition": "AlwaysTrueCond"}, - {"Condition": "AlwaysFalseCond"} - ] - }, - "OrCond": { - "Fn::Or": [ - {"Condition": "AlwaysTrueCond"}, - {"Condition": "AlwaysFalseCond"} - ] - }, - "AlwaysTrueCond": { - "Fn::Not": [{ - "Fn::Equals": [ - { - "Ref": "AWS::Region" - }, - "completely-made-up-region" - ] - }] - }, - "AlwaysFalseCond": { - "Fn::Equals": [ - { - "Ref": "AWS::Region" - }, - "completely-made-up-region" - ] - } - }, - "Resources": { - "Bucket": { - "Type": "AWS::S3::Bucket", - "Properties": { - "BucketName": { - "Fn::If": [ - "AlwaysTrueCond", - "Name1", - "Name2" - ] - } - } - } - } -} \ No newline at end of file diff --git a/packages/@aws-cdk/cloudformation-include/test/test-templates/functions-and-conditions.json b/packages/@aws-cdk/cloudformation-include/test/test-templates/functions-and-conditions.json index 17ccd663564ca..a9031ab3ae58c 100644 --- a/packages/@aws-cdk/cloudformation-include/test/test-templates/functions-and-conditions.json +++ b/packages/@aws-cdk/cloudformation-include/test/test-templates/functions-and-conditions.json @@ -9,21 +9,22 @@ "Conditions": { "AlwaysTrueCond": { "Fn::Not": [{ - "Fn::Equals": [ - { - "Ref": "AWS::Region" - }, - "completely-made-up-region" - ] - }] + "Fn::Equals": [{"Ref": "AWS::Region"}, "completely-made-up-region"]}] }, "AlwaysFalseCond": { - "Fn::Equals": [ - { - "Ref": "AWS::Region" - }, - "completely-made-up-region" - ] + "Fn::Equals": [{ "Ref": "AWS::Region" }, "completely-made-up-region"] + }, + "AndCond": { + "Fn::And": [ + {"Condition": "AlwaysTrueCond"}, + {"Condition": "AlwaysFalseCond"} + ] + }, + "OrCond": { + "Fn::Or": [ + {"Condition": "AlwaysTrueCond"}, + {"Condition": "AlwaysFalseCond"} + ] } }, "Resources": { @@ -33,8 +34,8 @@ "CidrBlock" : { "Fn::If": [ "AlwaysTrueCond", - { "Fn::Cidr": [ "192.168.1.1/24", "2"] }, - { "Fn::Cidr": [ "10.0.0.0/24", "6", "5"] } + { "Fn::Cidr": [ "192.168.1.1/24", 2] }, + { "Fn::Cidr": [ "10.0.0.0/24", 6, 5] } ] } } @@ -55,7 +56,7 @@ } } }, - "subnet1" : { + "Subnet1" : { "Type" : "AWS::EC2::Subnet", "Properties" : { "VpcId" : { @@ -80,7 +81,24 @@ } } }, - "transformBucket": { + "Subnet2" : { + "Type" : "AWS::EC2::Subnet", + "Properties" : { + "VpcId" : { + "Fn::Select" : ["3", ["foo", "aValidVPCID", "foo2"]] + }, + "CidrBlock" : "10.0.0.0/24", + "AvailabilityZone" : { + "Fn::Select" : [ + "0", + { + "Fn::GetAZs" : "eu-west-2" + } + ] + } + } + }, + "TransformBucket": { "Type": "AWS::S3::Bucket", "Properties": { "BucketName": { diff --git a/packages/@aws-cdk/cloudformation-include/test/test-templates/functions.json b/packages/@aws-cdk/cloudformation-include/test/test-templates/functions.json deleted file mode 100644 index fa57eab81ed29..0000000000000 --- a/packages/@aws-cdk/cloudformation-include/test/test-templates/functions.json +++ /dev/null @@ -1,94 +0,0 @@ -{ - "Mappings" : { - "RegionMap" : { - "region-1" : { - "HVM64" : "name1", "HVMG2" : "name2" - } - } - }, - "Resources": { - - "Vpc": { - "Type" : "AWS::EC2::VPC", - "Properties" : { - "CidrBlock" : { - "Fn::Cidr": [ "10.0.0.0/24", "6", "5"] - } - } - }, - "2ArgVpc": { - "Type" : "AWS::EC2::VPC", - "Properties" : { - "CidrBlock" : { - "Fn::Cidr": [ "10.0.0.0/24", "6"] - } - } - }, - "Bucket": { - "Type": "AWS::S3::Bucket", - "Properties": { - "BucketName": { - "Fn::FindInMap": [ - "RegionMap", - "region-1", - "HVM64" - ] - } - } - }, - "subnet1" : { - "Type" : "AWS::EC2::Subnet", - "Properties" : { - "VpcId" : { - "Fn::Split": [ - ",", - { "Fn::ImportValue" : "ImportedVpcId" } - ] - }, - "CidrBlock" : "10.0.0.0/24", - "AvailabilityZone" : { - "Fn::Select" : [ - "0", - { - "Fn::GetAZs" : "" - } - ] - } - } - }, - - "subnet2" : { - "Type" : "AWS::EC2::Subnet", - "Properties" : { - "VpcId" : { - "Fn::Select" : ["3", ["foo", "aValidVPCID", "foo2"]] - }, - "CidrBlock" : "10.0.0.0/24", - "AvailabilityZone" : { - "Fn::Select" : [ - "0", - { - "Fn::GetAZs" : "eu-west-2" - } - ] - } - } - }, - "transformBucket": { - "Type": "AWS::S3::Bucket", - "Properties": { - "BucketName": { - "Fn::Transform": { - "Name": "AWS::Include", - "Parameters": { - "Location": "location", - "AnotherParameter": { - "Fn:Base64": "AnotherValue" - } - } - } - } - } - } - } -} \ No newline at end of file diff --git a/packages/@aws-cdk/cloudformation-include/test/test-templates/only-codecommit-repo-using-cfn-functions.json b/packages/@aws-cdk/cloudformation-include/test/test-templates/invalid/only-codecommit-repo-using-cfn-functions.json similarity index 100% rename from packages/@aws-cdk/cloudformation-include/test/test-templates/only-codecommit-repo-using-cfn-functions.json rename to packages/@aws-cdk/cloudformation-include/test/test-templates/invalid/only-codecommit-repo-using-cfn-functions.json diff --git a/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts b/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts index 738d3c1187d2f..70372ad7f3c96 100644 --- a/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts +++ b/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts @@ -184,22 +184,6 @@ describe('CDK Include', () => { ); }); - test('can ingest a template with many conditions, and output it unchanged', () => { - includeTestTemplate(stack, 'conditions.json'); - - expect(stack).toMatchTemplate( - loadTestFileToJsObject('conditions.json'), - ); - }); - - test('can ingest a template with multiple cloudformation intrinsic functions, and output it unchanged', () => { - includeTestTemplate(stack, 'functions.json'); - - expect(stack).toMatchTemplate( - loadTestFileToJsObject('functions.json'), - ); - }); - test('can ingest a template with intrinsic functions and conditions, and output it unchanged', () => { includeTestTemplate(stack, 'functions-and-conditions.json'); @@ -208,7 +192,6 @@ describe('CDK Include', () => { ); }); - test('can ingest a template with a Ref expression for an array value, and output it unchanged', () => { includeTestTemplate(stack, 'ref-array-property.json'); @@ -295,12 +278,6 @@ describe('CDK Include', () => { }).toThrow(/Unrecognized CloudFormation resource type: 'AWS::FakeService::DoesNotExist'/); }); - test("throws an exception when encountering a CFN function it doesn't support", () => { - expect(() => { - includeTestTemplate(stack, 'only-codecommit-repo-using-cfn-functions.json'); - }).toThrow(/Unsupported CloudFormation function 'Fn::DoesNotExist'/); - }); - test('throws an exception when encountering the CreationPolicy attribute in a resource', () => { expect(() => { includeTestTemplate(stack, 'resource-attribute-creation-policy.json'); diff --git a/packages/@aws-cdk/core/lib/cfn-fn.ts b/packages/@aws-cdk/core/lib/cfn-fn.ts index 88c27bb538e29..98a368b9fdc38 100644 --- a/packages/@aws-cdk/core/lib/cfn-fn.ts +++ b/packages/@aws-cdk/core/lib/cfn-fn.ts @@ -176,11 +176,12 @@ export class Fn { * The intrinsic function Fn::Transform specifies a macro to perform custom processing on part of a stack template. * Macros enable you to perform custom processing on templates, from simple actions like find-and-replace operations * to extensive transformations of entire templates. - * @param macroNameParameters The name of the macro to perform the processing, and the Parameters to pass to it. + * @param macroName The name of the macro to perform the processing + * @param parameters The parameters to be passed to the macro * @returns a token represented as a string */ - public static transform(macroNameParameters: string): string { - return new FnTransform(macroNameParameters).toString(); + public static transform(macroName: string, parameters: '{[name: string]: any}'): string { + return new FnTransform(macroName, parameters).toString(); } /** @@ -372,10 +373,12 @@ class FnFindInMap extends FnBase { */ class FnTransform extends FnBase { /** - * @param macroNameParameters The name of the macro to be invoked, and the parameters to pass to it + * creates an ``Fn::Transform`` function. + * @param macroName The name of the macro to be invoked + * @param parameters the parameters to pass to it */ - constructor(macroNameParameters: string) { - super('Fn::Transform', macroNameParameters); + constructor(macroName: string, parameters: '{[name: string]: any}') { + super('Fn::Transform', {Name: macroName, Parameters: parameters}); } } diff --git a/packages/@aws-cdk/core/lib/cfn-parse.ts b/packages/@aws-cdk/core/lib/cfn-parse.ts index d386c5f512e55..876635e9b57f1 100644 --- a/packages/@aws-cdk/core/lib/cfn-parse.ts +++ b/packages/@aws-cdk/core/lib/cfn-parse.ts @@ -209,7 +209,7 @@ function parseIfCfnIntrinsic(object: any): any { } case 'Fn::Transform': { const value = parseCfnValueToCdkValue(object[key]); - return Fn.transform(value); + return Fn.transform(value.Name, value.Parameters); } case 'Fn::Base64': { const value = parseCfnValueToCdkValue(object[key]); From 7ca707e91f463af8e035312acea1138634eb8e46 Mon Sep 17 00:00:00 2001 From: Calvin Combs Date: Tue, 16 Jun 2020 20:41:43 -0400 Subject: [PATCH 09/22] updated README to reflect the newly supported cloudformation functions --- .../@aws-cdk/cloudformation-include/README.md | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/@aws-cdk/cloudformation-include/README.md b/packages/@aws-cdk/cloudformation-include/README.md index a64d7b988e9bb..0a9b21dbcc173 100644 --- a/packages/@aws-cdk/cloudformation-include/README.md +++ b/packages/@aws-cdk/cloudformation-include/README.md @@ -136,16 +136,16 @@ All items unchecked below are currently not supported. - [x] Fn::GetAtt - [x] Fn::Join - [x] Fn::If -- [ ] Fn::And +- [x] Fn::And - [x] Fn::Equals -- [ ] Fn::Not -- [ ] Fn::Or -- [ ] Fn::Base64 -- [ ] Fn::Cidr -- [ ] Fn::FindInMap -- [ ] Fn::GetAZs -- [ ] Fn::ImportValue -- [ ] Fn::Select -- [ ] Fn::Split +- [x] Fn::Not +- [x] Fn::Or +- [x] Fn::Base64 +- [x] Fn::Cidr +- [x] Fn::FindInMap +- [x] Fn::GetAZs +- [x] Fn::ImportValue +- [x] Fn::Select +- [x] Fn::Split - [ ] Fn::Sub -- [ ] Fn::Transform +- [x] Fn::Transform From 63c27a775196a33b04fde0bcd0d822d87aa132f9 Mon Sep 17 00:00:00 2001 From: Calvin Combs Date: Wed, 17 Jun 2020 17:35:10 -0400 Subject: [PATCH 10/22] removed quotes from the type of Transform's parameter argument, modified the return type of transform to IResolvable, and updated transform docs --- .../functions-and-conditions.json | 246 +++++++++++------- packages/@aws-cdk/core/lib/cfn-fn.ts | 12 +- 2 files changed, 151 insertions(+), 107 deletions(-) diff --git a/packages/@aws-cdk/cloudformation-include/test/test-templates/functions-and-conditions.json b/packages/@aws-cdk/cloudformation-include/test/test-templates/functions-and-conditions.json index a9031ab3ae58c..873bbe2254d48 100644 --- a/packages/@aws-cdk/cloudformation-include/test/test-templates/functions-and-conditions.json +++ b/packages/@aws-cdk/cloudformation-include/test/test-templates/functions-and-conditions.json @@ -1,122 +1,168 @@ { - "Mappings" : { - "RegionMap" : { - "region-1" : { - "HVM64" : "name1", "HVMG2" : "name2" - } + "Mappings": { + "RegionMap": { + "region-1": { + "HVM64": "name1", + "HVMG2": "name2" } + } + }, + "Conditions": { + "AlwaysTrueCond": { + "Fn::Not": [ + { + "Fn::Equals": [ + { + "Ref": "AWS::Region" + }, + "completely-made-up-region" + ] + } + ] }, - "Conditions": { - "AlwaysTrueCond": { - "Fn::Not": [{ - "Fn::Equals": [{"Ref": "AWS::Region"}, "completely-made-up-region"]}] + "AlwaysFalseCond": { + "Fn::Equals": [ + { + "Ref": "AWS::Region" }, - "AlwaysFalseCond": { - "Fn::Equals": [{ "Ref": "AWS::Region" }, "completely-made-up-region"] + "completely-made-up-region" + ] + }, + "AndCond": { + "Fn::And": [ + { + "Condition": "AlwaysTrueCond" }, - "AndCond": { - "Fn::And": [ - {"Condition": "AlwaysTrueCond"}, - {"Condition": "AlwaysFalseCond"} - ] + { + "Condition": "AlwaysFalseCond" + } + ] + }, + "OrCond": { + "Fn::Or": [ + { + "Condition": "AlwaysTrueCond" }, - "OrCond": { - "Fn::Or": [ - {"Condition": "AlwaysTrueCond"}, - {"Condition": "AlwaysFalseCond"} - ] + { + "Condition": "AlwaysFalseCond" } - }, - "Resources": { - "Vpc": { - "Type" : "AWS::EC2::VPC", - "Properties" : { - "CidrBlock" : { - "Fn::If": [ - "AlwaysTrueCond", - { "Fn::Cidr": [ "192.168.1.1/24", 2] }, - { "Fn::Cidr": [ "10.0.0.0/24", 6, 5] } + ] + } + }, + "Resources": { + "Vpc": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": { + "Fn::If": [ + "AlwaysTrueCond", + { + "Fn::Cidr": [ + "192.168.1.1/24", + 2 ] - } + }, + { + "Fn::Cidr": [ + "10.0.0.0/24", + 6, + 5 + ] + } + ] } - }, - "Bucket": { - "Type": "AWS::S3::Bucket", - "Properties": { - "BucketName": { - "Fn::If": [ - {"Fn::Or": ["AlwaysFalseCond", "AlwaysFalseCond"]}, - "Unreachable", - {"Fn::FindInMap": [ + } + }, + "Bucket": { + "Type": "AWS::S3::Bucket", + "Properties": { + "BucketName": { + "Fn::If": [ + "OrCond", + { + "Fn::FindInMap": [ "RegionMap", "region-1", "HVM64" - ]} - ] - } + ] + }, + "Unreachable" + ] } - }, - "Subnet1" : { - "Type" : "AWS::EC2::Subnet", - "Properties" : { - "VpcId" : { - "Fn::If": [ - {"Fn::And": ["AlwaysTrueCond", "AlwaysTrueCond"]}, - { - "Fn::Split": [ - ",", - { "Fn::ImportValue" : "ImportedVpcId" } - ]}, - "Unreachable" - ] - }, - "CidrBlock" : "10.0.0.0/24", - "AvailabilityZone" : { - "Fn::Select" : [ - "0", - { - "Fn::GetAZs" : "" - } - ] - } + } + }, + "Subnet1": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Fn::If": [ + "AlwaysTrueCond", + { + "Fn::Split": [ + ",", + { + "Fn::ImportValue": "ImportedVpcId" + } + ] + }, + "Unreachable" + ] + }, + "CidrBlock": "10.0.0.0/24", + "AvailabilityZone": { + "Fn::Select": [ + "0", + { + "Fn::GetAZs": "" + } + ] } - }, - "Subnet2" : { - "Type" : "AWS::EC2::Subnet", - "Properties" : { - "VpcId" : { - "Fn::Select" : ["3", ["foo", "aValidVPCID", "foo2"]] - }, - "CidrBlock" : "10.0.0.0/24", - "AvailabilityZone" : { - "Fn::Select" : [ - "0", - { - "Fn::GetAZs" : "eu-west-2" - } + } + }, + "Subnet2": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Fn::Select": [ + "3", + [ + "foo", + "aValidVPCID", + "foo2" ] - } + ] + }, + "CidrBlock": "10.0.0.0/24", + "AvailabilityZone": { + "Fn::Select": [ + "0", + { + "Fn::GetAZs": "eu-west-2" + } + ] } - }, - "TransformBucket": { - "Type": "AWS::S3::Bucket", - "Properties": { - "BucketName": { - "Fn::If": [ - { "Fn::Or": ["AlwaysFalseCond", "AlwaysTrueCond"]}, { - "Fn::Transform": { - "Name": "AWS::Include", - "Parameters": { - "Location": "location", - "AnotherParameter": { - "Fn:Base64": "AnotherValue" - } + } + }, + "TransformBucket": { + "Type": "AWS::S3::Bucket", + "Properties": { + "BucketName": { + "Fn::If": [ + "AndCond", + { + "Fn::Transform": { + "Name": "AWS::Include", + "Parameters": { + "Location": "location", + "AnotherParameter": { + "Fn:Base64": "AnotherValue" } } } - ] - } + } + ] } } } - } \ No newline at end of file + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/core/lib/cfn-fn.ts b/packages/@aws-cdk/core/lib/cfn-fn.ts index 98a368b9fdc38..31269f531a792 100644 --- a/packages/@aws-cdk/core/lib/cfn-fn.ts +++ b/packages/@aws-cdk/core/lib/cfn-fn.ts @@ -173,15 +173,13 @@ export class Fn { } /** - * The intrinsic function Fn::Transform specifies a macro to perform custom processing on part of a stack template. - * Macros enable you to perform custom processing on templates, from simple actions like find-and-replace operations - * to extensive transformations of entire templates. + * Creates a token representing the ``Fn::Transform`` expression * @param macroName The name of the macro to perform the processing * @param parameters The parameters to be passed to the macro - * @returns a token represented as a string + * @returns a token representing the transform expression */ - public static transform(macroName: string, parameters: '{[name: string]: any}'): string { - return new FnTransform(macroName, parameters).toString(); + public static transform(macroName: string, parameters: { [name: string]: any }): IResolvable { + return new FnTransform(macroName, parameters); } /** @@ -377,7 +375,7 @@ class FnTransform extends FnBase { * @param macroName The name of the macro to be invoked * @param parameters the parameters to pass to it */ - constructor(macroName: string, parameters: '{[name: string]: any}') { + constructor(macroName: string, parameters: { [name: string]: any }) { super('Fn::Transform', {Name: macroName, Parameters: parameters}); } } From 41792710439cd994d2e582fbd69de0a696c5142e Mon Sep 17 00:00:00 2001 From: Calvin Combs Date: Wed, 17 Jun 2020 20:09:23 -0400 Subject: [PATCH 11/22] fixed teseting issue related to Fn::Select --- .../functions-and-conditions.json | 48 ++++++++----------- packages/@aws-cdk/core/lib/cfn-fn.ts | 3 +- packages/@aws-cdk/core/lib/cfn-parse.ts | 4 -- 3 files changed, 22 insertions(+), 33 deletions(-) diff --git a/packages/@aws-cdk/cloudformation-include/test/test-templates/functions-and-conditions.json b/packages/@aws-cdk/cloudformation-include/test/test-templates/functions-and-conditions.json index 873bbe2254d48..c0ac971e316a6 100644 --- a/packages/@aws-cdk/cloudformation-include/test/test-templates/functions-and-conditions.json +++ b/packages/@aws-cdk/cloudformation-include/test/test-templates/functions-and-conditions.json @@ -20,31 +20,20 @@ } ] }, - "AlwaysFalseCond": { - "Fn::Equals": [ - { - "Ref": "AWS::Region" - }, - "completely-made-up-region" - ] - }, "AndCond": { "Fn::And": [ { "Condition": "AlwaysTrueCond" }, { - "Condition": "AlwaysFalseCond" - } - ] - }, - "OrCond": { - "Fn::Or": [ - { - "Condition": "AlwaysTrueCond" - }, - { - "Condition": "AlwaysFalseCond" + "Fn::Or": [ + { + "Condition": "AlwaysTrueCond" + }, + { + "Condition": "AlwaysTrueCond" + } + ] } ] } @@ -59,14 +48,15 @@ { "Fn::Cidr": [ "192.168.1.1/24", - 2 + 2, + 5 ] }, { "Fn::Cidr": [ "10.0.0.0/24", - 6, - 5 + "6", + "5" ] } ] @@ -124,12 +114,14 @@ "Properties": { "VpcId": { "Fn::Select": [ - "3", - [ - "foo", - "aValidVPCID", - "foo2" - ] + 0, + { + "Fn::Cidr": [ + "10.0.0.0/24", + 5, + 2 + ] + } ] }, "CidrBlock": "10.0.0.0/24", diff --git a/packages/@aws-cdk/core/lib/cfn-fn.ts b/packages/@aws-cdk/core/lib/cfn-fn.ts index 31269f531a792..73d0f61c03236 100644 --- a/packages/@aws-cdk/core/lib/cfn-fn.ts +++ b/packages/@aws-cdk/core/lib/cfn-fn.ts @@ -174,6 +174,7 @@ export class Fn { /** * Creates a token representing the ``Fn::Transform`` expression + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-transform.html * @param macroName The name of the macro to perform the processing * @param parameters The parameters to be passed to the macro * @returns a token representing the transform expression @@ -376,7 +377,7 @@ class FnTransform extends FnBase { * @param parameters the parameters to pass to it */ constructor(macroName: string, parameters: { [name: string]: any }) { - super('Fn::Transform', {Name: macroName, Parameters: parameters}); + super('Fn::Transform', { Name: macroName, Parameters: parameters }); } } diff --git a/packages/@aws-cdk/core/lib/cfn-parse.ts b/packages/@aws-cdk/core/lib/cfn-parse.ts index 876635e9b57f1..f8c2a84a98fd4 100644 --- a/packages/@aws-cdk/core/lib/cfn-parse.ts +++ b/packages/@aws-cdk/core/lib/cfn-parse.ts @@ -181,10 +181,6 @@ function parseIfCfnIntrinsic(object: any): any { } case 'Fn::Cidr': { const value = parseCfnValueToCdkValue(object[key]); - - if (value.length === 2) { - return Fn.cidr(value[0], value[1]); - } return Fn.cidr(value[0], value[1], value[2]); } case 'Fn::FindInMap': { From 14a0d647bdf042f6707dd5457900985c1d3fdbbf Mon Sep 17 00:00:00 2001 From: Calvin Combs Date: Thu, 18 Jun 2020 11:03:33 -0400 Subject: [PATCH 12/22] merge conflict resolution --- .../test/valid-templates.test.ts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts b/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts index 987b96cf54ec2..1855c46acab5a 100644 --- a/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts +++ b/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts @@ -299,18 +299,6 @@ describe('CDK Include', () => { includeTestTemplate(stack, 'non-existent-resource-type.json'); }).toThrow(/Unrecognized CloudFormation resource type: 'AWS::FakeService::DoesNotExist'/); }); - - test('throws an exception when encountering the CreationPolicy attribute in a resource', () => { - expect(() => { - includeTestTemplate(stack, 'resource-attribute-creation-policy.json'); - }).toThrow(/The CreationPolicy resource attribute is not supported by cloudformation-include yet/); - }); - - test('throws an exception when encountering the UpdatePolicy attribute in a resource', () => { - expect(() => { - includeTestTemplate(stack, 'resource-attribute-update-policy.json'); - }).toThrow(/The UpdatePolicy resource attribute is not supported by cloudformation-include yet/); - }); }); interface IncludeTestTemplateProps { From 4c9d1eca5bf1ec9e6492932aec13404c46dcc398 Mon Sep 17 00:00:00 2001 From: Calvin Combs Date: Thu, 18 Jun 2020 12:57:08 -0400 Subject: [PATCH 13/22] fixed typo in condition name --- .../test/test-templates/functions-and-conditions.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/cloudformation-include/test/test-templates/functions-and-conditions.json b/packages/@aws-cdk/cloudformation-include/test/test-templates/functions-and-conditions.json index c0ac971e316a6..ce57b3e1a8b9f 100644 --- a/packages/@aws-cdk/cloudformation-include/test/test-templates/functions-and-conditions.json +++ b/packages/@aws-cdk/cloudformation-include/test/test-templates/functions-and-conditions.json @@ -68,7 +68,7 @@ "Properties": { "BucketName": { "Fn::If": [ - "OrCond", + "AndCond", { "Fn::FindInMap": [ "RegionMap", From 42c0228f7702216f7ccde494d9edaeb761134bf8 Mon Sep 17 00:00:00 2001 From: Calvin Combs Date: Thu, 18 Jun 2020 18:26:05 -0400 Subject: [PATCH 14/22] removed parameters from _toCloudFormation() --- .../cloudformation-include/lib/cfn-include.ts | 40 +++++++++++++++++-- .../bucket-with-parameters.json | 15 +++++++ .../test/valid-templates.test.ts | 14 +++++++ 3 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 packages/@aws-cdk/cloudformation-include/test/test-templates/bucket-with-parameters.json diff --git a/packages/@aws-cdk/cloudformation-include/lib/cfn-include.ts b/packages/@aws-cdk/cloudformation-include/lib/cfn-include.ts index 07c6dee3bfcbf..0c351bedb6781 100644 --- a/packages/@aws-cdk/cloudformation-include/lib/cfn-include.ts +++ b/packages/@aws-cdk/cloudformation-include/lib/cfn-include.ts @@ -23,6 +23,7 @@ export interface CfnIncludeProps { export class CfnInclude extends core.CfnElement { private readonly conditions: { [conditionName: string]: core.CfnCondition } = {}; private readonly resources: { [logicalId: string]: core.CfnResource } = {}; + private readonly parameters: { [parameterName: string]: core.CfnParameter } = {}; private readonly template: any; private readonly preserveLogicalIds: boolean; @@ -44,6 +45,11 @@ export class CfnInclude extends core.CfnElement { for (const logicalId of Object.keys(this.template.Resources || {})) { this.getOrCreateResource(logicalId); } + + // instantiate all parameters + for (const parameterName of Object.keys(this.template.Parameters || {})) { + this.createParameter(parameterName); + } } /** @@ -72,7 +78,7 @@ export class CfnInclude extends core.CfnElement { /** * Returns the CfnCondition object from the 'Conditions' - * section of the CloudFormation template with the give name. + * section of the CloudFormation template with the given name. * Any modifications performed on that object will be reflected in the resulting CDK template. * * If a Condition with the given name is not present in the template, @@ -88,14 +94,34 @@ export class CfnInclude extends core.CfnElement { return ret; } + /** + * Returns the CfnParameter object from the 'Parameters' + * section of the CloudFormation template with the given name. + * Any modifications performed on that object will be reflected in the resulting CDK template. + * + * If a Parameter with the given name is not present in the template, + * throws an exception. + * + * @param parameterName the name of the Parameter in the CloudFormation template file + */ + /* public getParameter(parameterName: string): core.CfnParameter { + const ret = this.parameters[parameterName]; + if (!ret) { + throw new Error(`Parameter with name '${parameterName}' was not found in the template`); + } + return ret; + } + */ + /** @internal */ public _toCloudFormation(): object { const ret: { [section: string]: any } = {}; for (const section of Object.keys(this.template)) { // render all sections of the template unchanged, - // except Conditions and Resources, which will be taken care of by the created L1s - if (section !== 'Conditions' && section !== 'Resources') { + // except Conditions, Resources, and Parameters, which will be taken care of by the created L1s + // ToDo + if (section !== 'Conditions' && section !== 'Resources' && section !== 'Parameters') { ret[section] = this.template[section]; } } @@ -103,6 +129,14 @@ export class CfnInclude extends core.CfnElement { return ret; } + private createParameter(parameterName: string): void { + const expression = cfn_parse.FromCloudFormation.parseValue(this.template.Parameters[parameterName]); + const CfnParameter = new core.CfnParameter(this, parameterName, expression); + + CfnParameter.overrideLogicalId(parameterName); + this.parameters[parameterName] = CfnParameter; + } + private createCondition(conditionName: string): void { // ToDo condition expressions can refer to other conditions - // will be important when implementing preserveLogicalIds=false diff --git a/packages/@aws-cdk/cloudformation-include/test/test-templates/bucket-with-parameters.json b/packages/@aws-cdk/cloudformation-include/test/test-templates/bucket-with-parameters.json new file mode 100644 index 0000000000000..0104ef6541831 --- /dev/null +++ b/packages/@aws-cdk/cloudformation-include/test/test-templates/bucket-with-parameters.json @@ -0,0 +1,15 @@ +{ + "Parameters": { + "BucketName": "MyS3Bucket" + }, + "Resources": { + "Bucket": { + "Type": "AWS::S3::Bucket", + "Properties": { + "BucketName": { + "Ref": "BucketName" + } + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts b/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts index 1855c46acab5a..52cf132eaab46 100644 --- a/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts +++ b/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts @@ -251,6 +251,19 @@ describe('CDK Include', () => { ); }); + test("correctly parses templates with parameters", () => { + const cfnTemplate = includeTestTemplate(stack, 'bucket-with-parameters.json'); + //const bucketNameParam = cfnTemplate.getParameter('BucketName'); + + expect(stack).toHaveResourceLike('AWS::S3::Bucket', { + "Properties": { + "BucketName": "MyS3Bucket" + } + }); + + //expect(bucketNameParam).toBe("MyS3Bucket"); + }); + test('reflects changes to a retrieved CfnCondition object in the resulting template', () => { const cfnTemplate = includeTestTemplate(stack, 'resource-attribute-condition.json'); const alwaysFalseCondition = cfnTemplate.getCondition('AlwaysFalseCond'); @@ -299,6 +312,7 @@ describe('CDK Include', () => { includeTestTemplate(stack, 'non-existent-resource-type.json'); }).toThrow(/Unrecognized CloudFormation resource type: 'AWS::FakeService::DoesNotExist'/); }); + }); interface IncludeTestTemplateProps { From 6a2df1e910e4302c8348827bc02f6b2d8e112ada Mon Sep 17 00:00:00 2001 From: Calvin Combs Date: Fri, 19 Jun 2020 13:23:02 -0400 Subject: [PATCH 15/22] added support for parameters in templates --- .../cloudformation-include/lib/cfn-include.ts | 56 ++++++++++--------- .../bucket-with-parameters.json | 6 +- .../test/valid-templates.test.ts | 45 +++++++++++++-- 3 files changed, 74 insertions(+), 33 deletions(-) diff --git a/packages/@aws-cdk/cloudformation-include/lib/cfn-include.ts b/packages/@aws-cdk/cloudformation-include/lib/cfn-include.ts index 0c351bedb6781..df26cc198d5b2 100644 --- a/packages/@aws-cdk/cloudformation-include/lib/cfn-include.ts +++ b/packages/@aws-cdk/cloudformation-include/lib/cfn-include.ts @@ -23,7 +23,7 @@ export interface CfnIncludeProps { export class CfnInclude extends core.CfnElement { private readonly conditions: { [conditionName: string]: core.CfnCondition } = {}; private readonly resources: { [logicalId: string]: core.CfnResource } = {}; - private readonly parameters: { [parameterName: string]: core.CfnParameter } = {}; + private readonly parameters: { [logicalId: string]: core.CfnParameter } = {}; private readonly template: any; private readonly preserveLogicalIds: boolean; @@ -47,27 +47,11 @@ export class CfnInclude extends core.CfnElement { } // instantiate all parameters - for (const parameterName of Object.keys(this.template.Parameters || {})) { - this.createParameter(parameterName); + for (const logicalId of Object.keys(this.template.Parameters || {})) { + this.createParameter(logicalId); } } - /** - * Returns the low-level CfnResource from the template with the given logical ID. - * Any modifications performed on that resource will be reflected in the resulting CDK template. - * - * The returned object will be of the proper underlying class; - * you can always cast it to the correct type in your code: - * - * // assume the template contains an AWS::S3::Bucket with logical ID 'Bucket' - * const cfnBucket = cfnTemplate.getResource('Bucket') as s3.CfnBucket; - * // cfnBucket is of type s3.CfnBucket - * - * If the template does not contain a resource with the given logical ID, - * an exception will be thrown. - * - * @param logicalId the logical ID of the resource in the CloudFormation template file - */ public getResource(logicalId: string): core.CfnResource { const ret = this.resources[logicalId]; if (!ret) { @@ -94,6 +78,14 @@ export class CfnInclude extends core.CfnElement { return ret; } + public getParameter(parameterName: string): core.CfnParameter { + const ret = this.parameters[parameterName]; + if (!ret) { + throw new Error(`Parameter with name '${parameterName}' was not found in the template`); + } + return ret; + } + /** * Returns the CfnParameter object from the 'Parameters' * section of the CloudFormation template with the given name. @@ -102,7 +94,7 @@ export class CfnInclude extends core.CfnElement { * If a Parameter with the given name is not present in the template, * throws an exception. * - * @param parameterName the name of the Parameter in the CloudFormation template file + * @param logicalId the name of the Parameter in the CloudFormation template file */ /* public getParameter(parameterName: string): core.CfnParameter { const ret = this.parameters[parameterName]; @@ -129,12 +121,24 @@ export class CfnInclude extends core.CfnElement { return ret; } - private createParameter(parameterName: string): void { - const expression = cfn_parse.FromCloudFormation.parseValue(this.template.Parameters[parameterName]); - const CfnParameter = new core.CfnParameter(this, parameterName, expression); - - CfnParameter.overrideLogicalId(parameterName); - this.parameters[parameterName] = CfnParameter; + private createParameter(logicalId: string): void { + const expression = cfn_parse.FromCloudFormation.parseValue(this.template.Parameters[logicalId]); + const expressionCaseCorrected = { + type: expression.Type, + default: expression.Default, + allowedPattern: expression.AllowedPattern, + constraintDescription: expression.ConstraintDescription, + description: expression.Description, + maxLength: expression.MaxLength, + maxValue: expression.MaxValue, + minLength: expression.MinLength, + minValue: expression.MinValue, + noEcho: expression.NoEcho, + }; + const CfnParameter = new core.CfnParameter(this, logicalId, expressionCaseCorrected); + + CfnParameter.overrideLogicalId(logicalId); + this.parameters[logicalId] = CfnParameter; } private createCondition(conditionName: string): void { diff --git a/packages/@aws-cdk/cloudformation-include/test/test-templates/bucket-with-parameters.json b/packages/@aws-cdk/cloudformation-include/test/test-templates/bucket-with-parameters.json index 0104ef6541831..531db51c9f10d 100644 --- a/packages/@aws-cdk/cloudformation-include/test/test-templates/bucket-with-parameters.json +++ b/packages/@aws-cdk/cloudformation-include/test/test-templates/bucket-with-parameters.json @@ -1,6 +1,10 @@ { "Parameters": { - "BucketName": "MyS3Bucket" + "BucketName": { + "Default": "MyS3Bucket", + "Description": "The name of your bucket", + "Type": "String" + } }, "Resources": { "Bucket": { diff --git a/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts b/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts index 52cf132eaab46..a7e80df958d54 100644 --- a/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts +++ b/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts @@ -253,15 +253,48 @@ describe('CDK Include', () => { test("correctly parses templates with parameters", () => { const cfnTemplate = includeTestTemplate(stack, 'bucket-with-parameters.json'); - //const bucketNameParam = cfnTemplate.getParameter('BucketName'); + const param = cfnTemplate.getParameter('BucketName'); + const bucket = new s3.CfnBucket(stack, "newBucket", {"bucketName": param.valueAsString}); - expect(stack).toHaveResourceLike('AWS::S3::Bucket', { - "Properties": { - "BucketName": "MyS3Bucket" + expect(stack).toMatchTemplate( + { + "Resources": { + "Bucket": { + "Type": "AWS::S3::Bucket", + "Properties": { + "BucketName": { + "Ref": "BucketName" + } + } + }, + "newBucket": { + "Type": "AWS::S3::Bucket", + "Properties": { + "BucketName": { + "Ref": "BucketName" + } + } + } + }, + "Parameters": { + "BucketName": { + "Type": "String", + "Default": "MyS3Bucket", + "Description": "The name of your bucket" + } + } } - }); + ); + + expect(bucket.bucketName).toBeDefined(); + }); - //expect(bucketNameParam).toBe("MyS3Bucket"); + test('getParameter() throws an exception when a parameter is not found', () => { + const cfnTemplate = includeTestTemplate(stack, 'bucket-with-parameters.json'); + + expect(() => { + cfnTemplate.getParameter("FakeBucketNameThatDoesNotExist"); + }).toThrow(/Parameter with name 'FakeBucketNameThatDoesNotExist' was not found in the template/); }); test('reflects changes to a retrieved CfnCondition object in the resulting template', () => { From cd27ff6053f12d310d823c6f0e88dc3e0afb5d25 Mon Sep 17 00:00:00 2001 From: Calvin Combs Date: Fri, 19 Jun 2020 14:59:14 -0400 Subject: [PATCH 16/22] updated documentation --- .../cloudformation-include/lib/cfn-include.ts | 13 ++++++++++- .../test/valid-templates.test.ts | 22 +++++++++---------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/packages/@aws-cdk/cloudformation-include/lib/cfn-include.ts b/packages/@aws-cdk/cloudformation-include/lib/cfn-include.ts index df26cc198d5b2..b9a0ff9f4cc72 100644 --- a/packages/@aws-cdk/cloudformation-include/lib/cfn-include.ts +++ b/packages/@aws-cdk/cloudformation-include/lib/cfn-include.ts @@ -78,6 +78,17 @@ export class CfnInclude extends core.CfnElement { return ret; } + /** + * Returns the CfnParameter object from the 'Parameters' + * section of the included template + * Any modifications performed on that object will be reflected in the resulting CDK template. + * + * If a Parameter with the given name is not present in the template, + * throws an exception. + * + * @param parameterName the name of the parameter to retrieve + */ + public getParameter(parameterName: string): core.CfnParameter { const ret = this.parameters[parameterName]; if (!ret) { @@ -136,7 +147,7 @@ export class CfnInclude extends core.CfnElement { noEcho: expression.NoEcho, }; const CfnParameter = new core.CfnParameter(this, logicalId, expressionCaseCorrected); - + CfnParameter.overrideLogicalId(logicalId); this.parameters[logicalId] = CfnParameter; } diff --git a/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts b/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts index 47d7d70899fec..fe9c50341d6db 100644 --- a/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts +++ b/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts @@ -263,27 +263,27 @@ describe('CDK Include', () => { "Type": "AWS::S3::Bucket", "Properties": { "BucketName": { - "Ref": "BucketName" - } - } + "Ref": "BucketName", + }, + }, }, "newBucket": { "Type": "AWS::S3::Bucket", "Properties": { "BucketName": { - "Ref": "BucketName" - } - } - } + "Ref": "BucketName", + }, + }, + }, }, "Parameters": { "BucketName": { "Type": "String", "Default": "MyS3Bucket", - "Description": "The name of your bucket" - } - } - } + "Description": "The name of your bucket", + }, + }, + }, ); expect(bucket.bucketName).toBeDefined(); From 1e72465697888396fb7b3ba0594ab3681f80cad2 Mon Sep 17 00:00:00 2001 From: Calvin Combs Date: Fri, 19 Jun 2020 15:06:01 -0400 Subject: [PATCH 17/22] updated readme --- packages/@aws-cdk/cloudformation-include/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/cloudformation-include/README.md b/packages/@aws-cdk/cloudformation-include/README.md index 4023f2b214069..188f9989075ea 100644 --- a/packages/@aws-cdk/cloudformation-include/README.md +++ b/packages/@aws-cdk/cloudformation-include/README.md @@ -115,7 +115,7 @@ All items unchecked below are currently not supported. ### Ability to retrieve CloudFormation objects from the template: - [x] Resources -- [ ] Parameters +- [x] Parameters - [x] Conditions - [ ] Outputs From 070f902759c5f8528cf3a509dada354d115972ce Mon Sep 17 00:00:00 2001 From: Calvin Combs Date: Fri, 19 Jun 2020 18:22:52 -0400 Subject: [PATCH 18/22] incorporated adam's comments --- .../cloudformation-include/lib/cfn-include.ts | 55 ++++++++----------- .../bucket-with-parameters.json | 30 +++++++++- .../test/valid-templates.test.ts | 46 ++++++---------- 3 files changed, 70 insertions(+), 61 deletions(-) diff --git a/packages/@aws-cdk/cloudformation-include/lib/cfn-include.ts b/packages/@aws-cdk/cloudformation-include/lib/cfn-include.ts index b9a0ff9f4cc72..7906bd92c5cb5 100644 --- a/packages/@aws-cdk/cloudformation-include/lib/cfn-include.ts +++ b/packages/@aws-cdk/cloudformation-include/lib/cfn-include.ts @@ -36,6 +36,10 @@ export class CfnInclude extends core.CfnElement { // ToDo implement preserveLogicalIds=false this.preserveLogicalIds = true; + // instantiate all parameters + for (const logicalId of Object.keys(this.template.Parameters || {})) { + this.createParameter(logicalId); + } // first, instantiate the conditions for (const conditionName of Object.keys(this.template.Conditions || {})) { this.createCondition(conditionName); @@ -45,13 +49,24 @@ export class CfnInclude extends core.CfnElement { for (const logicalId of Object.keys(this.template.Resources || {})) { this.getOrCreateResource(logicalId); } - - // instantiate all parameters - for (const logicalId of Object.keys(this.template.Parameters || {})) { - this.createParameter(logicalId); - } } + /** + * Returns the low-level CfnResource from the template with the given logical ID. + * Any modifications performed on that resource will be reflected in the resulting CDK template. + * + * The returned object will be of the proper underlying class; + * you can always cast it to the correct type in your code: + * + * // assume the template contains an AWS::S3::Bucket with logical ID 'Bucket' + * const cfnBucket = cfnTemplate.getResource('Bucket') as s3.CfnBucket; + * // cfnBucket is of type s3.CfnBucket + * + * If the template does not contain a resource with the given logical ID, + * an exception will be thrown. + * + * @param logicalId the logical ID of the resource in the CloudFormation template file + */ public getResource(logicalId: string): core.CfnResource { const ret = this.resources[logicalId]; if (!ret) { @@ -88,7 +103,6 @@ export class CfnInclude extends core.CfnElement { * * @param parameterName the name of the parameter to retrieve */ - public getParameter(parameterName: string): core.CfnParameter { const ret = this.parameters[parameterName]; if (!ret) { @@ -97,25 +111,6 @@ export class CfnInclude extends core.CfnElement { return ret; } - /** - * Returns the CfnParameter object from the 'Parameters' - * section of the CloudFormation template with the given name. - * Any modifications performed on that object will be reflected in the resulting CDK template. - * - * If a Parameter with the given name is not present in the template, - * throws an exception. - * - * @param logicalId the name of the Parameter in the CloudFormation template file - */ - /* public getParameter(parameterName: string): core.CfnParameter { - const ret = this.parameters[parameterName]; - if (!ret) { - throw new Error(`Parameter with name '${parameterName}' was not found in the template`); - } - return ret; - } - */ - /** @internal */ public _toCloudFormation(): object { const ret: { [section: string]: any } = {}; @@ -123,7 +118,6 @@ export class CfnInclude extends core.CfnElement { for (const section of Object.keys(this.template)) { // render all sections of the template unchanged, // except Conditions, Resources, and Parameters, which will be taken care of by the created L1s - // ToDo if (section !== 'Conditions' && section !== 'Resources' && section !== 'Parameters') { ret[section] = this.template[section]; } @@ -134,7 +128,7 @@ export class CfnInclude extends core.CfnElement { private createParameter(logicalId: string): void { const expression = cfn_parse.FromCloudFormation.parseValue(this.template.Parameters[logicalId]); - const expressionCaseCorrected = { + const cfnParameter = new core.CfnParameter(this, logicalId, { type: expression.Type, default: expression.Default, allowedPattern: expression.AllowedPattern, @@ -145,11 +139,10 @@ export class CfnInclude extends core.CfnElement { minLength: expression.MinLength, minValue: expression.MinValue, noEcho: expression.NoEcho, - }; - const CfnParameter = new core.CfnParameter(this, logicalId, expressionCaseCorrected); + }); - CfnParameter.overrideLogicalId(logicalId); - this.parameters[logicalId] = CfnParameter; + cfnParameter.overrideLogicalId(logicalId); + this.parameters[logicalId] = cfnParameter; } private createCondition(conditionName: string): void { diff --git a/packages/@aws-cdk/cloudformation-include/test/test-templates/bucket-with-parameters.json b/packages/@aws-cdk/cloudformation-include/test/test-templates/bucket-with-parameters.json index 531db51c9f10d..deec4ffa24e81 100644 --- a/packages/@aws-cdk/cloudformation-include/test/test-templates/bucket-with-parameters.json +++ b/packages/@aws-cdk/cloudformation-include/test/test-templates/bucket-with-parameters.json @@ -2,8 +2,21 @@ "Parameters": { "BucketName": { "Default": "MyS3Bucket", + "AllowedPattern": "^[a-zA-Z0-9]*$", + "ConstraintDescription": "a string consisting only of alphanumeric characters", "Description": "The name of your bucket", - "Type": "String" + "MaxLength": "10", + "MinLength": "1", + "Type": "String", + "NoEcho": "true" + }, + "CorsMaxAge": { + "Default": "3", + "Description": "the time in seconds that a browser will cache the preflight response", + "MaxValue": "300", + "MinValue": "0", + "Type": "Number", + "NoEcho": "true" } }, "Resources": { @@ -12,6 +25,21 @@ "Properties": { "BucketName": { "Ref": "BucketName" + }, + "CorsConfiguration": { + "CorsRules": [{ + "AllowedMethods": [ + "GET", + "POST" + ], + "AllowedOrigins": [ + "origin1", + "origin2" + ], + "MaxAge": { + "Ref": "CorsMaxAge" + } + }] } } } diff --git a/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts b/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts index fe9c50341d6db..91cc14be619b2 100644 --- a/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts +++ b/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts @@ -253,43 +253,31 @@ describe('CDK Include', () => { test("correctly parses templates with parameters", () => { const cfnTemplate = includeTestTemplate(stack, 'bucket-with-parameters.json'); + const originalTemplate = loadTestFileToJsObject('bucket-with-parameters.json'); const param = cfnTemplate.getParameter('BucketName'); - const bucket = new s3.CfnBucket(stack, "newBucket", {"bucketName": param.valueAsString}); + new s3.CfnBucket(stack, "NewBucket", { + "bucketName": param.valueAsString, + }); - expect(stack).toMatchTemplate( - { - "Resources": { - "Bucket": { - "Type": "AWS::S3::Bucket", - "Properties": { - "BucketName": { - "Ref": "BucketName", - }, - }, - }, - "newBucket": { - "Type": "AWS::S3::Bucket", - "Properties": { - "BucketName": { - "Ref": "BucketName", - }, + expect(stack).toMatchTemplate({ + "Resources": { + ...originalTemplate.Resources, + "NewBucket": { + "Type": "AWS::S3::Bucket", + "Properties": { + "BucketName": { + "Ref": "BucketName", }, }, }, - "Parameters": { - "BucketName": { - "Type": "String", - "Default": "MyS3Bucket", - "Description": "The name of your bucket", - }, - }, }, - ); - - expect(bucket.bucketName).toBeDefined(); + "Parameters": { + ...originalTemplate.Parameters, + }, + }); }); - test('getParameter() throws an exception when a parameter is not found', () => { + test('getParameter() throws an exception if asked for a Parameter with a name that is not present in the template', () => { const cfnTemplate = includeTestTemplate(stack, 'bucket-with-parameters.json'); expect(() => { From b10a1ed08ba7171ea5394ed8f5baa36f4d32f319 Mon Sep 17 00:00:00 2001 From: Calvin Combs Date: Fri, 19 Jun 2020 19:08:41 -0400 Subject: [PATCH 19/22] fixed spacing --- packages/@aws-cdk/cloudformation-include/lib/cfn-include.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/@aws-cdk/cloudformation-include/lib/cfn-include.ts b/packages/@aws-cdk/cloudformation-include/lib/cfn-include.ts index 7906bd92c5cb5..600a97d65f991 100644 --- a/packages/@aws-cdk/cloudformation-include/lib/cfn-include.ts +++ b/packages/@aws-cdk/cloudformation-include/lib/cfn-include.ts @@ -40,6 +40,7 @@ export class CfnInclude extends core.CfnElement { for (const logicalId of Object.keys(this.template.Parameters || {})) { this.createParameter(logicalId); } + // first, instantiate the conditions for (const conditionName of Object.keys(this.template.Conditions || {})) { this.createCondition(conditionName); From f07037b9fbef3ca283c3fad09b2f4e8acf4a494e Mon Sep 17 00:00:00 2001 From: Adam Ruka Date: Fri, 19 Jun 2020 16:23:00 -0700 Subject: [PATCH 20/22] Update no longer up-to-date comments in CfnInclude's constructor --- packages/@aws-cdk/cloudformation-include/lib/cfn-include.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/cloudformation-include/lib/cfn-include.ts b/packages/@aws-cdk/cloudformation-include/lib/cfn-include.ts index 600a97d65f991..b7f712c23af56 100644 --- a/packages/@aws-cdk/cloudformation-include/lib/cfn-include.ts +++ b/packages/@aws-cdk/cloudformation-include/lib/cfn-include.ts @@ -41,12 +41,12 @@ export class CfnInclude extends core.CfnElement { this.createParameter(logicalId); } - // first, instantiate the conditions + // instantiate the conditions for (const conditionName of Object.keys(this.template.Conditions || {})) { this.createCondition(conditionName); } - // then, instantiate all resources as CDK L1 objects + // instantiate all resources as CDK L1 objects for (const logicalId of Object.keys(this.template.Resources || {})) { this.getOrCreateResource(logicalId); } From c01cc4a9a2dcca75ca7b06dd1abd39ad841bc68b Mon Sep 17 00:00:00 2001 From: Adam Ruka Date: Fri, 19 Jun 2020 16:25:01 -0700 Subject: [PATCH 21/22] Make string literals consistent --- .../cloudformation-include/test/valid-templates.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts b/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts index 91cc14be619b2..1481c68e50270 100644 --- a/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts +++ b/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts @@ -255,8 +255,8 @@ describe('CDK Include', () => { const cfnTemplate = includeTestTemplate(stack, 'bucket-with-parameters.json'); const originalTemplate = loadTestFileToJsObject('bucket-with-parameters.json'); const param = cfnTemplate.getParameter('BucketName'); - new s3.CfnBucket(stack, "NewBucket", { - "bucketName": param.valueAsString, + new s3.CfnBucket(stack, 'NewBucket', { + bucketName: param.valueAsString, }); expect(stack).toMatchTemplate({ @@ -281,7 +281,7 @@ describe('CDK Include', () => { const cfnTemplate = includeTestTemplate(stack, 'bucket-with-parameters.json'); expect(() => { - cfnTemplate.getParameter("FakeBucketNameThatDoesNotExist"); + cfnTemplate.getParameter('FakeBucketNameThatDoesNotExist'); }).toThrow(/Parameter with name 'FakeBucketNameThatDoesNotExist' was not found in the template/); }); From a45f168f1121a783cbb3edfd21e7d7bb6e9b6893 Mon Sep 17 00:00:00 2001 From: Adam Ruka Date: Fri, 19 Jun 2020 16:26:19 -0700 Subject: [PATCH 22/22] Move the loading of the test file to the 'then' part of the test --- .../cloudformation-include/test/valid-templates.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts b/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts index 1481c68e50270..f09331895f079 100644 --- a/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts +++ b/packages/@aws-cdk/cloudformation-include/test/valid-templates.test.ts @@ -253,12 +253,12 @@ describe('CDK Include', () => { test("correctly parses templates with parameters", () => { const cfnTemplate = includeTestTemplate(stack, 'bucket-with-parameters.json'); - const originalTemplate = loadTestFileToJsObject('bucket-with-parameters.json'); const param = cfnTemplate.getParameter('BucketName'); new s3.CfnBucket(stack, 'NewBucket', { bucketName: param.valueAsString, }); + const originalTemplate = loadTestFileToJsObject('bucket-with-parameters.json'); expect(stack).toMatchTemplate({ "Resources": { ...originalTemplate.Resources,