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

Cannot refer to subnet by name for imported VPC #3650

Closed
2 of 5 tasks
lkoniecz opened this issue Aug 14, 2019 · 15 comments · Fixed by #4090
Closed
2 of 5 tasks

Cannot refer to subnet by name for imported VPC #3650

lkoniecz opened this issue Aug 14, 2019 · 15 comments · Fixed by #4090
Assignees
Labels
@aws-cdk/aws-ec2 Related to Amazon Elastic Compute Cloud bug This issue is a bug.

Comments

@lkoniecz
Copy link

lkoniecz commented Aug 14, 2019

Note: for support questions, please first reference our documentation, then use Stackoverflow. This repository's issues are intended for feature requests and bug reports.

  • I'm submitting a ...

    • 🪲 bug report
    • 🚀 feature request
    • 📚 construct library gap
    • ☎️ security issue or vulnerability => Please see policy
    • ❓ support request => Please see note at the top of this template.
  • What is the current behavior?
    If the current behavior is a 🪲bug🪲: Please provide the steps to reproduce
    Please describe/document how to deploy an L2 construct that has vpc_subnets argument of SubnetSelection type.

Documentation mentions: https://docs.aws.amazon.com/cdk/api/latest/python/aws_cdk.aws_ec2/SubnetSelection.html
subnet_name, but it is unclear what it really is. Subnet (neither Cfn nor L2 construct ) does not have a subnet_name property.

I wasnt able to make it work, always getting
jsii.errors.JSIIError: There are no subnets named 'xxxx' in this VPC. Use a different VPC subnet selection.

Example code piece:

vpc = aws_ec2.Vpc.from_lookup(
    scope=self,
    id='dev-eks-vpc',
    is_default=False,
    tags={
        'aws:cloudformation:stack-name':'dev-eks-vpc'
    }
)

eks_cluster = aws_eks.Cluster(
    scope=self,
    id='EksCluster',
    vpc=vpc,
    vpc_subnets=[aws_ec2.SubnetSelection(subnet_type=aws_ec2.SubnetType.PRIVATE)],
    cluster_name='EksCluster-dev',
    version='1.12'
)

eks_autoscaling_group = eks_cluster.add_capacity(
    id='EksClusterAsg',
    instance_type='m5.large',
    desired_capacity=2,
    vpc_subnets=aws_ec2.SubnetSelection(subnet_name='dev-eks-vpc/DevEksVpc/PrivateSubnet2')
)

for subnet_name I tried what's under Name tag, logical id and physical id. None works

  • What is the expected behavior (or behavior of feature suggested)?
    Document how to deploy resources in certain subnets.

  • What is the motivation / use case for changing the behavior or adding this feature?
    It's quite clear users want to have an abiility to control where are the resources deployed.

  • Please tell us about your environment:

    • CDK CLI Version: 1.3.0
    • Module Version: 1.3.0
    • OS: [all]
    • Language: [all]
  • Other information (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. associated pull-request, stackoverflow, gitter, etc)
    Cannot get subnets from a previously deployed VPC #2393
    VpcPlacement: allow picking subset of subnets #1577

@lkoniecz lkoniecz added the needs-triage This issue or PR still needs to be triaged. label Aug 14, 2019
@lkoniecz lkoniecz changed the title Explain hot to deploy a resource in single subnet Explain how to deploy a resource in certain subnet Aug 14, 2019
@eladb
Copy link
Contributor

eladb commented Aug 14, 2019

Can you please provide a code snippet for reproduction?

@eladb eladb added the response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days. label Aug 14, 2019
@lkoniecz
Copy link
Author

lkoniecz commented Aug 14, 2019

@eladb
I attached code snipped.
Basically any combination of a vpc and a resource with vpc_subnets will do.

@rix0rrr
Copy link
Contributor

rix0rrr commented Aug 20, 2019

The subnet name is the name of group of subnets created using the subnetConfiguration option when creating the subnet. This is done in order to distinguish between different groups of subnets of the same type (for example, you might have 2 or more Private subnet groups).

Since in this case you're looking up the VPC instead of creating it, it will read the subnet names from some tags that the CDK VPC provisioner would put on it.

If no names are specified or found on the subnet tags, the names will be "Public", "Private" or "Isolated" depending on the subnet type.

@rix0rrr
Copy link
Contributor

rix0rrr commented Aug 20, 2019

You should probably select subnets by type, unless you know you have a reason to use names.

@lkoniecz
Copy link
Author

lkoniecz commented Aug 20, 2019

@rix0rrr

I am having troubles to make it work though, as subnet_configuration is applied for each AZ and carries the same data. For instance:

subnet_configs = [aws_ec2.SubnetConfiguration(name='PrivateName', subnet_type=aws_ec2.SubnetType.PRIVATE), aws_ec2.SubnetConfiguration(name='PublicName', subnet_type=aws_ec2.SubnetType.PUBLIC)]

vpc = aws_ec2.Vpc(
    scope=self,
    id=app.env_agnostic_resource_id(VPC_ID),
    cidr=app.get_param('Vpc', 'Cidr'),
    subnet_configuration=subnet_configs
)

adds aws-cdk:subnet-name = PrivateName to each private subnet.

Is it possible to name subnets individually?

for child in vpc.node.children:
    if isinstance(child, aws_ec2.
        core.Tag.add(child, 'aws-cdk:subnet-name', 'some_unique_value')

Following code does tag the subnets, but tags values are not respected by subnet_selection

@lkoniecz
Copy link
Author

@rix0rrr

I also confirm that this freature does not work for imported vpc. Whatever the data original vpc object carries is lost when vpc is imported and subnet name-based selection does not work.

I don't really want to go with Cfn* resources as so much work is done behind the scenes. Do you guys plan to make it work someday?

@stefanolczak
Copy link

stefanolczak commented Aug 20, 2019

Me and author of the issue are struggling with the same issue so I have debugged it and here are my findings:
I guess there is a bug in CDK that prevents from correctly receiving information of imported vpc when only subnet name is selected in SubnetSelection. This is possibly caused by missing privateSubnetNames and publicSubnetNames in DUMMY_VPC_PROPS :

/**
* There are returned when the provider has not supplied props yet
*
* It's only used for testing and on the first run-through.
*/
const DUMMY_VPC_PROPS: cxapi.VpcContextResponse = {
availabilityZones: ['dummy-1a', 'dummy-1b'],
vpcId: 'vpc-12345',
publicSubnetIds: ['s-12345', 's-67890'],
publicSubnetRouteTableIds: ['rtb-12345s', 'rtb-67890s'],
privateSubnetIds: ['p-12345', 'p-67890'],
privateSubnetRouteTableIds: ['rtb-12345p', 'rtb-57890p'],
};

So the CDK CLI doesn't try to fetch the missing context ( subnet names ) and just stop with an error after first run-through.

@rix0rrr rix0rrr changed the title Explain how to deploy a resource in certain subnet Cannot refer to subnet by name for imported VPC Aug 28, 2019
@rix0rrr rix0rrr added bug This issue is a bug. @aws-cdk/aws-ec2 Related to Amazon Elastic Compute Cloud service/vpc and removed response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days. needs-triage This issue or PR still needs to be triaged. labels Aug 28, 2019
@rix0rrr
Copy link
Contributor

rix0rrr commented Aug 28, 2019

You cannot pick individual subnets using the subnet selection mechanism, you just refer to subnet groups, which is a set of subnets of the same type spreading across all AZs.

Apparently there is a bug for imported subnets which prevents this from working completely.

We will look into this, but in the mean time the best way around this is probably to use the escape hatch mechanism.

@lkoniecz
Copy link
Author

@rix0rrr

Could you throw some light on how to utilize the escape hatch mechs in this case?

@rix0rrr
Copy link
Contributor

rix0rrr commented Aug 29, 2019

You will have to know the subnet IDs, and override the CloudFormation resource properties to use exactly those IDs.

rix0rrr added a commit that referenced this issue Sep 16, 2019
Looked-up VPCs are created with a dummy configuration before the first
lookup happens; a `selectSubnets` call on the dummy configuration is
likely to fail.

Add an exception to make the initial lookup not fail.

Fixes #3650.
rix0rrr added a commit that referenced this issue Sep 18, 2019
Looked-up VPCs are created with a dummy configuration before the first
lookup happens; a `selectSubnets` call on the dummy configuration is
likely to fail.

Add an exception to make the initial lookup not fail.

Fixes #3650.
eladb pushed a commit that referenced this issue Sep 23, 2019
Looked-up VPCs are created with a dummy configuration before the first
lookup happens; a `selectSubnets` call on the dummy configuration is
likely to fail.

Add an exception to make the initial lookup not fail.

Fixes #3650.
@Flood-ctrl
Copy link

Flood-ctrl commented Nov 4, 2019

Hello, how it's going? Sorry if I've places this message in the wrong thread, but I still not able to attach subnets to EC2 instance by using subnet selection provided by aws_ec2.ec2.Instance from imported vpc (ec2.Vpc.from_lookup). The one way at this time it's using the ec2.CfnInstance class and defining subnet_id directly.
Thank you.

@kiros-sc
Copy link

kiros-sc commented Apr 2, 2020

@Flood-ctrl did you try something like this:

const vpc = ec2.Vpc.fromLookup(this, "vpc", {
          vpcName: "lalainfra/vpc",
        });
      
const lalaInstance = new ec2.Instance(this, 'lalaServiceInstance',{
          vpc,
          vpcSubnets: {subnetName: "public"},
          // vpcSubnets: cdk.Fn.importValue("public"),

I my code I imported the vpc, and when using this line of code "vpcSubnets: {subnetName: "public"}," I got an error of _"vpcId of undefined", something like that, and believe or not by executing the cdk synth using this "vpcSubnets: cdk.Fn.importValue("public")", which did bring info, but incorrect, and then running again the synth but using "vpcSubnets: {subnetName: "public"}" fixed the issue.

My steps:

  1. execute "cdk synth" with this line >> "vpcSubnets: cdk.Fn.importValue("public")" -brings incorrect data.
  2. execute "cdk synth" again with the correct code line >> "vpcSubnets: {subnetName: "public"}".

It's not a fix, but works, so for now... I'll stick with that.

@dassowmd
Copy link

dassowmd commented Apr 17, 2020

Is this issue fixed? I am still having the same problem when I try to import a VPC and then lookup a subnet by name. My organization has a private subnet that I can't use, so I can't just grab the private subnet Type.

vpc = ec2.Vpc.from_lookup(self, "VPC", vpc_name='my_vpc_name') vpc_subnets=ec2.SubnetSelection(subnet_group_name='my_subnet_group_name')
The above code fails with an error of Cannot read property 'subnetID' of undefined.

However, if instead first comment out the subnet_group_name and instead use subnet type it will populate my cdk.context.json when I do a cdk synth
vpc = ec2.Vpc.from_lookup(self, "VPC", vpc_name='my_vpc_name') \#vpc_subnets=ec2.SubnetSelection(subnet_group_name='my_subnet_group_name') vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PRIVATE

From that point I can uncomment the group_name_lookup and remove the type lookup and the synth will complete successfully.

Because I deploy this code to different regions and environments I am not able to commit my cdk.context.json to my repo. Unless there is a way to do that without breaking each time I deploy to a new env/region?

@adrian-skybaker
Copy link

adrian-skybaker commented Aug 7, 2022

Trying to decipher why this is closed - alternatives to lookup by subnet name are suggested (look up by group name, look up by subnet id), but it's still not possible that I can see to refer to a subnet by name, which was the original issue.

Use case: trying to use CDK with non-CDK managed subnets that have no tagging, but have predictable name formats.

@kishiel
Copy link
Contributor

kishiel commented Jan 3, 2024

I've spent the past few days working around this issue, and I agree that this issue should not be closed because subnet import by subnet name is not a supported action when using ISubnet.fromAttributes or SubnetSelection. Subnet groups, however, can be imported by name via SubnetSelection.

The functionality to import a subnet by group name can get you what you want provided you don't actually care about subnet group names. I was able to piece together the puzzle loosely described by the importing-an-existing-vpc documentation. This is accomplished by setting a couple of tags (described below).

  1. Create a custom resource which executes a lambda directly
  2. The lambda takes a vpc-id as an input and to describes the subnets of the vpc
  3. Each subnet is tagged with two name tag keys: aws-cdk:subnet-name and Name. aws-cdk:subnet-name will be used by the subnetGroupName when performing a SubnetSelection. Name is what appears in the VPC UI's Name column.
  4. Each subnet is also tagged with aws-cdk:subnet-type to enable import by subnet type Public/Private via SubnetSelection.
  5. Once this custom resource is deployed an updated cdk.context.json is rendered for the bootstrapped VPC which will include the subnetGroup for each subnet, and a unique name for each. You can import these via:
      let _subnets: ec2.ISubnet[] = [];
      vpc.availabilityZones.forEach((az) => {
        _subnets.push(
          ...vpc.selectSubnets({
            subnetGroupName: `some-expected-name-in-${az}`,
          }).subnets,
        );
      });

This example names the aws-cdk:subnet-name value uniquely, but you don't have to. You can use other SubnetSelection filters to limit on attributes such as availability zone.

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.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

10 participants