Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cfn-include): add support for retrieving parameter objects #8658

Merged
merged 35 commits into from
Jun 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
db60c27
doc: added slack link to readme
comcalvi Jun 4, 2020
5924f3b
Merge branch 'master' into master
comcalvi Jun 5, 2020
f0c85a3
Update README.md
comcalvi Jun 5, 2020
f37e60e
Merge branch 'master' into master
mergify[bot] Jun 5, 2020
83ed743
Merge branch 'master' of https://github.com/aws/aws-cdk
comcalvi Jun 15, 2020
c6664af
added support for Fn::Select, Fn::FindInMap, Fn::Cidr, Fn::GetAZs, Fn…
comcalvi Jun 15, 2020
d0f64d2
added support for the 'Fn::Transform' cloudformation intrinsic function.
comcalvi Jun 16, 2020
d69e46d
added support for the Fn::Base64 Intrinsic Function
comcalvi Jun 16, 2020
df1446a
tested more complex combinations of conditional and non-conditional i…
comcalvi Jun 16, 2020
132cb4d
fixed linter issues
comcalvi Jun 16, 2020
ae7c570
implmented Adam's requests and fixed additional linter issues
comcalvi Jun 17, 2020
7ca707e
updated README to reflect the newly supported cloudformation functions
comcalvi Jun 17, 2020
63c27a7
removed quotes from the type of Transform's parameter argument, modif…
comcalvi Jun 17, 2020
4179271
fixed teseting issue related to Fn::Select
comcalvi Jun 18, 2020
117ae63
Merge branch 'master' into CfnFunctions
comcalvi Jun 18, 2020
dbb9ef8
fixing merge conflicts
comcalvi Jun 18, 2020
bdab761
Merge branch 'master' of https://github.com/aws/aws-cdk
comcalvi Jun 18, 2020
d390580
Merge branch 'master' of https://github.com/aws/aws-cdk into CfnFunct…
comcalvi Jun 18, 2020
14a0d64
merge conflict resolution
comcalvi Jun 18, 2020
dfb42b9
Merge branch 'CfnFunctions' of github.com:comcalvi/aws-cdk into CfnFu…
comcalvi Jun 18, 2020
9f1b2d9
Merge branch 'master' of https://github.com/aws/aws-cdk into CfnFunct…
comcalvi Jun 18, 2020
4c9d1ec
fixed typo in condition name
comcalvi Jun 18, 2020
e15c187
Merge branch 'CfnFunctions'
comcalvi Jun 18, 2020
82c4317
Merge branch 'master' of https://github.com/aws/aws-cdk
comcalvi Jun 18, 2020
42c0228
removed parameters from _toCloudFormation()
comcalvi Jun 18, 2020
6a2df1e
added support for parameters in templates
comcalvi Jun 19, 2020
43198b7
fixed merge conflict
comcalvi Jun 19, 2020
cd27ff6
updated documentation
comcalvi Jun 19, 2020
1e72465
updated readme
comcalvi Jun 19, 2020
070f902
incorporated adam's comments
comcalvi Jun 19, 2020
b10a1ed
fixed spacing
comcalvi Jun 19, 2020
f07037b
Update no longer up-to-date comments in CfnInclude's constructor
skinny85 Jun 19, 2020
c01cc4a
Make string literals consistent
skinny85 Jun 19, 2020
a45f168
Move the loading of the test file to the 'then' part of the test
skinny85 Jun 19, 2020
4c95ced
Merge branch 'master' into CfnParams
mergify[bot] Jun 20, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/@aws-cdk/cloudformation-include/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
53 changes: 48 additions & 5 deletions packages/@aws-cdk/cloudformation-include/lib/cfn-include.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: { [logicalId: string]: core.CfnParameter } = {};
private readonly template: any;
private readonly preserveLogicalIds: boolean;

Expand All @@ -35,12 +36,17 @@ export class CfnInclude extends core.CfnElement {
// ToDo implement preserveLogicalIds=false
this.preserveLogicalIds = true;

// first, instantiate the conditions
// instantiate all parameters
for (const logicalId of Object.keys(this.template.Parameters || {})) {
this.createParameter(logicalId);
}

// 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);
}
Expand Down Expand Up @@ -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,
Expand All @@ -88,21 +94,58 @@ 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) {
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
if (section !== 'Conditions' && section !== 'Resources' && section !== 'Parameters') {
ret[section] = this.template[section];
}
}

return ret;
}

private createParameter(logicalId: string): void {
const expression = cfn_parse.FromCloudFormation.parseValue(this.template.Parameters[logicalId]);
const cfnParameter = new core.CfnParameter(this, logicalId, {
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,
});

cfnParameter.overrideLogicalId(logicalId);
this.parameters[logicalId] = cfnParameter;
}

private createCondition(conditionName: string): void {
// ToDo condition expressions can refer to other conditions -
// will be important when implementing preserveLogicalIds=false
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"Parameters": {
"BucketName": {
"Default": "MyS3Bucket",
"AllowedPattern": "^[a-zA-Z0-9]*$",
"ConstraintDescription": "a string consisting only of alphanumeric characters",
"Description": "The name of your bucket",
"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": {
"Bucket": {
"Type": "AWS::S3::Bucket",
"Properties": {
"BucketName": {
"Ref": "BucketName"
},
"CorsConfiguration": {
"CorsRules": [{
"AllowedMethods": [
"GET",
"POST"
],
"AllowedOrigins": [
"origin1",
"origin2"
],
"MaxAge": {
"Ref": "CorsMaxAge"
}
}]
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,40 @@ describe('CDK Include', () => {
);
});

test("correctly parses templates with parameters", () => {
const cfnTemplate = includeTestTemplate(stack, '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,
"NewBucket": {
"Type": "AWS::S3::Bucket",
"Properties": {
"BucketName": {
"Ref": "BucketName",
},
},
},
},
"Parameters": {
...originalTemplate.Parameters,
},
});
});

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(() => {
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', () => {
const cfnTemplate = includeTestTemplate(stack, 'resource-attribute-condition.json');
const alwaysFalseCondition = cfnTemplate.getCondition('AlwaysFalseCond');
Expand Down