Skip to content

Commit

Permalink
fix(cfn-include): allow parameters to be replaced across nested stacks (
Browse files Browse the repository at this point in the history
#9842)

Fixes #9838

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
comcalvi committed Sep 2, 2020
1 parent 9e4c6d2 commit 9ea8d5c
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 11 deletions.
26 changes: 17 additions & 9 deletions packages/@aws-cdk/cloudformation-include/lib/cfn-include.ts
Original file line number Diff line number Diff line change
Expand Up @@ -558,23 +558,31 @@ export class CfnInclude extends core.CfnElement {

const nestedStackProps = cfnParser.parseValue(nestedStackAttributes.Properties);
const nestedStack = new core.NestedStack(this, nestedStackId, {
parameters: nestedStackProps.Parameters,
parameters: this.parametersForNestedStack(nestedStackProps.Parameters, nestedStackId),
notificationArns: nestedStackProps.NotificationArns,
timeout: nestedStackProps.Timeout,
});
const template = new CfnInclude(nestedStack, nestedStackId, this.nestedStacksToInclude[nestedStackId]);
this.nestedStacks[nestedStackId] = { stack: nestedStack, includedTemplate: template };

// we know this is never undefined for nested stacks
const nestedStackResource: core.CfnResource = nestedStack.nestedStackResource!;
cfnParser.handleAttributes(nestedStackResource, nestedStackAttributes, nestedStackId);
return nestedStackResource;
}

const propStack = this.nestedStacksToInclude[nestedStackId];
const template = new CfnInclude(nestedStack, nestedStackId, {
templateFile: propStack.templateFile,
nestedStacks: propStack.nestedStacks,
});
const includedStack: IncludedNestedStack = { stack: nestedStack, includedTemplate: template };
this.nestedStacks[nestedStackId] = includedStack;
private parametersForNestedStack(parameters: any, nestedStackId: string): { [key: string]: any } | undefined {
if (parameters == null) {
return undefined;
}

return nestedStackResource;
const parametersToReplace = this.nestedStacksToInclude[nestedStackId].parameters ?? {};
const ret: { [key: string]: string } = {};
for (const paramName of Object.keys(parameters)) {
if (!(paramName in parametersToReplace)) {
ret[paramName] = parameters[paramName];
}
}
return ret;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as path from 'path';
import { ResourcePart } from '@aws-cdk/assert';
import { ABSENT, ResourcePart } from '@aws-cdk/assert';
import '@aws-cdk/assert/jest';
import * as s3 from '@aws-cdk/aws-s3';
import * as core from '@aws-cdk/core';
Expand All @@ -9,7 +9,7 @@ import * as futils from '../lib/file-utils';
/* eslint-disable quote-props */
/* eslint-disable quotes */

describe('CDK Include', () => {
describe('CDK Include for nested stacks', () => {
let stack: core.Stack;

beforeEach(() => {
Expand Down Expand Up @@ -612,6 +612,66 @@ describe('CDK Include', () => {
);
});
});

describe('for a parameter passed to the included child stack', () => {
let parentStack: core.Stack;
let childStack: core.Stack;

beforeAll(() => {
parentStack = new core.Stack();
const parentTemplate = new inc.CfnInclude(parentStack, 'ParentStack', {
templateFile: testTemplateFilePath('parent-two-parameters.json'),
nestedStacks: {
'ChildStack': {
templateFile: testTemplateFilePath('child-two-parameters.json'),
parameters: {
'FirstParameter': 'test-value',
},
},
},
});
childStack = parentTemplate.getNestedStack('ChildStack').stack;
});

test('correctly removes the parameter from the child stack', () => {
expect(childStack).toMatchTemplate({
"Parameters": {
"SecondParameter": {
"Type": "String",
},
},
"Resources": {
"BucketImport": {
"Type": "AWS::S3::Bucket",
"Properties": {
"BucketName": "test-value",
"AccessControl": {
"Ref": "SecondParameter",
},
},
},
"GrandChildStack": {
"Type": "AWS::CloudFormation::Stack",
"Properties": {
"TemplateURL": "https://cfn-templates-set.s3.amazonaws.com/grandchild-import-stack.json",
"Parameters": {
"FirstParameter": "test-value",
},
},
},
},
});
});

test('correctly removes the parameter from the parent stack', () => {
expect(parentStack).toHaveResourceLike('AWS::CloudFormation::Stack', {
"Parameters": {
"FirstParameter": ABSENT,
"SecondParameter": "second-value",
},
});
});
});
});

function loadTestFileToJsObject(testTemplate: string): any {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"Parameters": {
"FirstParameter": {
"Type": "String"
},
"SecondParameter": {
"Type": "String"
}
},
"Resources": {
"BucketImport": {
"Type": "AWS::S3::Bucket",
"Properties": {
"BucketName": {
"Ref": "FirstParameter"
},
"AccessControl": {
"Ref": "SecondParameter"
}
}
},
"GrandChildStack": {
"Type": "AWS::CloudFormation::Stack",
"Properties": {
"TemplateURL": "https://cfn-templates-set.s3.amazonaws.com/grandchild-import-stack.json",
"Parameters": {
"FirstParameter": {
"Ref": "FirstParameter"
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"Resources": {
"ChildStack": {
"Type": "AWS::CloudFormation::Stack",
"Properties": {
"TemplateURL": "https://cfn-templates-set.s3.amazonaws.com/grandchild-import-stack.json",
"Parameters": {
"FirstParameter": "first-value",
"SecondParameter": "second-value"
}
}
}
}
}

0 comments on commit 9ea8d5c

Please sign in to comment.