diff --git a/packages/@aws-cdk/cloudformation-include/lib/cfn-include.ts b/packages/@aws-cdk/cloudformation-include/lib/cfn-include.ts index 318846833a426..2577910e6a035 100644 --- a/packages/@aws-cdk/cloudformation-include/lib/cfn-include.ts +++ b/packages/@aws-cdk/cloudformation-include/lib/cfn-include.ts @@ -584,7 +584,12 @@ export class CfnInclude extends core.CfnElement { return cfnCondition; } - private getOrCreateResource(logicalId: string): core.CfnResource { + private getOrCreateResource(logicalId: string, cycleChain: string[] = []): core.CfnResource { + cycleChain = cycleChain.concat([logicalId]); + if (cycleChain.length !== new Set(cycleChain).size) { + throw new Error(`Found a cycle between resources in the template: ${cycleChain.join(' depends on ')}`); + } + const ret = this.resources[logicalId]; if (ret) { return ret; @@ -618,7 +623,7 @@ export class CfnInclude extends core.CfnElement { if (!(lId in (self.template.Resources || {}))) { return undefined; } - return self.getOrCreateResource(lId); + return self.getOrCreateResource(lId, cycleChain); }, findRefTarget(elementName: string): core.CfnElement | undefined { 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 fb2f4697f610e..a3f55427dbbc9 100644 --- a/packages/@aws-cdk/cloudformation-include/test/invalid-templates.test.ts +++ b/packages/@aws-cdk/cloudformation-include/test/invalid-templates.test.ts @@ -139,6 +139,12 @@ describe('CDK Include', () => { includeTestTemplate(stack, 'short-form-get-att-no-dot.yaml'); }).toThrow(/Short-form Fn::GetAtt must contain a '.' in its string argument, got: 'Bucket1Arn'/); }); + + test('detects a cycle between resources in the template', () => { + expect(() => { + includeTestTemplate(stack, 'cycle-in-resources.json'); + }).toThrow(/Found a cycle between resources in the template: Bucket1 depends on Bucket2 depends on Bucket1/); + }); }); function includeTestTemplate(scope: constructs.Construct, testTemplate: string): inc.CfnInclude { diff --git a/packages/@aws-cdk/cloudformation-include/test/test-templates/invalid/cycle-in-resources.json b/packages/@aws-cdk/cloudformation-include/test/test-templates/invalid/cycle-in-resources.json new file mode 100644 index 0000000000000..61ab0a4b692a2 --- /dev/null +++ b/packages/@aws-cdk/cloudformation-include/test/test-templates/invalid/cycle-in-resources.json @@ -0,0 +1,16 @@ +{ + "Resources": { + "Bucket1": { + "Type": "AWS::S3::Bucket", + "Properties": { + "BucketName": { + "Ref": "Bucket2" + } + } + }, + "Bucket2": { + "Type": "AWS::S3::Bucket", + "DependsOn": "Bucket1" + } + } +}