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

(aws-ec2): Vpc.from_lookup Does Not Return Subnet IPv4 CIDR Information #11821

Closed
joel-aws opened this issue Dec 2, 2020 · 5 comments · Fixed by #12878
Closed

(aws-ec2): Vpc.from_lookup Does Not Return Subnet IPv4 CIDR Information #11821

joel-aws opened this issue Dec 2, 2020 · 5 comments · Fixed by #12878
Assignees
Labels
@aws-cdk/aws-ec2 Related to Amazon Elastic Compute Cloud bug This issue is a bug. effort/medium Medium work item – several days of effort p1

Comments

@joel-aws
Copy link
Contributor

joel-aws commented Dec 2, 2020

When referencing a VPC from its ID, despite populating the Runtime Context with all the VPC's information (including the subnets' CIDRs), an error is thrown when trying to get the the IPv4 CIDR block of a given subnet.

Reproduction Steps

from aws_cdk import core, aws_ec2 as ec2

class VpcStack(core.Stack):
    def __init__(self, scope: core.Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        vpc = ec2.Vpc.from_lookup(self, "vpc", vpc_id="vpc-002244cc44997733") # Created using CDK
        private_subnet = vpc.private_subnets[0]
        print(private_subnet.subnet_id)  # This returns "subnet-00bb44dd2244dd33"
        print(private_subnet.ipv4_cidr_block)  # This errors out

app = core.App()
VpcStack(app, "vpctest", env={"account": "111122223333", "region": "us-east-1"})

app.synth()

What did you expect to happen?

I expected the subnet's IPv4 CIDR block to be returned, similar to how it would've been returned if the VPC were created (self.vpc = ec2.Vpc(self, "VPC", cidr="10.0.0.0/16", max_azs=3)) and referenced.

What actually happened?

The IPv4 CIDR was not returned; instead the following error was given:

You cannot reference an imported Subnet's IPv4 CIDR if it was not supplied. Add the ipv4CidrBlock when importing using Subnet.fromSubnetAttributes()

Environment

  • CDK CLI Version: 1.75.0
  • Framework Version:
  • Node.js Version: v15.3.0
  • OS: Mac OS 10.15.7
  • Language (Version): Python 3.7.9

This is 🐛 Bug Report

@joel-aws joel-aws added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Dec 2, 2020
@joel-aws joel-aws changed the title (aws-ec): Vpc.from_lookup Does Not Return Subnet IPv4 CIDR Information (aws-ec2): Vpc.from_lookup Does Not Return Subnet IPv4 CIDR Information Dec 2, 2020
@github-actions github-actions bot added the @aws-cdk/aws-ec2 Related to Amazon Elastic Compute Cloud label Dec 2, 2020
@rix0rrr rix0rrr added effort/medium Medium work item – several days of effort p1 labels Dec 7, 2020
@SomayaB SomayaB removed the needs-triage This issue or PR still needs to be triaged. label Dec 7, 2020
@joel-aws
Copy link
Contributor Author

Temporary workaround in a stack when the runtime context for the imported VPC has already been generated:

    def _get_ipv4_cidr(self) -> str:
        """Returns the IPv4 CIDR for a given subnet.

        Temporary fix for: https://github.com/aws/aws-cdk/issues/11821
        """
        try:
            return self.emr_subnet.ipv4_cidr_block
        except:  # noqa
            print("Error getting the subnet via Lookup. Now searching Runtime Context.")
            ctx = json.loads(os.environ["CDK_CONTEXT_JSON"])
            for key in ctx.keys():
                if all(x in key for x in [self._vpc.vpc_id, self.region, self.account]):
                    for subnet_type in ctx[key]["subnetGroups"]:
                        for subnet in subnet_type["subnets"]:
                            if subnet["subnetId"] == self.emr_subnet.subnet_id:
                                return subnet["cidr"]

@aktungmak
Copy link

Hello, any idea when this might be fixed? I tried the workaround but it does not work in our build pipeline since the context is not there.
I looked at the code for other resources that have a from_* factory method (eg SecurityGroup) to see if that could be reused, but I am not familiar with typescript so I didn't get much further unfortunately.

@christophegrall
Copy link

christophegrall commented Feb 2, 2021

Hello @rix0rrr,

In the subnetGroupToSubnets function in https://github.com/aws/aws-cdk/blob/master/packages/%40aws-cdk/aws-ec2/lib/vpc.ts#L1888

the ipv4CidrBlock attribute is missing :

private subnetGroupToSubnets(subnetGroup: cxapi.VpcSubnetGroup): ISubnet[] {
    const ret = new Array<ISubnet>();
    for (let i = 0; i < subnetGroup.subnets.length; i++) {
      const vpcSubnet = subnetGroup.subnets[i];
      ret.push(Subnet.fromSubnetAttributes(this, `${subnetGroup.name}Subnet${i + 1}`, {
        availabilityZone: vpcSubnet.availabilityZone,
        subnetId: vpcSubnet.subnetId,
        routeTableId: vpcSubnet.routeTableId,
  
       //  Add this to fix 
       ipv4CidrBlock: vpcSubnet.cidr
       //

      }));
    }
    return ret;
  }

@mergify mergify bot closed this as completed in #12878 Feb 9, 2021
mergify bot pushed a commit that referenced this issue Feb 9, 2021
When importing a VPC using `Vpc.fromLookup()`, the subnets are properly looked up and saved into the `cdk.context.json`. However, the Subnets object within the imported VPC don't have the CIDR attached and trying to access the subnet CIDR within the code triggers the following error:

> You cannot reference an imported Subnet's IPv4 CIDR if it was not supplied. Add the ipv4CidrBlock when importing using Subnet.fromSubnetAttributes().

This PR fixes the issue.

closes #11821

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
@github-actions
Copy link

github-actions bot commented Feb 9, 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.

TLadd pushed a commit to TLadd/aws-cdk that referenced this issue Feb 9, 2021
When importing a VPC using `Vpc.fromLookup()`, the subnets are properly looked up and saved into the `cdk.context.json`. However, the Subnets object within the imported VPC don't have the CIDR attached and trying to access the subnet CIDR within the code triggers the following error:

> You cannot reference an imported Subnet's IPv4 CIDR if it was not supplied. Add the ipv4CidrBlock when importing using Subnet.fromSubnetAttributes().

This PR fixes the issue.

closes aws#11821

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
NovakGu pushed a commit to NovakGu/aws-cdk that referenced this issue Feb 18, 2021
When importing a VPC using `Vpc.fromLookup()`, the subnets are properly looked up and saved into the `cdk.context.json`. However, the Subnets object within the imported VPC don't have the CIDR attached and trying to access the subnet CIDR within the code triggers the following error:

> You cannot reference an imported Subnet's IPv4 CIDR if it was not supplied. Add the ipv4CidrBlock when importing using Subnet.fromSubnetAttributes().

This PR fixes the issue.

closes aws#11821

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
@Exter-dg
Copy link

If somebody is still using the old version, here is the workaround in typescript:

interface Subnet {
  subnetId: string;
  cidr: string;
}

interface SubnetGroup {
  subnets: Subnet[];
}

interface VpcData {
  vpcId: string;
  subnetGroups: SubnetGroup[];
}

interface ContextData {
  [key: string]: VpcData;
}

...
...

private getIpv4Cidr(vpc: ec2.IVpc, emrSubnet: ec2.ISubnet, region: string, account: string): string {
  try {
    return emrSubnet.ipv4CidrBlock;
  } catch (error) {
    console.error(`Error getting the subnet via Lookup. Error: ${error}`);

    const ctxJson = process.env.CDK_CONTEXT_JSON;
    if (!ctxJson) {
      throw new Error("CDK_CONTEXT_JSON environment variable not found.");
    }

    const ctxData: ContextData = JSON.parse(ctxJson);
    const vpcId = vpc.vpcId;

    for (const key in ctxData) {
      if (key.includes(vpcId) && key.includes(region) && key.includes(account)) {
        const vpcData = ctxData[key];
        for (const subnetGroup of vpcData["subnetGroups"]) {
          for (const subnet of subnetGroup["subnets"]) {
            if(subnet["subnetId"] === emrSubnet.subnetId) {
              console.log("Subnet CIDR: ", subnet["cidr"]);
              return subnet["cidr"];
            }
          }
        }
      }
    }
    console.log("Subnet CIDR not found!!!")
    return ""; // Return empty string if CIDR not found
  }
}

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 bug This issue is a bug. effort/medium Medium work item – several days of effort p1
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants