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.

(CDK): Export changes prevent stack updates

See original GitHub issue

What is the problem?

While creating a multi-stack app I am referring to resources between stacks. The CDK does a great job understanding those relationship automatically and creating an export for me.

However when a change is made in a stack that consumes resources where those resources are no longer used (in my case setting/updating Transit Gateway Routes) which have a level of dynamism based on routing traffic for inspection etc the CDK insists on deleting previous used (but now not) exports in the underlying stack.

This is blocked by CloudFormation which prevents the deletion of the stack. The ‘stack above’ cannot be updated because the ‘stack below’ doesn’t export the resources it needs for the update. Both stacks are effectively ‘locked’ from updates.

Reproduction Steps

Deploy the following with a cdk deploy --all:

#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from '@aws-cdk/core';
import * as ec2 from '@aws-cdk/aws-ec2'

const app = new cdk.App();

// Transit Gateway Stack
class TransitGateway extends cdk.Stack {
    transitGateway: ec2.CfnTransitGateway

    constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
        super(scope, id, props);
        this.transitGateway = new ec2.CfnTransitGateway(this, "TransitGateway", {})
    }
}
const transitGatewayStack = new TransitGateway(app, 'TransitGateway', {});

// 'n' number of VPCs That will eventually use the TGW
class Vpc extends cdk.Stack {
    vpc: ec2.Vpc

    constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
        super(scope, id, props);
        this.vpc = new ec2.Vpc(this, "Vpc", {
            cidr: "10.1.0.0/16",
            subnetConfiguration: [
                {
                    name: "Public",
                    cidrMask: 24,
                    subnetType: ec2.SubnetType.PUBLIC
                },
                {
                    name: "Private",
                    cidrMask: 24,
                    subnetType: ec2.SubnetType.PRIVATE_WITH_NAT
                },
                {
                    name: "TransitGateway",
                    cidrMask: 28,
                    subnetType: ec2.SubnetType.PRIVATE_ISOLATED
                }
            ]
        })
    }
}
const vpcStack = new Vpc(app, "Vpc", {})
// I'm deploying many more VPCs in this stage, along with firewalls, gateway load balancers etc

// Finally have a stack that wires them all together via the TGW
class TransitRoutes extends cdk.Stack {
    constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
        super(scope, id, props);
        const association = new ec2.CfnTransitGatewayVpcAttachment(this, "VpcAttach", {
            transitGatewayId: transitGatewayStack.transitGateway.attrId,
            subnetIds: vpcStack.vpc.selectSubnets({subnetGroupName: "TransitGateway"}).subnetIds,
            vpcId: vpcStack.vpc.vpcId
        })
        vpcStack.vpc.selectSubnets({subnetGroupName: "Public"}).subnets.forEach((subnet, index) => {
            const route = new ec2.CfnRoute(this, `RouteToTGW${index}`, {
                routeTableId: (subnet as ec2.Subnet).routeTable.routeTableId,
                destinationCidrBlock: "10.100.2.0/24",
                transitGatewayId: transitGatewayStack.transitGateway.attrId
            })
            route.node.addDependency(association)
        })
    }
}

const transitRoutesStack = new TransitRoutes(app, "TransitRoutes", {})

After it has deployed successfully. Change line 59 to be Private instead of Public. ie:

vpcStack.vpc.selectSubnets({subnetGroupName: "Private"}).subnets.forEach((subnet, index) => {

Attempt to deploy changes. CDK will attempt to delete the RouteTableID exports for the public subnets in the Vpc Stack. This will be prevented because the TransitGateway Stack depends on them. Neither stack can be updated at this point.

What did you expect to happen?

The CDK would understand a previously used export was possibly / probably still in use and preserve it. I don’t see a lot of value in deleting an existing export? Where an export has been created, I’d expect it to exist for the life-cycle of the stack.

Where that’s not possible some kind of ‘exportAll()’ method on a construct would come in handy!

What actually happened?

CDK insists on deleting the now unused export which locks both stacks up preventing either from being updated.

CDK CLI Version

1.134.0 (build dd5e12d)

Framework Version

No response

Node.js Version

v14.18.1

OS

OSX 11.6.1

Language

Typescript

Language Version

3.9.10

Other information

No response

Issue Analytics

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

github_iconTop GitHub Comments

4reactions
apmcleancommented, Nov 29, 2021

Alright, I think if I’m going to put the effort into naming exports and managing all that between stacks, I’ll just switch to using SSM parameters. Looser coupling. Thanks!

0reactions
github-actions[bot]commented, Nov 29, 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

Resolve the "Export EXPORT_NAME cannot be updated as it ...
You get this error when one or more stacks are importing an exported output value from the stack that you want to update...
Read more >
CDK tips, part 3 – how to unblock cross-stack references
In the first one, you remove the reference from the consuming Stack, while keeping the exports in the producing Stack. Once the updated...
Read more >
How to fix AWS CDK error: “Export [export name] cannot be ...
Go to the AWS CloudFormation console, click Stacks in your top left, then find and click the depending stack that needs to be...
Read more >
Limiting Cross-stack References in CDK - Chariot Solutions
The reason is that when you export a value from one stack and ... bind those stacks tightly together, and can't change that...
Read more >
Deployment Issues with Cross Stack Dependencies and the ...
Since the CDK deploys the exporting stack first, CloudFormation tries to remove the export before the importing stack has removed the Fn:: ...
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