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

Cross stack vpc causes unresolved resource dependencies error #4474

Closed
Lightning303 opened this issue Oct 11, 2019 · 6 comments · Fixed by #5211
Closed

Cross stack vpc causes unresolved resource dependencies error #4474

Lightning303 opened this issue Oct 11, 2019 · 6 comments · Fixed by #5211
Assignees
Labels
@aws-cdk/aws-ec2 Related to Amazon Elastic Compute Cloud @aws-cdk/aws-elasticloadbalancing Related to Amazon Elastic Load Balancing bug This issue is a bug. cross-stack Related to cross-stack resource sharing in-progress This issue is being actively worked on. p1

Comments

@Lightning303
Copy link

Lightning303 commented Oct 11, 2019

Hi,
creating a vpc in a child stack (not nested), and creating some resources, that depend on the vpc, in another child stack will result in a ValidationError.
I was able to reproduce this with application loadbalancers (only internet facing) aswell as an aurora cluster (public and private).

Reproduction Steps

import cdk = require('@aws-cdk/core');
import { NetworkStack } from './Network-stack';
import { InstancesStack } from './Instances-stack';

export class TestStack extends cdk.Stack {
    constructor(scope: cdk.App, id: string, props: cdk.StackProps) {
        super(scope, id, props);
        const network = new NetworkStack(this, "NetworkStack", props);

        new InstancesStack(this, "Instances", {
            env: props.env,
            network: network
        });
    }
}
import cdk = require('@aws-cdk/core');
import ec2 = require('@aws-cdk/aws-ec2');

export class NetworkStack extends cdk.Stack {
    public readonly vpc: ec2.Vpc;

    constructor(scope: cdk.Stack, id: string, props: cdk.StackProps) {
        super(scope, id, props);

        this.vpc = new ec2.Vpc(this, "vpc", {
            cidr: "10.0.0.0/16",
            maxAzs: 3,
            subnetConfiguration: [
                {
                    cidrMask: 20,
                    subnetType: ec2.SubnetType.PRIVATE,
                    name: "subnet-private"
                },
                {
                    cidrMask: 20,
                    subnetType: ec2.SubnetType.PUBLIC,
                    name: "subnet-public"
                }
            ],
            natGateways: 2
        });
    }
}
import cdk = require('@aws-cdk/core'); 
import loadbalancer = require('@aws-cdk/aws-elasticloadbalancingv2');
import { NetworkStack } from './Network-stack';
 
export interface theseProps extends cdk.StackProps { 
    network: NetworkStack
} 
 
export class InstancesStack extends cdk.Stack {
 
    constructor(scope: cdk.Stack, id: string, props: theseProps) { 
        super(scope, id, props);
        
        new loadbalancer.ApplicationLoadBalancer(this, "testLB", {
            vpc: props.network.vpc,
            internetFacing: true
        });
    } 
}

Error Log

cdk deploy *
TestStack
TestStack: deploying...
TestStack: creating CloudFormation changeset...

 ✅  TestStack (no changes)

Stack ARN:
arn:aws:cloudformation:eu-west-1:123456789:stack/TestStack/f7358b50-ec24-11e9-8e0e-02c03455965c
TestStackNetworkStackE68E9FD0
TestStackNetworkStackE68E9FD0: deploying...
TestStackNetworkStackE68E9FD0: creating CloudFormation changeset...
...

 ✅  TestStackNetworkStackE68E9FD0

Outputs:
TestStackNetworkStackE68E9FD0.ExportsOutputRefvpcsubnetpublicSubnet1SubnetF125D982384FC8F2 = subnet-05bb64c9b53308b7c
TestStackNetworkStackE68E9FD0.ExportsOutputRefvpcA2121C384D1B3CDE = vpc-02997d94566f805bf
TestStackNetworkStackE68E9FD0.ExportsOutputRefvpcsubnetpublicSubnet2Subnet2731CC5E2E3D2FF3 = subnet-0b862d79b52959ec6
TestStackNetworkStackE68E9FD0.ExportsOutputRefvpcsubnetpublicSubnet3Subnet7494E9BC8FCFC236 = subnet-03944fc3ed16a79b4

Stack ARN:
arn:aws:cloudformation:eu-west-1:123456789:stack/TestStackNetworkStackE68E9FD0/2d351770-ec25-11e9-9415-06982f8c16e4
TestStackInstancesF0B37D31
TestStackInstancesF0B37D31: deploying...
TestStackInstancesF0B37D31: creating CloudFormation changeset...

 ❌  TestStackInstancesF0B37D31 failed: ValidationError: Template format error: Unresolved resource dependencies [vpcsubnetpublicSubnet3DefaultRoute3905C18B, vpcsubnetpublicSubnet2DefaultRoute7436D83A, vpcsubnetpublicSubnet1Defau
ltRouteA1448C8B] in the Resources block of the template
Template format error: Unresolved resource dependencies [vpcsubnetpublicSubnet3DefaultRoute3905C18B, vpcsubnetpublicSubnet2DefaultRoute7436D83A, vpcsubnetpublicSubnet1DefaultRouteA1448C8B] in the Resources block of the template  

Environment

  • CLI Version : 1.16.232
  • Framework Version: 1.12.0
  • OS : Windows 10
  • Language : TypeScript

This is 🐛 Bug Report

@Lightning303 Lightning303 added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Oct 11, 2019
@NGL321 NGL321 added @aws-cdk/aws-ec2 Related to Amazon Elastic Compute Cloud @aws-cdk/aws-elasticloadbalancing Related to Amazon Elastic Load Balancing package/vpc needs-reproduction This issue needs reproduction. and removed needs-triage This issue or PR still needs to be triaged. labels Oct 11, 2019
@SomayaB SomayaB added the cross-stack Related to cross-stack resource sharing label Oct 23, 2019
@rix0rrr rix0rrr added the p1 label Oct 24, 2019
@zxkane
Copy link
Contributor

zxkane commented Oct 29, 2019

This is a blocking issue to organize large infra by nested stacks. Any fix ETA?

@rix0rrr
Copy link
Contributor

rix0rrr commented Oct 30, 2019

Unfortunately we don't have an ETA yet. To work around issues this problem is causing for you, you can try using the escape hatch mechanism.

@cmckni3
Copy link
Contributor

cmckni3 commented Nov 15, 2019

I ran into this issue as well. It seems like it has something to do with Stacks being initialized inside of other Stacks.

@eladb
Copy link
Contributor

eladb commented Nov 27, 2019

Apologies for the confusion, managed to reproduce this in 1.18.0:

import { Stack, App } from '@aws-cdk/core';
import ec2 = require('@aws-cdk/aws-ec2');
import elb = require('@aws-cdk/aws-elasticloadbalancingv2');

const app = new App();

const root = new Stack(app, 'Root');

const stack1 = new Stack(root, 'Network');
const vpc = new ec2.Vpc(stack1, 'Vpc');

const stack2 = new Stack(root, 'Instances');
new elb.ApplicationLoadBalancer(stack2, 'LoadBalancer', { 
  vpc, 
  internetFacing: true 
});

app.synth();

Validated that this is going to be resolved by #5211

@SomayaB SomayaB added in-progress This issue is being actively worked on. and removed needs-reproduction This issue needs reproduction. labels Nov 27, 2019
@mergify mergify bot closed this as completed in #5211 Nov 29, 2019
mergify bot pushed a commit that referenced this issue Nov 29, 2019
* fix(cloudformation): dependencies across nested stack boundaries

When adding dependencies of any kind (`node.addDependency`, `stack.addDependency` or `cfnResource.addDependsOn`), we now take nested stacks into account and transfer the dependency to the lowest common scope (either a common stack or the assembly).

This is primarily implemented in `cfnResource.addDependsOn` and `stack.addDependency` through the following algorithm:

- Lookup the lowest common stack
- If not found, apply the dependency at the assembly level (between two top-level stacks).
- If found, identify the two CloudFormation resources which represent this relationship within the scope of the common stack (this could be the actual resource if they are both in the same stack or the `AWS::CloudFormation::Stack` resource if the source or target are with in a nested stack).
- Apply the dependency at the CloudFormation level (add `DependsOn`).

There are a bunch of edge cases as well.

To be able to find the AWS::CloudFormation::Stack resource for nested stacks, the `nestedStackResource` property was added to `core.Stack` and assigned by `NestedStack`. It seems like we should probably move `NestedStack` from the `aws-cloudformation` module and into `core` since there is too much coupling right now.

Created a thorough test suite to examine various cases under `test.deps.ts`. Note that this suite includes tests for nested stacks and for regular cases, but decided to put them all in a single suite to make it easier to reason about coverage.

Fixes #4460

* validate #4474

* combine stack and resource deps into a single algorithm

- Rewrote the `addDependency` algorithm generically to support defining dependencies between two resources or two stacks.
- Added a cache for `Stack.of` which is expected to have some nice gains since this method is widely used, especially around these algorithms.

* rename `parentStack` to `nestedStackParent`

* hide the Stack.of cache property

* convert nestedStackParent to a getter

* fix compilation error
@cmckni3
Copy link
Contributor

cmckni3 commented Dec 5, 2019

@eladb is this set for a 1.19.0 release?

@cmckni3
Copy link
Contributor

cmckni3 commented Dec 9, 2019

I can confirm this is fixed in master. I did a full build and linked dependencies into a project last night.

cdk deploy worked perfectly with cross stack VPCs. No more template reference error could not reference MyAppVPCRoute. 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
@aws-cdk/aws-ec2 Related to Amazon Elastic Compute Cloud @aws-cdk/aws-elasticloadbalancing Related to Amazon Elastic Load Balancing bug This issue is a bug. cross-stack Related to cross-stack resource sharing in-progress This issue is being actively worked on. p1
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants