question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

core: Double nested stack outputs not resolved correctly

See original GitHub issue

When multiple stacks are nested inside of each other, accessing resources that depend on parameters doesn’t seem to work correctly. I don’t have a good explanation of what is happening, but I have multiple ways to fix whatever the problem is.

The CloudFormation I’m trying to import that is failing looks like:

root-stack.yaml
       |----------load-balancers.yaml
               |----------load-balancer-stack-1.yaml
               |----------load-balancer-stack-2.yaml
               |----------load-balancer-stack-3.yaml

The problem we’re running into is using the TargetGroup from load-balancer-stack-1.yaml in some new CDK resources.

This is related to https://github.com/aws/aws-cdk/issues/1374

Reproduction Steps

bin/cdk-test.ts:

#!/usr/bin/env node
import { App, Stack } from '@aws-cdk/core';
import { CfnInclude } from '@aws-cdk/cloudformation-include';
import { CfnBucket, Bucket } from '@aws-cdk/aws-s3';

class DoubleNestedStack extends Stack {
  readonly outputBucketName : CfnBucket;

  constructor(scope: App, id: string) {
      super(scope, id);

    const parentTemplate = new CfnInclude(this, 'ParentStack', {
        templateFile: 'parent-stack.yaml',
    });
    const middleTemplate = parentTemplate.loadNestedStack('MiddleStack', {
        templateFile: 'middle-stack.yaml'
    }).includedTemplate;
    const bottomTemplate = middleTemplate.loadNestedStack('BottomStack', {
        templateFile: 'bottom-stack.yaml'
    }).includedTemplate;

    this.outputBucketName = bottomTemplate.getResource('Bucket') as CfnBucket;
  }
}

class OtherStack extends Stack {
    constructor(scope: App, id: string, bucketName: string) {
        super(scope, id);

        const newBucket = new Bucket(this, 'newBucket', {
            bucketName: bucketName
        });
    }
}

const app = new App();
const doubleNestedStack = new DoubleNestedStack(app, 'DoubleNestedStack');
const bucketName = doubleNestedStack.outputBucketName.bucketName as string;
new OtherStack(app, 'OtherStack', bucketName);

parent-stack.yaml:

AWSTemplateFormatVersion: '2010-09-09'

Resources:
  MiddleStack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: 'https://s3.amazonaws.com/this-doesnt-matter.yaml'

middle-stack.yaml:

AWSTemplateFormatVersion: '2010-09-09'

Resources:
  BottomStack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: 'https://s3.amazonaws.com/this-doesnt-matter.yaml'
      Parameters:
        Name: anything

bottom-stack.yaml:

AWSTemplateFormatVersion: '2010-09-09'

Parameters:
  Name:
    Type: String

Resources:
  Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Ref Name

What did you expect to happen?

I expected cdk synth to work and my OtherStack to be able to reference the double nested stack’s resource. (I realize that I’m trying to name an S3 bucket the same thing as another bucket, but that’s not the problem)

[masonme@f45c89b36d13] $ cdk synth
Successfully synthesized to /Users/masonme/cdk-migration-test/cdk.out
Supply a stack id (DoubleNestedStack, OtherStack) to display its template.

What actually happened?

Failure Output:

[masonme@f45c89b36d13] $ cdk synth

/Users/masonme/cdk-migration-test/node_modules/@aws-cdk/core/lib/construct-compat.ts:83

            ^
Error: Cannot use tokens in construct ID: DoubleNestedStackParentStackMiddleStackBottomStackNestedStackBottomStackNestedStackResource43C48F46Outputs.${Token[DoubleNestedStack.ParentStack.MiddleStack.Middl...arentStackMiddleStackBottomStackName8BE86CBFRef.LogicalID.48]}
    at new Construct (/Users/masonme/cdk-migration-test/node_modules/@aws-cdk/core/lib/construct-compat.ts:83:13)
    at new CfnElement (/Users/masonme/cdk-migration-test/node_modules/@aws-cdk/core/lib/cfn-element.ts:57:5)
    at new CfnOutput (/Users/masonme/cdk-migration-test/node_modules/@aws-cdk/core/lib/cfn-output.ts:50:5)
    at createNestedStackOutput (/Users/masonme/cdk-migration-test/node_modules/@aws-cdk/core/lib/private/refs.ts:207:14)
    at resolveValue (/Users/masonme/cdk-migration-test/node_modules/@aws-cdk/core/lib/private/refs.ts:86:25)
    at resolveValue (/Users/masonme/cdk-migration-test/node_modules/@aws-cdk/core/lib/private/refs.ts:87:12)
    at Object.resolveReferences (/Users/masonme/cdk-migration-test/node_modules/@aws-cdk/core/lib/private/refs.ts:30:24)
    at Object.prepareApp (/Users/masonme/cdk-migration-test/node_modules/@aws-cdk/core/lib/private/prepare-app.ts:31:3)
    at Object.synthesize (/Users/masonme/cdk-migration-test/node_modules/@aws-cdk/core/lib/private/synthesis.ts:24:3)
    at App.synth (/Users/masonme/cdk-migration-test/node_modules/@aws-cdk/core/lib/stage.ts:180:23)
Subprocess exited with error 1

cdk synth failed due to CDK using a token in the ID of an internal construct. The code for this ID seems to be here: https://github.com/aws/aws-cdk/blob/7966f8d48c4bff26beb22856d289f9d0c7e7081d/packages/%40aws-cdk/core/lib/private/refs.ts#L204

I’ve found multiple ways to avoid the problem:

  • Change bottom-stack.yaml’s BucketName property to a string instead of a reference to a parameter
  • RemoveOtherStack or its usage of BottomStack’s output

Environment

  • CDK CLI Version : 1.103.0 (build bc13a66)
  • Framework Version: 1.103.0
  • Node.js Version: v14.15.4
  • OS : OS X 10.14.6 (18G9216)
  • Language (Version): TypeScript (Version 4.1.5)

Other


This is 🐛 Bug Report

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:8 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
eladbcommented, Jun 18, 2021

I’ll take a look next week

0reactions
github-actions[bot]commented, Jul 1, 2021

⚠️COMMENT VISIBILITY WARNING⚠️

Comments on closed issues are hard for our team to see. If you need more assistance, please either tag a team member or open a new issue that references this one. If you wish to keep having a conversation with other community members under this issue feel free to do so.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Working with nested stacks - AWS CloudFormation
Nested stacks are stacks created as part of other stacks. You create a nested stack within another stack by using the AWS::CloudFormation::Stack resource....
Read more >
C++ Core Guidelines - GitHub Pages
The C++ Core Guidelines are a set of tried-and-true guidelines, rules, and best practices about coding in C++.
Read more >
Indexer errors and warnings - Azure Cognitive Search
The error information in this article can help you resolve errors, ... Error: Could not map output field 'xyz' to search index due...
Read more >
Snakefiles and Rules — Snakemake 7.19.1 documentation
Most commonly, rules consist of a name, input files, output files, and a shell ... Note that dataset is NOT a wildcard here...
Read more >
Bug listing with status RESOLVED with resolution FIXED as at ...
status:RESOLVED resolution:FIXED severity:normal ... "variable KV not substituted in output of emerge --search linux" status:RESOLVED resolution:FIXED ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found