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

feat(aws-ec2): add VPC context provider #1168

Merged
merged 9 commits into from
Nov 15, 2018
Merged

Conversation

rix0rrr
Copy link
Contributor

@rix0rrr rix0rrr commented Nov 14, 2018

Add a context provider for looking up existing VPCs in an account. This
is useful if the VPC is defined outside of your CDK app, such as in a
different CDK app, by hand or in a CloudFormation template.

Addresses some need of #1095.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license.

@rix0rrr rix0rrr requested review from eladb and moofish32 November 14, 2018 10:48
Add a context provider for looking up existing VPCs in an account. This
is useful if the VPC is defined outside of your CDK app, such as in a
different CDK app, by hand or in a CloudFormation template.

Addresses some need of #1095.
@rix0rrr rix0rrr force-pushed the huijbers/vpc-context branch from 89d5266 to 631eeb1 Compare November 14, 2018 10:56
#### Sharing VPCs across stacks

If you are creating multiple `Stack`s inside the same CDK application,
you can reuse a VPC from one Stack in another by using `export()` and
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"to another"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I don't think that's correct.

@@ -0,0 +1,21 @@
export const VPC_PROVIDER = 'vpc-provider';

export interface VpcContextQuery {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doc?

const tags: {[key: string]: string} | undefined = args.tags;
const isDefault: boolean | undefined = args.isDefault;

// Builter request filter
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Build


// Builter request filter
const filters: AWS.EC2.Filter[] = [];
if (vpcId) { filters.push({ Name: 'vpc-id', Values: [vpcId] }); }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just expose the filters API in the context provider API and move the logic of building the filters to the construct library?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rix0rrr might still be recovering from when I used the word filter and he really didn't like it, but this context is different and I won't give him too hard a time if filter comes back.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess I wanted as narrow an API as possible. But yeah, I suppose it makes it easier to add features in the future.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just feels like we can expose this to the user and give them more power without sacrificing too much usability (maybe we can add a bunch of sugar methods for the common use cases)

azs.sort();

const subnets: Subnet[] = listedSubnets.map(subnet => {
let type = getTag('aws-cdk:SubnetType', subnet.Tags);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we try to standardize around something like aws:cdk:subnet-type

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we set an aws: tag? or does it have to be aws-cdk?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't believe we can set the aws: tag.

// - Type tag, we tag subnets with their type
// - Name tag, we tag subnets with their subnet group name
// - MapPublicIpOnLaunch in absence of tags => must be a Public subnet, anything else is either Isolated or Private

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also mention that"type" is used as a name if we don't have a name tag

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The actual source of truth for this is the route table. I was thinking the logic would be check for our Type tag and trust that CDK is the source of truth if it exists. If that is not there pull the route tables. If a route exists to an IGW (public), only NAT (private), neither (isolated). Yes there are egress only gateways and I'm not sure if those are public or private, my vote is private.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know, but that seemed like overcomplicating.

So for non-CDK-exported VPCs we only support public/private nets, for CDK-exported VPCs we support isolated subnets as well. Seems like a fair compromise.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I happen to know my legacy VPCs do not set MapPublicIpOnLaunch to true for public subnets. I'm not positive if it was a secure by default argument or a non-repudiation (the non EIP public IPs are never in Cloud Trail). I do agree this is more complicated, and if we launch without it and let the community drive the request I'm probably ok.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would argue in those cases you can always add the tags manually.

Copy link
Contributor

@moofish32 moofish32 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small comments, but my big question is should route table be the subnet type source of truth.

const SUBNETTYPE_TAG = 'aws-cdk:SubnetType';
const SUBNETNAME_TAG = 'aws-cdk:SubnetName';

function subnetTypeTagValue(type: SubnetType) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes me think we should have used String enums for this type.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe so. It's not too onerous to have this function I think.


// Builter request filter
const filters: AWS.EC2.Filter[] = [];
if (vpcId) { filters.push({ Name: 'vpc-id', Values: [vpcId] }); }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rix0rrr might still be recovering from when I used the word filter and he really didn't like it, but this context is different and I won't give him too hard a time if filter comes back.

// - Type tag, we tag subnets with their type
// - Name tag, we tag subnets with their subnet group name
// - MapPublicIpOnLaunch in absence of tags => must be a Public subnet, anything else is either Isolated or Private

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The actual source of truth for this is the route table. I was thinking the logic would be check for our Type tag and trust that CDK is the source of truth if it exists. If that is not there pull the route tables. If a route exists to an IGW (public), only NAT (private), neither (isolated). Yes there are egress only gateways and I'm not sure if those are public or private, my vote is private.

azs.sort();

const subnets: Subnet[] = listedSubnets.map(subnet => {
let type = getTag('aws-cdk:SubnetType', subnet.Tags);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we set an aws: tag? or does it have to be aws-cdk?

/**
* Group subnets of the same type together, and order by AZ
*/
function groupSubnets(subnets: Subnet[]): SubnetGroups {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 have to sort these

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not even optional :)

Purpose: 'WebServices'
}
});
const vpc = VpcNetworkRef.import(this, 'VPC', provider.vpcProps);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also include the VpcNetwork.importFromContext usage in this example?


/**
* Properties for looking up an existing VPC.
*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reference AWS docs page that describes the query API

}

// These values will be used to recover the config upon provider import
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mention the name of the context provider class here

* Query region
*/
region?: string;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not, though I suppose I could model it differently.

* Query region
*/
region?: string;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would put this under filters: any[] to avoid the need to define this in 100% places.


// Builter request filter
const filters: AWS.EC2.Filter[] = [];
if (vpcId) { filters.push({ Name: 'vpc-id', Values: [vpcId] }); }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just feels like we can expose this to the user and give them more power without sacrificing too much usability (maybe we can add a bunch of sugar methods for the common use cases)

@rix0rrr rix0rrr merged commit e8380fa into master Nov 15, 2018
@rix0rrr rix0rrr deleted the huijbers/vpc-context branch November 15, 2018 14:41
@NGL321 NGL321 added the contribution/core This is a PR that came from AWS. label Sep 27, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
contribution/core This is a PR that came from AWS.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants